sisyphi 0.1.2 → 0.1.3

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.
Files changed (73) hide show
  1. package/dist/{chunk-FWHTKXN5.js → chunk-N2BPQOO2.js} +23 -3
  2. package/dist/chunk-N2BPQOO2.js.map +1 -0
  3. package/dist/cli.js +85 -162
  4. package/dist/cli.js.map +1 -1
  5. package/dist/daemon.js +603 -186
  6. package/dist/daemon.js.map +1 -1
  7. package/dist/templates/CLAUDE.md +50 -0
  8. package/dist/templates/agent-plugin/.claude/agents/debug.md +39 -0
  9. package/dist/templates/agent-plugin/.claude/agents/plan.md +101 -0
  10. package/dist/templates/agent-plugin/.claude/agents/review-plan.md +81 -0
  11. package/dist/templates/agent-plugin/.claude/agents/review.md +56 -0
  12. package/dist/templates/agent-plugin/.claude/agents/spec-draft.md +73 -0
  13. package/dist/templates/agent-plugin/.claude/agents/test-spec.md +56 -0
  14. package/dist/templates/agent-plugin/.claude-plugin/plugin.json +5 -0
  15. package/dist/templates/agent-plugin/agents/CLAUDE.md +52 -0
  16. package/dist/templates/agent-plugin/agents/debug.md +39 -0
  17. package/dist/templates/agent-plugin/agents/operator.md +56 -0
  18. package/dist/templates/agent-plugin/agents/plan.md +101 -0
  19. package/dist/templates/agent-plugin/agents/review-plan.md +81 -0
  20. package/dist/templates/agent-plugin/agents/review.md +56 -0
  21. package/dist/templates/agent-plugin/agents/spec-draft.md +73 -0
  22. package/dist/templates/agent-plugin/agents/test-spec.md +56 -0
  23. package/dist/templates/agent-suffix.md +3 -1
  24. package/dist/templates/banner.txt +24 -6
  25. package/dist/templates/orchestrator-plugin/.claude/commands/begin.md +62 -0
  26. package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/SKILL.md +40 -0
  27. package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/task-patterns.md +222 -0
  28. package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/workflow-examples.md +208 -0
  29. package/dist/templates/orchestrator-plugin/.claude-plugin/plugin.json +5 -0
  30. package/dist/templates/orchestrator-plugin/hooks/hooks.json +25 -0
  31. package/dist/templates/orchestrator-plugin/scripts/block-task.sh +4 -0
  32. package/dist/templates/orchestrator-plugin/scripts/stop-suggest.sh +4 -0
  33. package/dist/templates/orchestrator-plugin/skills/git-management/SKILL.md +111 -0
  34. package/dist/templates/orchestrator-plugin/skills/orchestration/SKILL.md +40 -0
  35. package/dist/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +248 -0
  36. package/dist/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +237 -0
  37. package/dist/templates/orchestrator-settings.json +2 -0
  38. package/dist/templates/orchestrator.md +56 -49
  39. package/dist/templates/resources/.claude/agents/debug.md +39 -0
  40. package/dist/templates/resources/.claude/agents/plan.md +101 -0
  41. package/dist/templates/resources/.claude/agents/review-plan.md +81 -0
  42. package/dist/templates/resources/.claude/agents/review.md +56 -0
  43. package/dist/templates/resources/.claude/agents/spec-draft.md +73 -0
  44. package/dist/templates/resources/.claude/agents/test-spec.md +56 -0
  45. package/dist/templates/resources/.claude/commands/begin.md +62 -0
  46. package/dist/templates/resources/.claude/skills/orchestration/SKILL.md +40 -0
  47. package/dist/templates/resources/.claude/skills/orchestration/task-patterns.md +222 -0
  48. package/dist/templates/resources/.claude/skills/orchestration/workflow-examples.md +208 -0
  49. package/dist/templates/resources/.claude-plugin/plugin.json +8 -0
  50. package/package.json +2 -2
  51. package/templates/CLAUDE.md +50 -0
  52. package/templates/agent-plugin/.claude-plugin/plugin.json +5 -0
  53. package/templates/agent-plugin/agents/CLAUDE.md +52 -0
  54. package/templates/agent-plugin/agents/debug.md +39 -0
  55. package/templates/agent-plugin/agents/operator.md +56 -0
  56. package/templates/agent-plugin/agents/plan.md +101 -0
  57. package/templates/agent-plugin/agents/review-plan.md +81 -0
  58. package/templates/agent-plugin/agents/review.md +56 -0
  59. package/templates/agent-plugin/agents/spec-draft.md +73 -0
  60. package/templates/agent-plugin/agents/test-spec.md +56 -0
  61. package/templates/agent-suffix.md +3 -1
  62. package/templates/banner.txt +24 -6
  63. package/templates/orchestrator-plugin/.claude-plugin/plugin.json +5 -0
  64. package/templates/orchestrator-plugin/hooks/hooks.json +25 -0
  65. package/templates/orchestrator-plugin/scripts/block-task.sh +4 -0
  66. package/templates/orchestrator-plugin/scripts/stop-suggest.sh +4 -0
  67. package/templates/orchestrator-plugin/skills/git-management/SKILL.md +111 -0
  68. package/templates/orchestrator-plugin/skills/orchestration/SKILL.md +40 -0
  69. package/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +248 -0
  70. package/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +237 -0
  71. package/templates/orchestrator-settings.json +2 -0
  72. package/templates/orchestrator.md +56 -49
  73. package/dist/chunk-FWHTKXN5.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/daemon/index.ts","../src/shared/config.ts","../src/daemon/server.ts","../src/daemon/session-manager.ts","../src/daemon/state.ts","../src/daemon/orchestrator.ts","../src/daemon/tmux.ts","../src/daemon/colors.ts","../src/daemon/agent.ts","../src/daemon/pane-monitor.ts"],"sourcesContent":["import { mkdirSync, readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs';\nimport { globalDir, daemonPidPath, statePath } from '../shared/paths.js';\nimport { loadConfig } from '../shared/config.js';\nimport { startServer, stopServer, registerSessionCwd, loadSessionRegistry } from './server.js';\nimport { startMonitor, stopMonitor, setRespawnCallback } from './pane-monitor.js';\nimport { onAllAgentsDone } from './session-manager.js';\n\nfunction ensureDirs(): void {\n mkdirSync(globalDir(), { recursive: true });\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction acquirePidLock(): void {\n const pidFile = daemonPidPath();\n try {\n const existing = parseInt(readFileSync(pidFile, 'utf-8').trim(), 10);\n if (existing && isProcessAlive(existing)) {\n console.error(`[sisyphus] Daemon already running (pid ${existing}). Kill it first or remove ${pidFile}`);\n process.exit(1);\n }\n } catch {\n // No pidfile or unreadable — proceed\n }\n writeFileSync(pidFile, String(process.pid), 'utf-8');\n}\n\nfunction releasePidLock(): void {\n try {\n unlinkSync(daemonPidPath());\n } catch {\n // Already gone\n }\n}\n\nfunction recoverSessions(): void {\n const registry = loadSessionRegistry();\n const entries = Object.entries(registry);\n\n if (entries.length === 0) {\n console.log('[sisyphus] No sessions to recover');\n return;\n }\n\n let recovered = 0;\n for (const [sessionId, cwd] of entries) {\n const stateFile = statePath(cwd, sessionId);\n if (!existsSync(stateFile)) {\n continue;\n }\n\n try {\n const session = JSON.parse(readFileSync(stateFile, 'utf-8')) as { status: string };\n if (session.status === 'active' || session.status === 'paused') {\n registerSessionCwd(sessionId, cwd);\n recovered++;\n }\n } catch {\n console.error(`[sisyphus] Failed to read session state for ${sessionId}, skipping`);\n }\n }\n\n console.log(`[sisyphus] Recovered ${recovered} session(s) from registry`);\n}\n\nasync function main(): Promise<void> {\n console.log('[sisyphus] Starting daemon...');\n ensureDirs();\n acquirePidLock();\n\n const config = loadConfig(process.cwd());\n\n setRespawnCallback(onAllAgentsDone);\n\n await startServer();\n startMonitor(config.pollIntervalMs);\n\n recoverSessions();\n\n const shutdown = async () => {\n console.log('[sisyphus] Shutting down...');\n stopMonitor();\n await stopServer();\n releasePidLock();\n process.exit(0);\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n\nmain().catch((err) => {\n console.error('[sisyphus] Fatal error:', err);\n process.exit(1);\n});\n","import { readFileSync } from 'node:fs';\nimport { globalConfigPath, projectConfigPath } from './paths.js';\n\nexport interface Config {\n model?: string;\n tmuxSession?: string;\n orchestratorPrompt?: string;\n pollIntervalMs?: number;\n}\n\nconst DEFAULT_CONFIG: Config = {\n pollIntervalMs: 1000,\n};\n\nfunction readJsonFile(filePath: string): Partial<Config> {\n try {\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as Partial<Config>;\n } catch {\n return {};\n }\n}\n\nexport function loadConfig(cwd: string): Config {\n const global = readJsonFile(globalConfigPath());\n const project = readJsonFile(projectConfigPath(cwd));\n return { ...DEFAULT_CONFIG, ...global, ...project };\n}\n","import { createServer, type Server } from 'node:net';\nimport { unlinkSync, existsSync, writeFileSync, readFileSync, mkdirSync } from 'node:fs';\nimport { socketPath, globalDir } from '../shared/paths.js';\nimport { join } from 'node:path';\nimport type { Request, Response } from '../shared/protocol.js';\nimport * as sessionManager from './session-manager.js';\n\nlet server: Server | null = null;\n\n// Track the cwd for each session so we can route requests\nconst sessionCwdMap = new Map<string, string>();\n// Track the originating tmux session for each sisyphus session\nconst sessionTmuxMap = new Map<string, string>();\n// Track the originating tmux window for each sisyphus session\nconst sessionWindowMap = new Map<string, string>();\n\nexport function getSessionCwd(sessionId: string): string | undefined {\n return sessionCwdMap.get(sessionId);\n}\n\nexport function getSessionTmux(sessionId: string): string | undefined {\n return sessionTmuxMap.get(sessionId);\n}\n\nfunction registryPath(): string {\n return join(globalDir(), 'session-registry.json');\n}\n\nfunction persistSessionRegistry(): void {\n const dir = globalDir();\n mkdirSync(dir, { recursive: true });\n const registry: Record<string, string> = {};\n for (const [id, cwd] of sessionCwdMap) {\n registry[id] = cwd;\n }\n writeFileSync(registryPath(), JSON.stringify(registry, null, 2), 'utf-8');\n}\n\nexport function loadSessionRegistry(): Record<string, string> {\n const p = registryPath();\n if (!existsSync(p)) return {};\n try {\n return JSON.parse(readFileSync(p, 'utf-8')) as Record<string, string>;\n } catch {\n return {};\n }\n}\n\nexport function registerSessionCwd(sessionId: string, cwd: string): void {\n sessionCwdMap.set(sessionId, cwd);\n persistSessionRegistry();\n}\n\nasync function handleRequest(req: Request): Promise<Response> {\n try {\n switch (req.type) {\n case 'start': {\n const session = await sessionManager.startSession(req.task, req.cwd, req.tmuxSession, req.tmuxWindow);\n registerSessionCwd(session.id, req.cwd);\n sessionTmuxMap.set(session.id, req.tmuxSession);\n sessionWindowMap.set(session.id, req.tmuxWindow);\n return { ok: true, data: { sessionId: session.id } };\n }\n\n case 'spawn': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const result = await sessionManager.handleSpawn(req.sessionId, cwd, req.agentType, req.name, req.instruction);\n return { ok: true, data: { agentId: result.agentId } };\n }\n\n case 'submit': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const windowId = sessionWindowMap.get(req.sessionId);\n if (!windowId) return { ok: false, error: `No tmux window found for session: ${req.sessionId}` };\n await sessionManager.handleSubmit(cwd, req.sessionId, req.agentId, req.report, windowId);\n return { ok: true };\n }\n\n case 'report': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleReport(cwd, req.sessionId, req.agentId, req.content);\n return { ok: true };\n }\n\n case 'yield': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleYield(req.sessionId, cwd, req.nextPrompt);\n return { ok: true };\n }\n\n case 'complete': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleComplete(req.sessionId, cwd, req.report);\n return { ok: true };\n }\n\n case 'status': {\n if (req.sessionId) {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const session = sessionManager.getSessionStatus(cwd, req.sessionId);\n return { ok: true, data: { session: session as unknown as Record<string, unknown> } };\n }\n return { ok: true, data: { message: 'daemon running' } };\n }\n\n case 'tasks_add': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const result = await sessionManager.handleTaskAdd(cwd, req.sessionId, req.description, req.status);\n return { ok: true, data: { taskId: result.taskId } };\n }\n\n case 'tasks_update': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleTaskUpdate(cwd, req.sessionId, req.taskId, req.status, req.description);\n return { ok: true };\n }\n\n case 'tasks_list': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const result = sessionManager.handleTasksList(cwd, req.sessionId);\n return { ok: true, data: { tasks: result.tasks as unknown as Record<string, unknown> } };\n }\n\n case 'list': {\n // List sessions across all known cwds\n const allSessions: Array<Record<string, unknown>> = [];\n const seenCwds = new Set<string>();\n for (const cwd of sessionCwdMap.values()) {\n if (seenCwds.has(cwd)) continue;\n seenCwds.add(cwd);\n const sessions = sessionManager.listSessions(cwd);\n allSessions.push(...sessions.map(s => s as unknown as Record<string, unknown>));\n }\n return { ok: true, data: { sessions: allSessions } };\n }\n\n case 'resume': {\n let cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) {\n // Session not in memory — try to recover from disk using the cwd provided by CLI\n const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;\n if (existsSync(stateFile)) {\n cwd = req.cwd;\n registerSessionCwd(req.sessionId, cwd);\n } else {\n return { ok: false, error: `Unknown session: ${req.sessionId}. No state.json found at ${stateFile}` };\n }\n }\n sessionTmuxMap.set(req.sessionId, req.tmuxSession);\n sessionWindowMap.set(req.sessionId, req.tmuxWindow);\n const session = await sessionManager.resumeSession(req.sessionId, cwd, req.tmuxSession, req.tmuxWindow, req.message);\n return { ok: true, data: { sessionId: session.id, status: session.status } };\n }\n\n case 'register_claude_session': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleRegisterClaudeSession(cwd, req.sessionId, req.agentId, req.claudeSessionId);\n return { ok: true };\n }\n\n case 'kill': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const killedAgents = await sessionManager.handleKill(req.sessionId, cwd);\n sessionCwdMap.delete(req.sessionId);\n sessionTmuxMap.delete(req.sessionId);\n sessionWindowMap.delete(req.sessionId);\n persistSessionRegistry();\n return { ok: true, data: { killedAgents, sessionId: req.sessionId } };\n }\n\n default:\n return { ok: false, error: `Unknown request type: ${(req as Record<string, unknown>).type}` };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n\nexport function startServer(): Promise<Server> {\n return new Promise((resolve, reject) => {\n const sock = socketPath();\n\n if (existsSync(sock)) {\n unlinkSync(sock);\n }\n\n server = createServer((conn) => {\n let buffer = '';\n\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n const lines = buffer.split('\\n');\n buffer = lines.pop()!;\n\n for (const line of lines) {\n if (!line.trim()) continue;\n let req: Request;\n try {\n req = JSON.parse(line) as Request;\n } catch {\n conn.write(JSON.stringify({ ok: false, error: 'Invalid JSON' }) + '\\n');\n continue;\n }\n\n handleRequest(req).then((res) => {\n conn.write(JSON.stringify(res) + '\\n');\n });\n }\n });\n\n conn.on('error', (err) => {\n console.error('[sisyphus] Connection error:', err.message);\n });\n });\n\n server.on('error', reject);\n\n server.listen(sock, () => {\n console.log(`[sisyphus] Daemon listening on ${sock}`);\n resolve(server!);\n });\n });\n}\n\nexport function stopServer(): Promise<void> {\n return new Promise((resolve) => {\n if (!server) {\n resolve();\n return;\n }\n server.close(() => {\n const sock = socketPath();\n if (existsSync(sock)) {\n unlinkSync(sock);\n }\n server = null;\n resolve();\n });\n });\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { existsSync, readdirSync } from 'node:fs';\nimport * as state from './state.js';\nimport * as orchestrator from './orchestrator.js';\nimport * as tmux from './tmux.js';\nimport { spawnAgent, resetAgentCounter, clearAgentCounter, handleAgentSubmit, handleAgentReport } from './agent.js';\nimport { trackSession, untrackSession, updateTrackedWindow } from './pane-monitor.js';\nimport { resetColors } from './colors.js';\nimport { sessionsDir } from '../shared/paths.js';\nimport type { Session, TaskStatus } from '../shared/types.js';\n\nexport async function startSession(task: string, cwd: string, tmuxSession: string, windowId: string): Promise<Session> {\n const sessionId = uuidv4();\n const session = state.createSession(sessionId, task, cwd);\n\n trackSession(sessionId, cwd, tmuxSession);\n await orchestrator.spawnOrchestrator(sessionId, cwd, windowId);\n updateTrackedWindow(sessionId, windowId);\n\n return session;\n}\n\nexport async function resumeSession(sessionId: string, cwd: string, tmuxSession: string, windowId: string, message?: string): Promise<Session> {\n const session = state.getSession(cwd, sessionId);\n\n // Mark any \"running\" agents as \"lost\"\n for (const agent of session.agents) {\n if (agent.status === 'running') {\n await state.updateAgent(cwd, sessionId, agent.id, {\n status: 'lost',\n completedAt: new Date().toISOString(),\n killedReason: 'session resumed — agent was still running',\n });\n }\n }\n\n await state.updateSessionStatus(cwd, sessionId, 'active');\n\n // Reset counters based on existing agents\n resetAgentCounter(sessionId, session.agents.length);\n resetColors(sessionId);\n\n trackSession(sessionId, cwd, tmuxSession);\n await orchestrator.spawnOrchestrator(sessionId, cwd, windowId, message);\n updateTrackedWindow(sessionId, windowId);\n\n return state.getSession(cwd, sessionId);\n}\n\nexport function getSessionStatus(cwd: string, sessionId: string): Session {\n return state.getSession(cwd, sessionId);\n}\n\nexport function listSessions(cwd: string): Array<{ id: string; task: string; status: string; createdAt: string; agentCount: number }> {\n const dir = sessionsDir(cwd);\n if (!existsSync(dir)) return [];\n\n const entries = readdirSync(dir, { withFileTypes: true });\n const sessions: Array<{ id: string; task: string; status: string; createdAt: string; agentCount: number }> = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n try {\n const session = state.getSession(cwd, entry.name);\n sessions.push({\n id: session.id,\n task: session.task,\n status: session.status,\n createdAt: session.createdAt,\n agentCount: session.agents.length,\n });\n } catch (err) {\n console.error(`[sisyphus] Failed to read session ${entry.name}:`, err);\n }\n }\n\n return sessions;\n}\n\nexport function onAllAgentsDone(sessionId: string, cwd: string, windowId: string): void {\n const session = state.getSession(cwd, sessionId);\n if (session.status !== 'active') return;\n\n // Delay to let /exit finish quitting the previous Claude session\n setTimeout(() => {\n orchestrator.spawnOrchestrator(sessionId, cwd, windowId)\n .then(() => updateTrackedWindow(sessionId, windowId))\n .catch((err: unknown) => console.error(`[sisyphus] Failed to respawn orchestrator for session ${sessionId}:`, err));\n }, 2000);\n}\n\nexport async function handleSpawn(\n sessionId: string,\n cwd: string,\n agentType: string,\n name: string,\n instruction: string,\n): Promise<{ agentId: string }> {\n const windowId = orchestrator.getWindowId(sessionId);\n if (!windowId) throw new Error(`No tmux window found for session ${sessionId}`);\n\n const agent = await spawnAgent({\n sessionId,\n cwd,\n agentType,\n name,\n instruction,\n windowId,\n });\n\n await state.appendAgentToLastCycle(cwd, sessionId, agent.id);\n\n return { agentId: agent.id };\n}\n\nexport async function handleSubmit(cwd: string, sessionId: string, agentId: string, report: string, windowId: string): Promise<void> {\n const allDone = await handleAgentSubmit(cwd, sessionId, agentId, report);\n if (allDone) {\n onAllAgentsDone(sessionId, cwd, windowId);\n }\n}\n\nexport async function handleReport(cwd: string, sessionId: string, agentId: string, content: string): Promise<void> {\n await handleAgentReport(cwd, sessionId, agentId, content);\n}\n\nexport async function handleYield(sessionId: string, cwd: string, nextPrompt?: string): Promise<void> {\n await orchestrator.handleOrchestratorYield(sessionId, cwd, nextPrompt);\n}\n\nexport async function handleComplete(sessionId: string, cwd: string, report: string): Promise<void> {\n untrackSession(sessionId);\n await orchestrator.handleOrchestratorComplete(sessionId, cwd, report);\n}\n\nexport async function handleTaskAdd(cwd: string, sessionId: string, description: string, initialStatus?: string): Promise<{ taskId: string }> {\n const VALID_STATUSES: Set<string> = new Set(['draft', 'pending', 'in_progress', 'done']);\n const status = initialStatus !== undefined && VALID_STATUSES.has(initialStatus) ? initialStatus as TaskStatus : undefined;\n const task = await state.addTask(cwd, sessionId, description, status);\n return { taskId: task.id };\n}\n\nexport async function handleTaskUpdate(cwd: string, sessionId: string, taskId: string, status?: string, description?: string): Promise<void> {\n const VALID_STATUSES: Set<string> = new Set(['draft', 'pending', 'in_progress', 'done']);\n const updates: { status?: TaskStatus; description?: string } = {};\n if (status !== undefined) {\n if (!VALID_STATUSES.has(status)) throw new Error(`Invalid status: ${status}. Valid: draft, pending, in_progress, done`);\n updates.status = status as TaskStatus;\n }\n if (description !== undefined) updates.description = description;\n await state.updateTask(cwd, sessionId, taskId, updates);\n}\n\nexport function handleTasksList(cwd: string, sessionId: string): { tasks: Session['tasks'] } {\n const session = state.getSession(cwd, sessionId);\n return { tasks: session.tasks };\n}\n\nexport async function handleRegisterClaudeSession(\n cwd: string,\n sessionId: string,\n agentId: string,\n claudeSessionId: string,\n): Promise<void> {\n await state.updateAgent(cwd, sessionId, agentId, { claudeSessionId });\n}\n\nexport async function handleKill(sessionId: string, cwd: string): Promise<number> {\n const session = state.getSession(cwd, sessionId);\n const windowId = orchestrator.getWindowId(sessionId);\n\n // Kill all running agents\n let killedAgents = 0;\n for (const agent of session.agents) {\n if (agent.status === 'running') {\n await state.updateAgent(cwd, sessionId, agent.id, {\n status: 'killed',\n killedReason: 'session killed by user',\n completedAt: new Date().toISOString(),\n });\n killedAgents++;\n }\n }\n\n // Kill the orchestrator pane if it exists\n const orchPaneId = orchestrator.getOrchestratorPaneId(sessionId);\n if (orchPaneId) {\n tmux.killPane(orchPaneId);\n }\n\n // Mark session as completed\n await state.updateSessionStatus(cwd, sessionId, 'completed');\n\n // Untrack from pane monitor\n untrackSession(sessionId);\n\n // Kill the entire tmux window\n if (windowId) {\n tmux.killWindow(windowId);\n }\n\n // Clean up agent counter\n clearAgentCounter(sessionId);\n\n return killedAgents;\n}\n","import { readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type { Session, Agent, AgentReport, Task, OrchestratorCycle, SessionStatus, TaskStatus } from '../shared/types.js';\nimport { statePath, sessionDir, contextDir } from '../shared/paths.js';\n\n// Per-session mutex to prevent read-modify-write races\nconst sessionLocks = new Map<string, Promise<void>>();\n\nasync function withSessionLock<T>(sessionId: string, fn: () => T): Promise<T> {\n const prev = sessionLocks.get(sessionId) ?? Promise.resolve();\n let resolve: () => void;\n const next = new Promise<void>(r => { resolve = r; });\n sessionLocks.set(sessionId, next);\n await prev;\n try {\n return fn();\n } finally {\n resolve!();\n }\n}\n\nfunction atomicWrite(filePath: string, data: string): void {\n const dir = dirname(filePath);\n const tmpPath = join(dir, `.state.${randomUUID()}.tmp`);\n writeFileSync(tmpPath, data, 'utf-8');\n renameSync(tmpPath, filePath);\n}\n\nexport function createSession(id: string, task: string, cwd: string): Session {\n const dir = sessionDir(cwd, id);\n mkdirSync(dir, { recursive: true });\n mkdirSync(contextDir(cwd, id), { recursive: true });\n\n const session: Session = {\n id,\n task,\n cwd,\n status: 'active',\n createdAt: new Date().toISOString(),\n tasks: [],\n agents: [],\n orchestratorCycles: [],\n };\n\n atomicWrite(statePath(cwd, id), JSON.stringify(session, null, 2));\n return session;\n}\n\nexport function getSession(cwd: string, sessionId: string): Session {\n const content = readFileSync(statePath(cwd, sessionId), 'utf-8');\n return JSON.parse(content) as Session;\n}\n\nfunction saveSession(session: Session): void {\n atomicWrite(statePath(session.cwd, session.id), JSON.stringify(session, null, 2));\n}\n\nexport async function addTask(cwd: string, sessionId: string, description: string, initialStatus?: TaskStatus): Promise<Task> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const nextNum = session.tasks.length + 1;\n const task: Task = {\n id: `t${nextNum}`,\n description,\n status: initialStatus !== undefined ? initialStatus : 'pending',\n };\n session.tasks.push(task);\n saveSession(session);\n return task;\n });\n}\n\nexport async function updateTask(cwd: string, sessionId: string, taskId: string, updates: { status?: TaskStatus; description?: string }): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const task = session.tasks.find(t => t.id === taskId);\n if (!task) throw new Error(`Task ${taskId} not found in session ${sessionId}`);\n if (updates.status) task.status = updates.status;\n if (updates.description) task.description = updates.description;\n saveSession(session);\n });\n}\n\nexport async function addAgent(cwd: string, sessionId: string, agent: Agent): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.agents.push(agent);\n saveSession(session);\n });\n}\n\nexport async function updateAgent(cwd: string, sessionId: string, agentId: string, updates: Partial<Agent>): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const agent = session.agents.find(a => a.id === agentId);\n if (!agent) throw new Error(`Agent ${agentId} not found in session ${sessionId}`);\n Object.assign(agent, updates);\n saveSession(session);\n });\n}\n\nexport async function addOrchestratorCycle(cwd: string, sessionId: string, cycle: OrchestratorCycle): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.orchestratorCycles.push(cycle);\n saveSession(session);\n });\n}\n\nexport async function updateSessionStatus(cwd: string, sessionId: string, status: SessionStatus, completionReport?: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.status = status;\n if (completionReport !== undefined) {\n session.completionReport = completionReport;\n }\n saveSession(session);\n });\n}\n\nexport async function appendAgentToLastCycle(cwd: string, sessionId: string, agentId: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const cycles = session.orchestratorCycles;\n if (cycles.length === 0) return;\n cycles[cycles.length - 1]!.agentsSpawned.push(agentId);\n saveSession(session);\n });\n}\n\nexport async function completeSession(cwd: string, sessionId: string, report: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.status = 'completed';\n session.completedAt = new Date().toISOString();\n session.completionReport = report;\n saveSession(session);\n });\n}\n\nexport async function appendAgentReport(cwd: string, sessionId: string, agentId: string, entry: AgentReport): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const agent = session.agents.find(a => a.id === agentId);\n if (!agent) throw new Error(`Agent ${agentId} not found in session ${sessionId}`);\n agent.reports.push(entry);\n saveSession(session);\n });\n}\n\nexport async function completeOrchestratorCycle(cwd: string, sessionId: string, nextPrompt?: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const cycles = session.orchestratorCycles;\n if (cycles.length === 0) return;\n const cycle = cycles[cycles.length - 1]!;\n cycle.completedAt = new Date().toISOString();\n if (nextPrompt) cycle.nextPrompt = nextPrompt;\n saveSession(session);\n });\n}\n","import { readFileSync, existsSync, writeFileSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport * as state from './state.js';\nimport * as tmux from './tmux.js';\nimport { ORCHESTRATOR_COLOR } from './colors.js';\nimport { projectOrchestratorPromptPath, sessionDir, contextDir } from '../shared/paths.js';\nimport type { Session, Agent } from '../shared/types.js';\n\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nconst sessionWindowMap = new Map<string, string>();\nconst sessionOrchestratorPane = new Map<string, string>();\n\nexport function getWindowId(sessionId: string): string | undefined {\n return sessionWindowMap.get(sessionId);\n}\n\nexport function setWindowId(sessionId: string, windowId: string): void {\n sessionWindowMap.set(sessionId, windowId);\n}\n\nexport function getOrchestratorPaneId(sessionId: string): string | undefined {\n return sessionOrchestratorPane.get(sessionId);\n}\n\nfunction loadOrchestratorPrompt(cwd: string): string {\n const projectPath = projectOrchestratorPromptPath(cwd);\n if (existsSync(projectPath)) {\n return readFileSync(projectPath, 'utf-8');\n }\n const bundledPath = resolve(import.meta.dirname, '../templates/orchestrator.md');\n return readFileSync(bundledPath, 'utf-8');\n}\n\nfunction formatStateForOrchestrator(session: Session): string {\n const shortId = session.id.slice(0, 8);\n const cycleNum = session.orchestratorCycles.length;\n\n const taskLines = session.tasks.length > 0\n ? session.tasks.map(t => `- ${t.id}: [${t.status}] ${t.description}`).join('\\n')\n : ' (none)';\n\n const ctxDir = contextDir(session.cwd, session.id);\n let contextLines: string;\n if (existsSync(ctxDir)) {\n const files = readdirSync(ctxDir);\n contextLines = files.length > 0 ? files.map(f => `- ${f}`).join('\\n') : ' (none)';\n } else {\n contextLines = ' (none)';\n }\n\n const agentLines = session.agents.length > 0\n ? session.agents.map((a: Agent) => {\n const header = `- ${a.id} (${a.name}): ${a.status} — ${a.reports.length} report(s)`;\n if (a.reports.length === 0) return header;\n let updateNum = 0;\n const reportLines = a.reports.map(r => {\n const label = r.type === 'final' ? '[final]' : `[update ${String(++updateNum).padStart(3, '0')}]`;\n return ` ${label} \"${r.summary}\" → ${r.filePath}`;\n });\n return [header, ...reportLines].join('\\n');\n }).join('\\n')\n : ' (none)';\n\n const cycleLines = session.orchestratorCycles.length > 0\n ? session.orchestratorCycles.map(c => {\n const spawnedList = c.agentsSpawned.length > 0 ? c.agentsSpawned.join(', ') : '(none)';\n return `Cycle ${c.cycle}: Spawned ${spawnedList}`;\n }).join('\\n')\n : ' (none)';\n\n return [\n '<state>',\n `session: ${shortId} (cycle ${cycleNum})`,\n `task: ${session.task}`,\n `status: ${session.status}`,\n '',\n '## Tasks',\n taskLines,\n '',\n '## Context Files',\n contextLines,\n '',\n '## Agents',\n agentLines,\n '',\n '## Previous Cycles',\n cycleLines,\n '</state>',\n ].join('\\n');\n}\n\nexport async function spawnOrchestrator(sessionId: string, cwd: string, windowId: string, message?: string): Promise<void> {\n const session = state.getSession(cwd, sessionId);\n const basePrompt = loadOrchestratorPrompt(cwd);\n const formattedState = formatStateForOrchestrator(session);\n\n // System prompt: template only (no state)\n const cycleNum = session.orchestratorCycles.length + 1;\n const promptFilePath = `${sessionDir(cwd, sessionId)}/orchestrator-prompt-${cycleNum}.md`;\n writeFileSync(promptFilePath, basePrompt, 'utf-8');\n\n sessionWindowMap.set(sessionId, windowId);\n\n const envExports = [\n `export SISYPHUS_SESSION_ID='${sessionId}'`,\n `export SISYPHUS_AGENT_ID='orchestrator'`,\n ].join(' && ');\n\n // User message: state block + contextual prompt\n let userPrompt: string;\n if (message) {\n userPrompt = `${formattedState}\\n\\nThe user resumed this session with new instructions: ${message}`;\n } else {\n // Check last completed cycle for a stored nextPrompt\n const lastCycle = [...session.orchestratorCycles].reverse().find(c => c.completedAt);\n const storedPrompt = lastCycle?.nextPrompt;\n if (storedPrompt) {\n userPrompt = `${formattedState}\\n\\n${storedPrompt}`;\n } else {\n userPrompt = `${formattedState}\\n\\nReview the current session state and execute the next cycle of work.`;\n }\n }\n\n const userPromptFilePath = `${sessionDir(cwd, sessionId)}/orchestrator-user-${cycleNum}.md`;\n writeFileSync(userPromptFilePath, userPrompt, 'utf-8');\n const claudeCmd = `claude --dangerously-skip-permissions --append-system-prompt \"$(cat '${promptFilePath}')\" \"$(cat '${userPromptFilePath}')\"`;\n\n const paneId = tmux.createPane(windowId, cwd);\n\n sessionOrchestratorPane.set(sessionId, paneId);\n tmux.setPaneTitle(paneId, `orchestrator (${sessionId.slice(0, 8)})`);\n tmux.setPaneStyle(paneId, ORCHESTRATOR_COLOR);\n\n const bannerPath = resolve(import.meta.dirname, '../templates/banner.txt');\n const bannerCmd = existsSync(bannerPath) ? `cat '${bannerPath}' &&` : '';\n tmux.sendKeys(paneId, `${bannerCmd} ${envExports} && ${claudeCmd}`);\n\n await state.addOrchestratorCycle(cwd, sessionId, {\n cycle: cycleNum,\n timestamp: new Date().toISOString(),\n agentsSpawned: [],\n paneId,\n });\n}\n\nfunction resolveOrchestratorPane(sessionId: string, cwd: string): string | undefined {\n const memPane = sessionOrchestratorPane.get(sessionId);\n if (memPane) return memPane;\n const session = state.getSession(cwd, sessionId);\n const lastCycle = session.orchestratorCycles[session.orchestratorCycles.length - 1];\n return lastCycle?.paneId ?? undefined;\n}\n\nexport async function handleOrchestratorYield(sessionId: string, cwd: string, nextPrompt?: string): Promise<void> {\n const paneId = resolveOrchestratorPane(sessionId, cwd);\n if (paneId) {\n tmux.killPane(paneId);\n sessionOrchestratorPane.delete(sessionId);\n }\n\n await state.completeOrchestratorCycle(cwd, sessionId, nextPrompt);\n\n const session = state.getSession(cwd, sessionId);\n const runningAgents = session.agents.filter(a => a.status === 'running');\n if (runningAgents.length === 0) {\n console.error(`[sisyphus] WARNING: Orchestrator yielded but no agents are running for session ${sessionId}`);\n }\n}\n\nexport async function handleOrchestratorComplete(sessionId: string, cwd: string, report: string): Promise<void> {\n const paneId = resolveOrchestratorPane(sessionId, cwd);\n\n await state.completeOrchestratorCycle(cwd, sessionId);\n await state.completeSession(cwd, sessionId, report);\n\n if (paneId) {\n tmux.killPane(paneId);\n sessionOrchestratorPane.delete(sessionId);\n }\n\n sessionWindowMap.delete(sessionId);\n\n console.log(`[sisyphus] Session ${sessionId} completed: ${report}`);\n}\n","import { execSync } from 'node:child_process';\n\nconst EXEC_ENV = {\n ...process.env,\n PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env['PATH'] ?? '/usr/bin:/bin'}`,\n};\n\nfunction exec(cmd: string): string {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV }).trim();\n}\n\nfunction execSafe(cmd: string): string | null {\n try {\n return exec(cmd);\n } catch {\n return null;\n }\n}\n\nexport function getCurrentTmuxSession(): string {\n const tmuxEnv = process.env['TMUX'];\n if (!tmuxEnv) throw new Error('Not running inside tmux');\n return exec('tmux display-message -p \"#{session_name}\"');\n}\n\nexport function createWindow(sessionName: string, windowName: string, cwd?: string): string {\n const cwdFlag = cwd ? ` -c ${shellQuote(cwd)}` : '';\n exec(`tmux new-window -t \"${sessionName}\" -n \"${windowName}\"${cwdFlag} -P -F \"#{window_id}\"`);\n return exec(`tmux display-message -t \"${sessionName}:${windowName}\" -p \"#{window_id}\"`);\n}\n\nexport function createPane(windowTarget: string, cwd?: string): string {\n const cwdFlag = cwd ? ` -c ${shellQuote(cwd)}` : '';\n const paneId = exec(`tmux split-window -h -t \"${windowTarget}\"${cwdFlag} -P -F \"#{pane_id}\"`);\n execSafe(`tmux select-layout -t \"${windowTarget}\" even-horizontal`);\n return paneId;\n}\n\nexport function sendKeys(paneTarget: string, command: string): void {\n exec(`tmux send-keys -t \"${paneTarget}\" ${shellQuote(command)} Enter`);\n}\n\nexport function killPane(paneTarget: string): void {\n execSafe(`tmux kill-pane -t \"${paneTarget}\"`);\n}\n\nexport function killWindow(windowTarget: string): void {\n execSafe(`tmux kill-window -t \"${windowTarget}\"`);\n}\n\nexport interface PaneInfo {\n paneId: string;\n panePid: string;\n}\n\nexport function listPanes(windowTarget: string): PaneInfo[] {\n const output = execSafe(`tmux list-panes -t \"${windowTarget}\" -F \"#{pane_id} #{pane_pid}\"`);\n if (!output) return [];\n return output\n .split('\\n')\n .filter(Boolean)\n .map(line => {\n const [paneId, panePid] = line.split(' ');\n return { paneId: paneId!, panePid: panePid! };\n });\n}\n\nexport function setPaneTitle(paneTarget: string, title: string): void {\n execSafe(`tmux select-pane -t \"${paneTarget}\" -T ${shellQuote(title)}`);\n}\n\nexport function setPaneStyle(paneTarget: string, color: string): void {\n // pane-border-style is window-level in tmux 3.6 (last-write-wins across all panes).\n // pane-border-format IS truly per-pane, so we colorize the border status text instead.\n const fmt = `#[fg=${color},bold] #{pane_title} #[fg=${color}]#{pane_current_path} #[default]`;\n execSafe(`tmux set -p -t \"${paneTarget}\" pane-border-format ${shellQuote(fmt)}`);\n execSafe(`tmux set -p -t \"${paneTarget}\" pane-border-style \"fg=${color}\"`);\n execSafe(`tmux set -p -t \"${paneTarget}\" pane-active-border-style \"fg=${color}\"`);\n}\n\nexport function sendSignal(paneTarget: string, signal: string): void {\n const info = execSafe(`tmux list-panes -t \"${paneTarget}\" -F \"#{pane_pid}\"`);\n if (!info) return;\n const pid = info.split('\\n')[0]?.trim();\n if (pid) {\n execSafe(`kill -${signal} ${pid}`);\n }\n}\n\nexport function selectLayout(windowTarget: string, layout: string = 'even-horizontal'): void {\n execSafe(`tmux select-layout -t \"${windowTarget}\" ${layout}`);\n}\n\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n","export const ORCHESTRATOR_COLOR = 'yellow';\n\nconst AGENT_PALETTE = ['blue', 'green', 'magenta', 'cyan', 'red', 'white'] as const;\n\nconst sessionColorIndex = new Map<string, number>();\n\nexport function getNextColor(sessionId: string): string {\n const idx = sessionColorIndex.get(sessionId) ?? 0;\n const color = AGENT_PALETTE[idx % AGENT_PALETTE.length]!;\n sessionColorIndex.set(sessionId, idx + 1);\n return color;\n}\n\nexport function resetColors(sessionId: string): void {\n sessionColorIndex.delete(sessionId);\n}\n","import { readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { Agent, AgentReport } from '../shared/types.js';\nimport * as state from './state.js';\nimport * as tmux from './tmux.js';\nimport { getNextColor } from './colors.js';\nimport { sessionDir, reportsDir, reportFilePath } from '../shared/paths.js';\n\nconst agentCounters = new Map<string, number>();\n\nexport function resetAgentCounter(sessionId: string, value: number = 0): void {\n agentCounters.set(sessionId, value);\n}\n\nexport function clearAgentCounter(sessionId: string): void {\n agentCounters.delete(sessionId);\n}\n\nfunction renderAgentSuffix(sessionId: string, instruction: string): string {\n const templatePath = resolve(import.meta.dirname, '../templates/agent-suffix.md');\n let template: string;\n try {\n template = readFileSync(templatePath, 'utf-8');\n } catch {\n template = `# Sisyphus Agent\\nSession: {{SESSION_ID}}\\nTask: {{INSTRUCTION}}`;\n }\n return template\n .replace(/\\{\\{SESSION_ID\\}\\}/g, sessionId)\n .replace(/\\{\\{INSTRUCTION\\}\\}/g, instruction);\n}\n\nexport interface SpawnAgentOpts {\n sessionId: string;\n cwd: string;\n agentType: string;\n name: string;\n instruction: string;\n windowId: string;\n}\n\nexport async function spawnAgent(opts: SpawnAgentOpts): Promise<Agent> {\n const { sessionId, cwd, agentType, name, instruction, windowId } = opts;\n const count = (agentCounters.get(sessionId) ?? 0) + 1;\n agentCounters.set(sessionId, count);\n const agentId = `agent-${String(count).padStart(3, '0')}`;\n const color = getNextColor(sessionId);\n\n const paneId = tmux.createPane(windowId, cwd);\n tmux.setPaneTitle(paneId, `${name} (${agentId})`);\n tmux.setPaneStyle(paneId, color);\n\n const suffix = renderAgentSuffix(sessionId, instruction);\n const suffixFilePath = `${sessionDir(cwd, sessionId)}/${agentId}-system.md`;\n writeFileSync(suffixFilePath, suffix, 'utf-8');\n\n const bannerPath = resolve(import.meta.dirname, '../templates/banner.txt');\n const bannerCmd = existsSync(bannerPath) ? `cat '${bannerPath}' &&` : '';\n\n const envExports = [\n `export SISYPHUS_SESSION_ID='${sessionId}'`,\n `export SISYPHUS_AGENT_ID='${agentId}'`,\n ].join(' && ');\n\n const agentFlag = agentType ? ` --agent ${shellQuote(agentType)}` : '';\n const claudeCmd = `claude --dangerously-skip-permissions${agentFlag} --append-system-prompt \"$(cat '${suffixFilePath}')\" ${shellQuote(instruction)}`;\n tmux.sendKeys(paneId, `${bannerCmd} ${envExports} && ${claudeCmd}`);\n\n const agent: Agent = {\n id: agentId,\n name,\n agentType,\n color,\n instruction,\n status: 'running',\n spawnedAt: new Date().toISOString(),\n completedAt: null,\n reports: [],\n paneId,\n };\n\n await state.addAgent(cwd, sessionId, agent);\n return agent;\n}\n\nfunction nextReportNumber(cwd: string, sessionId: string, agentId: string): string {\n const dir = reportsDir(cwd, sessionId);\n try {\n const files = readdirSync(dir).filter(f => f.startsWith(`${agentId}-`) && !f.endsWith('-final.md'));\n return String(files.length + 1).padStart(3, '0');\n } catch {\n return '001';\n }\n}\n\nexport async function handleAgentReport(\n cwd: string,\n sessionId: string,\n agentId: string,\n content: string,\n): Promise<void> {\n const dir = reportsDir(cwd, sessionId);\n mkdirSync(dir, { recursive: true });\n\n const num = nextReportNumber(cwd, sessionId, agentId);\n const filePath = reportFilePath(cwd, sessionId, agentId, num);\n writeFileSync(filePath, content, 'utf-8');\n\n const entry: AgentReport = {\n type: 'update',\n filePath,\n summary: content.slice(0, 200),\n timestamp: new Date().toISOString(),\n };\n await state.appendAgentReport(cwd, sessionId, agentId, entry);\n}\n\nexport async function handleAgentSubmit(\n cwd: string,\n sessionId: string,\n agentId: string,\n report: string,\n): Promise<boolean> {\n const dir = reportsDir(cwd, sessionId);\n mkdirSync(dir, { recursive: true });\n\n const filePath = reportFilePath(cwd, sessionId, agentId, 'final');\n writeFileSync(filePath, report, 'utf-8');\n\n const entry: AgentReport = {\n type: 'final',\n filePath,\n summary: report.slice(0, 200),\n timestamp: new Date().toISOString(),\n };\n await state.appendAgentReport(cwd, sessionId, agentId, entry);\n\n await state.updateAgent(cwd, sessionId, agentId, {\n status: 'completed',\n completedAt: new Date().toISOString(),\n });\n\n const session = state.getSession(cwd, sessionId);\n const agent = session.agents.find(a => a.id === agentId);\n if (agent) {\n tmux.killPane(agent.paneId);\n }\n\n return allAgentsDone(session);\n}\n\nexport async function handleAgentKilled(\n cwd: string,\n sessionId: string,\n agentId: string,\n reason: string,\n): Promise<boolean> {\n await state.updateAgent(cwd, sessionId, agentId, {\n status: 'killed',\n killedReason: reason,\n completedAt: new Date().toISOString(),\n });\n\n const session = state.getSession(cwd, sessionId);\n return allAgentsDone(session);\n}\n\n// Note: this checks ALL running agents in the session, not just orchestrator-spawned ones.\n// Agents can also call `sisyphus spawn`, and those child agents are included here —\n// the orchestrator won't respawn until every agent (including agent-spawned ones) finishes.\nfunction allAgentsDone(session: import('../shared/types.js').Session): boolean {\n const running = session.agents.filter(a => a.status === 'running');\n return running.length === 0 && session.agents.length > 0;\n}\n\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n","import * as state from './state.js';\nimport * as tmux from './tmux.js';\nimport { getOrchestratorPaneId } from './orchestrator.js';\nimport { handleAgentKilled } from './agent.js';\n\ntype RespawnCallback = (sessionId: string, cwd: string, windowId: string) => void;\n\nlet monitorInterval: ReturnType<typeof setInterval> | null = null;\nlet onAllAgentsDone: RespawnCallback | null = null;\n\nexport function setRespawnCallback(cb: RespawnCallback): void {\n onAllAgentsDone = cb;\n}\n\nexport function startMonitor(pollIntervalMs: number = 1000): void {\n if (monitorInterval) return;\n monitorInterval = setInterval(() => {\n pollAllSessions().catch(err => {\n console.error('[sisyphus] Pane monitor error:', err);\n });\n }, pollIntervalMs);\n}\n\nexport function stopMonitor(): void {\n if (monitorInterval) {\n clearInterval(monitorInterval);\n monitorInterval = null;\n }\n}\n\nconst trackedSessions = new Map<string, { id: string; cwd: string; tmuxSession: string; windowId: string | null }>();\n\nexport function trackSession(sessionId: string, cwd: string, tmuxSession: string): void {\n // windowId is registered separately via updateTrackedWindow after spawnOrchestrator sets it\n const existing = trackedSessions.get(sessionId);\n trackedSessions.set(sessionId, { id: sessionId, cwd, tmuxSession, windowId: existing ? existing.windowId : null });\n}\n\nexport function updateTrackedWindow(sessionId: string, windowId: string): void {\n const entry = trackedSessions.get(sessionId);\n if (!entry) throw new Error(`Cannot update window for untracked session: ${sessionId}`);\n entry.windowId = windowId;\n}\n\nexport function untrackSession(sessionId: string): void {\n trackedSessions.delete(sessionId);\n}\n\nasync function pollAllSessions(): Promise<void> {\n for (const { id: sessionId, cwd, windowId } of trackedSessions.values()) {\n if (windowId) {\n await pollSession(sessionId, cwd, windowId);\n }\n }\n}\n\nasync function pollSession(sessionId: string, cwd: string, windowId: string): Promise<void> {\n let session;\n try {\n session = state.getSession(cwd, sessionId);\n } catch (err) {\n console.error(`[sisyphus] Failed to read state for session ${sessionId}:`, err);\n return;\n }\n\n if (session.status !== 'active') return;\n\n const livePanes = tmux.listPanes(windowId);\n if (livePanes.length === 0) return;\n\n const livePaneIds = new Set(livePanes.map(p => p.paneId));\n\n for (const agent of session.agents) {\n if (agent.status !== 'running') continue;\n if (!livePaneIds.has(agent.paneId)) {\n const allDone = await handleAgentKilled(cwd, sessionId, agent.id, 'pane closed by user');\n if (allDone && onAllAgentsDone) {\n onAllAgentsDone(sessionId, cwd, windowId);\n }\n }\n }\n\n // Check orchestrator pane\n const orchPaneId = getOrchestratorPaneId(sessionId);\n if (orchPaneId && !livePaneIds.has(orchPaneId)) {\n // Orchestrator pane disappeared without a yield command\n const runningAgents = session.agents.filter(a => a.status === 'running');\n if (runningAgents.length === 0) {\n // No agents running and orchestrator gone — pause\n await state.updateSessionStatus(cwd, sessionId, 'paused');\n console.log(`[sisyphus] Session ${sessionId} paused: orchestrator pane disappeared`);\n }\n }\n}\n"],"mappings":"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","names":["mkdirSync","readFileSync","writeFileSync","unlinkSync","existsSync","existsSync","writeFileSync","readFileSync","mkdirSync","join","existsSync","readdirSync","readFileSync","resolve","readFileSync","readFileSync","writeFileSync","readFileSync","writeFileSync","readFileSync","writeFileSync","mkdirSync","readdirSync","existsSync","resolve","resolve","readFileSync","writeFileSync","existsSync","shellQuote","readdirSync","mkdirSync","existsSync","readdirSync","onAllAgentsDone","sessionWindowMap","join","mkdirSync","writeFileSync","existsSync","readFileSync","sessionWindowMap","resolve","mkdirSync","readFileSync","writeFileSync","unlinkSync","existsSync","onAllAgentsDone"]}
1
+ {"version":3,"sources":["../src/daemon/index.ts","../src/shared/config.ts","../src/daemon/server.ts","../src/daemon/session-manager.ts","../src/daemon/state.ts","../src/daemon/orchestrator.ts","../src/daemon/colors.ts","../src/daemon/tmux.ts","../src/daemon/agent.ts","../src/daemon/worktree.ts","../src/daemon/pane-monitor.ts"],"sourcesContent":["import { mkdirSync, readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs';\nimport { globalDir, daemonPidPath, statePath } from '../shared/paths.js';\nimport { loadConfig } from '../shared/config.js';\nimport { startServer, stopServer, registerSessionCwd, registerSessionTmux, loadSessionRegistry } from './server.js';\nimport { startMonitor, stopMonitor, setRespawnCallback, trackSession, updateTrackedWindow } from './pane-monitor.js';\nimport { onAllAgentsDone } from './session-manager.js';\nimport { resetAgentCounterFromState } from './agent.js';\nimport { setWindowId, setOrchestratorPaneId, getOrchestratorPaneId } from './orchestrator.js';\nimport { listPanes } from './tmux.js';\nimport * as stateModule from './state.js';\nimport type { Session } from '../shared/types.js';\n\nfunction ensureDirs(): void {\n mkdirSync(globalDir(), { recursive: true });\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction readPid(): number | null {\n const pidFile = daemonPidPath();\n try {\n const pid = parseInt(readFileSync(pidFile, 'utf-8').trim(), 10);\n return pid && isProcessAlive(pid) ? pid : null;\n } catch {\n return null;\n }\n}\n\nfunction acquirePidLock(): void {\n const pid = readPid();\n if (pid) {\n console.error(`[sisyphus] Daemon already running (pid ${pid}). Use 'sisyphusd restart' or 'sisyphusd stop' first.`);\n process.exit(0);\n }\n writeFileSync(daemonPidPath(), String(process.pid), 'utf-8');\n}\n\nfunction releasePidLock(): void {\n try {\n unlinkSync(daemonPidPath());\n } catch {\n // Already gone\n }\n}\n\nfunction stopDaemon(): boolean {\n const pid = readPid();\n if (!pid) {\n console.log('[sisyphus] Daemon is not running');\n // Clean up stale pid file if it exists\n releasePidLock();\n return false;\n }\n\n console.log(`[sisyphus] Stopping daemon (pid ${pid})...`);\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n console.error(`[sisyphus] Failed to send SIGTERM to pid ${pid}`);\n return false;\n }\n\n // Wait for process to exit (up to 5s)\n const deadline = Date.now() + 5000;\n while (Date.now() < deadline) {\n if (!isProcessAlive(pid)) {\n console.log('[sisyphus] Daemon stopped');\n releasePidLock();\n return true;\n }\n // Busy-wait in small increments (synchronous — fine for a CLI command)\n const wait = Date.now() + 100;\n while (Date.now() < wait) { /* spin */ }\n }\n\n console.error(`[sisyphus] Daemon (pid ${pid}) did not exit within 5s, sending SIGKILL`);\n try {\n process.kill(pid, 'SIGKILL');\n } catch { /* already dead */ }\n releasePidLock();\n return true;\n}\n\nasync function recoverSessions(): Promise<void> {\n const registry = loadSessionRegistry();\n const entries = Object.entries(registry);\n\n if (entries.length === 0) {\n console.log('[sisyphus] No sessions to recover');\n return;\n }\n\n let recovered = 0;\n for (const [sessionId, cwd] of entries) {\n const stateFile = statePath(cwd, sessionId);\n if (!existsSync(stateFile)) {\n continue;\n }\n\n try {\n const session = JSON.parse(readFileSync(stateFile, 'utf-8')) as Session;\n if (session.status === 'active' || session.status === 'paused') {\n registerSessionCwd(sessionId, cwd);\n resetAgentCounterFromState(sessionId, session.agents ?? []);\n\n // Reconnect to tmux panes if info was persisted\n if (session.tmuxSessionName && session.tmuxWindowId) {\n const livePanes = listPanes(session.tmuxWindowId);\n if (livePanes.length > 0) {\n registerSessionTmux(sessionId, session.tmuxSessionName, session.tmuxWindowId);\n setWindowId(sessionId, session.tmuxWindowId);\n trackSession(sessionId, cwd, session.tmuxSessionName);\n updateTrackedWindow(sessionId, session.tmuxWindowId);\n\n // Recover orchestrator pane from last incomplete cycle\n const lastIncompleteCycle = [...session.orchestratorCycles].reverse().find(c => !c.completedAt && c.paneId);\n if (lastIncompleteCycle?.paneId) {\n setOrchestratorPaneId(sessionId, lastIncompleteCycle.paneId);\n }\n\n console.log(`[sisyphus] Reconnected session ${sessionId} to tmux window ${session.tmuxWindowId}`);\n\n // Detect sessions stuck in \"all agents done, no orchestrator\" state\n if (session.status === 'active' && session.agents.length > 0) {\n const hasRunningAgents = session.agents.some(a => a.status === 'running');\n if (!hasRunningAgents) {\n const livePaneIds = new Set(livePanes.map(p => p.paneId));\n const orchestratorPaneId = getOrchestratorPaneId(sessionId);\n const orchestratorAlive = orchestratorPaneId && livePaneIds.has(orchestratorPaneId);\n if (!orchestratorAlive) {\n console.log(`[sisyphus] Detected stuck session ${sessionId} on recovery: triggering orchestrator respawn`);\n await onAllAgentsDone(sessionId, cwd, session.tmuxWindowId!);\n }\n }\n }\n } else {\n // Window gone — pause the session so user can `sisyphus resume`\n if (session.status === 'active') {\n await stateModule.updateSessionStatus(cwd, sessionId, 'paused');\n console.log(`[sisyphus] Session ${sessionId} paused: tmux window no longer exists`);\n }\n }\n }\n\n recovered++;\n }\n } catch {\n console.error(`[sisyphus] Failed to read session state for ${sessionId}, skipping`);\n }\n }\n\n console.log(`[sisyphus] Recovered ${recovered} session(s) from registry`);\n}\n\nasync function startDaemon(): Promise<void> {\n console.log('[sisyphus] Starting daemon...');\n ensureDirs();\n acquirePidLock();\n\n const config = loadConfig(process.cwd());\n\n setRespawnCallback(onAllAgentsDone);\n\n await startServer();\n startMonitor(config.pollIntervalMs);\n\n await recoverSessions();\n\n const shutdown = async () => {\n console.log('[sisyphus] Shutting down...');\n stopMonitor();\n await stopServer();\n releasePidLock();\n process.exit(0);\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n\nconst command = process.argv[2];\n\nswitch (command) {\n case 'stop':\n stopDaemon();\n break;\n\n case 'restart': {\n stopDaemon();\n // Small delay to let socket release\n const wait = Date.now() + 500;\n while (Date.now() < wait) { /* spin */ }\n startDaemon().catch((err) => {\n console.error('[sisyphus] Fatal error:', err);\n process.exit(1);\n });\n break;\n }\n\n case 'start':\n case undefined:\n startDaemon().catch((err) => {\n console.error('[sisyphus] Fatal error:', err);\n process.exit(1);\n });\n break;\n\n default:\n console.error(`[sisyphus] Unknown command: ${command}`);\n console.error('Usage: sisyphusd [start|stop|restart]');\n process.exit(1);\n}\n","import { readFileSync } from 'node:fs';\nimport { globalConfigPath, projectConfigPath } from './paths.js';\n\nexport interface WorktreeConfig {\n copy?: string[];\n clone?: string[];\n symlink?: string[];\n init?: string;\n}\n\nexport interface Config {\n model?: string;\n tmuxSession?: string;\n orchestratorPrompt?: string;\n pollIntervalMs?: number;\n}\n\nconst DEFAULT_CONFIG: Config = {\n pollIntervalMs: 1000,\n};\n\nfunction readJsonFile(filePath: string): Partial<Config> {\n try {\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as Partial<Config>;\n } catch {\n return {};\n }\n}\n\nexport function loadConfig(cwd: string): Config {\n const global = readJsonFile(globalConfigPath());\n const project = readJsonFile(projectConfigPath(cwd));\n return { ...DEFAULT_CONFIG, ...global, ...project };\n}\n","import { createServer, type Server } from 'node:net';\nimport { unlinkSync, existsSync, writeFileSync, readFileSync, mkdirSync } from 'node:fs';\nimport { socketPath, globalDir } from '../shared/paths.js';\nimport { join } from 'node:path';\nimport type { Request, Response } from '../shared/protocol.js';\nimport * as sessionManager from './session-manager.js';\n\nlet server: Server | null = null;\n\n// Track the cwd for each session so we can route requests\nconst sessionCwdMap = new Map<string, string>();\n// Track the originating tmux session for each sisyphus session\nconst sessionTmuxMap = new Map<string, string>();\n// Track the originating tmux window for each sisyphus session\nconst sessionWindowMap = new Map<string, string>();\n\nexport function getSessionCwd(sessionId: string): string | undefined {\n return sessionCwdMap.get(sessionId);\n}\n\nexport function getSessionTmux(sessionId: string): string | undefined {\n return sessionTmuxMap.get(sessionId);\n}\n\nfunction registryPath(): string {\n return join(globalDir(), 'session-registry.json');\n}\n\nfunction persistSessionRegistry(): void {\n const dir = globalDir();\n mkdirSync(dir, { recursive: true });\n const registry: Record<string, string> = {};\n for (const [id, cwd] of sessionCwdMap) {\n registry[id] = cwd;\n }\n writeFileSync(registryPath(), JSON.stringify(registry, null, 2), 'utf-8');\n}\n\nexport function loadSessionRegistry(): Record<string, string> {\n const p = registryPath();\n if (!existsSync(p)) return {};\n try {\n return JSON.parse(readFileSync(p, 'utf-8')) as Record<string, string>;\n } catch {\n return {};\n }\n}\n\nexport function registerSessionCwd(sessionId: string, cwd: string): void {\n sessionCwdMap.set(sessionId, cwd);\n persistSessionRegistry();\n}\n\nexport function registerSessionTmux(sessionId: string, tmuxSession: string, windowId: string): void {\n sessionTmuxMap.set(sessionId, tmuxSession);\n sessionWindowMap.set(sessionId, windowId);\n}\n\nasync function handleRequest(req: Request): Promise<Response> {\n try {\n switch (req.type) {\n case 'start': {\n const session = await sessionManager.startSession(req.task, req.cwd, req.tmuxSession, req.tmuxWindow);\n registerSessionCwd(session.id, req.cwd);\n sessionTmuxMap.set(session.id, req.tmuxSession);\n sessionWindowMap.set(session.id, req.tmuxWindow);\n return { ok: true, data: { sessionId: session.id } };\n }\n\n case 'spawn': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const result = await sessionManager.handleSpawn(req.sessionId, cwd, req.agentType, req.name, req.instruction, req.worktree);\n return { ok: true, data: { agentId: result.agentId } };\n }\n\n case 'submit': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const windowId = sessionWindowMap.get(req.sessionId);\n if (!windowId) return { ok: false, error: `No tmux window found for session: ${req.sessionId}` };\n await sessionManager.handleSubmit(cwd, req.sessionId, req.agentId, req.report, windowId);\n return { ok: true };\n }\n\n case 'report': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleReport(cwd, req.sessionId, req.agentId, req.content);\n return { ok: true };\n }\n\n case 'yield': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleYield(req.sessionId, cwd, req.nextPrompt);\n return { ok: true };\n }\n\n case 'complete': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleComplete(req.sessionId, cwd, req.report);\n return { ok: true };\n }\n\n case 'status': {\n if (req.sessionId) {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const session = sessionManager.getSessionStatus(cwd, req.sessionId);\n return { ok: true, data: { session: session as unknown as Record<string, unknown> } };\n }\n return { ok: true, data: { message: 'daemon running' } };\n }\n\n case 'list': {\n const allSessions: Array<Record<string, unknown>> = [];\n if (req.all) {\n // List sessions across all known cwds\n const seenCwds = new Set<string>();\n for (const cwd of sessionCwdMap.values()) {\n if (seenCwds.has(cwd)) continue;\n seenCwds.add(cwd);\n const sessions = sessionManager.listSessions(cwd);\n allSessions.push(...sessions.map(s => ({ ...s, cwd } as unknown as Record<string, unknown>)));\n }\n } else {\n // List sessions for the requesting cwd only\n const sessions = sessionManager.listSessions(req.cwd);\n allSessions.push(...sessions.map(s => ({ ...s, cwd: req.cwd } as unknown as Record<string, unknown>)));\n // Count total across all cwds for the hint\n let totalCount = allSessions.length;\n const seenCwds = new Set<string>([req.cwd]);\n for (const cwd of sessionCwdMap.values()) {\n if (seenCwds.has(cwd)) continue;\n seenCwds.add(cwd);\n totalCount += sessionManager.listSessions(cwd).length;\n }\n if (totalCount > allSessions.length) {\n return { ok: true, data: { sessions: allSessions, totalCount, filtered: true } };\n }\n }\n return { ok: true, data: { sessions: allSessions } };\n }\n\n case 'resume': {\n let cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) {\n // Session not in memory — try to recover from disk using the cwd provided by CLI\n const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;\n if (existsSync(stateFile)) {\n cwd = req.cwd;\n registerSessionCwd(req.sessionId, cwd);\n } else {\n return { ok: false, error: `Unknown session: ${req.sessionId}. No state.json found at ${stateFile}` };\n }\n }\n sessionTmuxMap.set(req.sessionId, req.tmuxSession);\n sessionWindowMap.set(req.sessionId, req.tmuxWindow);\n const session = await sessionManager.resumeSession(req.sessionId, cwd, req.tmuxSession, req.tmuxWindow, req.message);\n return { ok: true, data: { sessionId: session.id, status: session.status } };\n }\n\n case 'register_claude_session': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n await sessionManager.handleRegisterClaudeSession(cwd, req.sessionId, req.agentId, req.claudeSessionId);\n return { ok: true };\n }\n\n case 'kill': {\n const cwd = sessionCwdMap.get(req.sessionId);\n if (!cwd) return { ok: false, error: `Unknown session: ${req.sessionId}` };\n const killedAgents = await sessionManager.handleKill(req.sessionId, cwd);\n sessionCwdMap.delete(req.sessionId);\n sessionTmuxMap.delete(req.sessionId);\n sessionWindowMap.delete(req.sessionId);\n persistSessionRegistry();\n return { ok: true, data: { killedAgents, sessionId: req.sessionId } };\n }\n\n default:\n return { ok: false, error: `Unknown request type: ${(req as Record<string, unknown>).type}` };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n\nexport function startServer(): Promise<Server> {\n return new Promise((resolve, reject) => {\n const sock = socketPath();\n\n if (existsSync(sock)) {\n unlinkSync(sock);\n }\n\n server = createServer((conn) => {\n let buffer = '';\n\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n const lines = buffer.split('\\n');\n buffer = lines.pop()!;\n\n for (const line of lines) {\n if (!line.trim()) continue;\n let req: Request;\n try {\n req = JSON.parse(line) as Request;\n } catch {\n conn.write(JSON.stringify({ ok: false, error: 'Invalid JSON' }) + '\\n');\n continue;\n }\n\n handleRequest(req).then((res) => {\n conn.write(JSON.stringify(res) + '\\n');\n });\n }\n });\n\n conn.on('error', (err) => {\n console.error('[sisyphus] Connection error:', err.message);\n });\n });\n\n server.on('error', reject);\n\n server.listen(sock, () => {\n console.log(`[sisyphus] Daemon listening on ${sock}`);\n resolve(server!);\n });\n });\n}\n\nexport function stopServer(): Promise<void> {\n return new Promise((resolve) => {\n if (!server) {\n resolve();\n return;\n }\n server.close(() => {\n const sock = socketPath();\n if (existsSync(sock)) {\n unlinkSync(sock);\n }\n server = null;\n resolve();\n });\n });\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { existsSync, readdirSync } from 'node:fs';\nimport * as state from './state.js';\nimport * as orchestrator from './orchestrator.js';\nimport * as tmux from './tmux.js';\nimport { spawnAgent, resetAgentCounterFromState, clearAgentCounter, handleAgentSubmit, handleAgentReport } from './agent.js';\nimport { trackSession, untrackSession, updateTrackedWindow } from './pane-monitor.js';\nimport { resetColors } from './colors.js';\nimport { sessionsDir } from '../shared/paths.js';\nimport type { Session } from '../shared/types.js';\nimport { mergeWorktrees, cleanupWorktree } from './worktree.js';\n\nexport async function startSession(task: string, cwd: string, tmuxSession: string, windowId: string): Promise<Session> {\n const sessionId = uuidv4();\n const session = state.createSession(sessionId, task, cwd);\n await state.updateSessionTmux(cwd, sessionId, tmuxSession, windowId);\n\n trackSession(sessionId, cwd, tmuxSession);\n await orchestrator.spawnOrchestrator(sessionId, cwd, windowId);\n updateTrackedWindow(sessionId, windowId);\n\n return session;\n}\n\nexport async function resumeSession(sessionId: string, cwd: string, tmuxSession: string, windowId: string, message?: string): Promise<Session> {\n const session = state.getSession(cwd, sessionId);\n\n if (session.status !== 'active') {\n // Determine which agents still have live panes\n const livePaneIds = new Set<string>();\n if (session.tmuxWindowId) {\n const panes = tmux.listPanes(session.tmuxWindowId);\n for (const pane of panes) {\n livePaneIds.add(pane.paneId);\n }\n }\n\n // Mark running agents as \"lost\" only if their pane is gone (or no window ID to check)\n for (const agent of session.agents) {\n if (agent.status === 'running') {\n const isAlive = agent.paneId != null && livePaneIds.has(agent.paneId);\n if (!isAlive) {\n await state.updateAgent(cwd, sessionId, agent.id, {\n status: 'lost',\n completedAt: new Date().toISOString(),\n killedReason: 'session resumed — agent was still running',\n });\n }\n }\n }\n }\n\n await state.updateSessionStatus(cwd, sessionId, 'active');\n await state.updateSessionTmux(cwd, sessionId, tmuxSession, windowId);\n\n // Reset counters based on existing agents\n resetAgentCounterFromState(sessionId, session.agents);\n resetColors(sessionId);\n\n trackSession(sessionId, cwd, tmuxSession);\n await orchestrator.spawnOrchestrator(sessionId, cwd, windowId, message);\n updateTrackedWindow(sessionId, windowId);\n\n return state.getSession(cwd, sessionId);\n}\n\nexport function getSessionStatus(cwd: string, sessionId: string): Session {\n return state.getSession(cwd, sessionId);\n}\n\nexport function listSessions(cwd: string): Array<{ id: string; task: string; status: string; createdAt: string; agentCount: number }> {\n const dir = sessionsDir(cwd);\n if (!existsSync(dir)) return [];\n\n const entries = readdirSync(dir, { withFileTypes: true });\n const sessions: Array<{ id: string; task: string; status: string; createdAt: string; agentCount: number }> = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n try {\n const session = state.getSession(cwd, entry.name);\n sessions.push({\n id: session.id,\n task: session.task,\n status: session.status,\n createdAt: session.createdAt,\n agentCount: session.agents.length,\n });\n } catch (err) {\n console.error(`[sisyphus] Failed to read session ${entry.name}:`, err);\n }\n }\n\n return sessions;\n}\n\nexport function onAllAgentsDone(sessionId: string, cwd: string, windowId: string): void {\n const session = state.getSession(cwd, sessionId);\n if (session.status !== 'active') return;\n\n // Merge any worktree agents before respawning orchestrator\n const worktreeAgents = session.agents.filter(a => a.worktreePath && a.mergeStatus === 'pending');\n if (worktreeAgents.length > 0) {\n const results = mergeWorktrees(cwd, worktreeAgents);\n for (const result of results) {\n const mergeStatus = result.status === 'conflict' ? 'conflict' as const : 'merged' as const;\n state.updateAgent(cwd, sessionId, result.agentId, {\n mergeStatus,\n mergeDetails: result.conflictDetails,\n }).catch((err: unknown) => console.error(`[sisyphus] Failed to update merge status for ${result.agentId}:`, err));\n }\n }\n\n // Delay to let /exit finish quitting the previous Claude session\n setTimeout(() => {\n orchestrator.spawnOrchestrator(sessionId, cwd, windowId)\n .then(() => updateTrackedWindow(sessionId, windowId))\n .catch((err: unknown) => console.error(`[sisyphus] Failed to respawn orchestrator for session ${sessionId}:`, err));\n }, 2000);\n}\n\nexport async function handleSpawn(\n sessionId: string,\n cwd: string,\n agentType: string,\n name: string,\n instruction: string,\n worktree?: boolean,\n): Promise<{ agentId: string }> {\n const windowId = orchestrator.getWindowId(sessionId);\n if (!windowId) throw new Error(`No tmux window found for session ${sessionId}`);\n\n const agent = await spawnAgent({\n sessionId,\n cwd,\n agentType,\n name,\n instruction,\n windowId,\n worktree,\n });\n\n await state.appendAgentToLastCycle(cwd, sessionId, agent.id);\n\n return { agentId: agent.id };\n}\n\nexport async function handleSubmit(cwd: string, sessionId: string, agentId: string, report: string, windowId: string): Promise<void> {\n const allDone = await handleAgentSubmit(cwd, sessionId, agentId, report);\n if (allDone) {\n onAllAgentsDone(sessionId, cwd, windowId);\n }\n}\n\nexport async function handleReport(cwd: string, sessionId: string, agentId: string, content: string): Promise<void> {\n await handleAgentReport(cwd, sessionId, agentId, content);\n}\n\nexport async function handleYield(sessionId: string, cwd: string, nextPrompt?: string): Promise<void> {\n await orchestrator.handleOrchestratorYield(sessionId, cwd, nextPrompt);\n}\n\nexport async function handleComplete(sessionId: string, cwd: string, report: string): Promise<void> {\n await orchestrator.handleOrchestratorComplete(sessionId, cwd, report);\n}\n\nexport async function handleRegisterClaudeSession(\n cwd: string,\n sessionId: string,\n agentId: string,\n claudeSessionId: string,\n): Promise<void> {\n await state.updateAgent(cwd, sessionId, agentId, { claudeSessionId });\n}\n\nexport async function handleKill(sessionId: string, cwd: string): Promise<number> {\n const session = state.getSession(cwd, sessionId);\n const windowId = orchestrator.getWindowId(sessionId);\n\n // Kill all running agents\n let killedAgents = 0;\n for (const agent of session.agents) {\n if (agent.status === 'running') {\n await state.updateAgent(cwd, sessionId, agent.id, {\n status: 'killed',\n killedReason: 'session killed by user',\n completedAt: new Date().toISOString(),\n });\n killedAgents++;\n }\n }\n\n // Clean up worktrees for agents that had them\n for (const agent of session.agents) {\n if (agent.worktreePath && agent.branchName) {\n cleanupWorktree(cwd, agent.worktreePath, agent.branchName);\n }\n }\n\n // Kill the orchestrator pane if it exists\n const orchPaneId = orchestrator.getOrchestratorPaneId(sessionId);\n if (orchPaneId) {\n tmux.killPane(orchPaneId);\n }\n\n // Mark session as completed\n await state.updateSessionStatus(cwd, sessionId, 'completed');\n\n // Untrack from pane monitor\n untrackSession(sessionId);\n\n // Kill the entire tmux window\n if (windowId) {\n tmux.killWindow(windowId);\n }\n\n // Clean up agent counter\n clearAgentCounter(sessionId);\n\n return killedAgents;\n}\n","import { readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type { Session, Agent, AgentReport, OrchestratorCycle, SessionStatus } from '../shared/types.js';\nimport { statePath, sessionDir, contextDir, promptsDir, planPath, logsPath } from '../shared/paths.js';\n\nconst PLAN_SEED = `---\ndescription: >\n Living document of what still needs to happen. Write your remaining work plan\n here: phases, next steps, file references, open questions. Remove or collapse\n items as they're completed so this file only reflects outstanding work. The\n orchestrator sees this every cycle — keep it focused and current.\n---\n`;\n\nconst LOGS_SEED = `---\ndescription: >\n Session memory. Record important observations, decisions, and findings here.\n This is your persistent memory across cycles: things you tried, what\n worked/failed, design decisions and their rationale, gotchas discovered during\n implementation. Unlike plan.md, entries here accumulate — they're a log.\n---\n`;\n\n// Per-session mutex to prevent read-modify-write races\nconst sessionLocks = new Map<string, Promise<void>>();\n\nasync function withSessionLock<T>(sessionId: string, fn: () => T): Promise<T> {\n const prev = sessionLocks.get(sessionId) ?? Promise.resolve();\n let resolve: () => void;\n const next = new Promise<void>(r => { resolve = r; });\n sessionLocks.set(sessionId, next);\n await prev;\n try {\n return fn();\n } finally {\n resolve!();\n }\n}\n\nfunction atomicWrite(filePath: string, data: string): void {\n const dir = dirname(filePath);\n const tmpPath = join(dir, `.state.${randomUUID()}.tmp`);\n writeFileSync(tmpPath, data, 'utf-8');\n renameSync(tmpPath, filePath);\n}\n\nexport function createSession(id: string, task: string, cwd: string): Session {\n const dir = sessionDir(cwd, id);\n mkdirSync(dir, { recursive: true });\n mkdirSync(contextDir(cwd, id), { recursive: true });\n mkdirSync(promptsDir(cwd, id), { recursive: true });\n\n writeFileSync(planPath(cwd, id), PLAN_SEED, 'utf-8');\n writeFileSync(logsPath(cwd, id), LOGS_SEED, 'utf-8');\n\n const session: Session = {\n id,\n task,\n cwd,\n status: 'active',\n createdAt: new Date().toISOString(),\n agents: [],\n orchestratorCycles: [],\n };\n\n atomicWrite(statePath(cwd, id), JSON.stringify(session, null, 2));\n return session;\n}\n\nexport function getSession(cwd: string, sessionId: string): Session {\n const content = readFileSync(statePath(cwd, sessionId), 'utf-8');\n return JSON.parse(content) as Session;\n}\n\nfunction saveSession(session: Session): void {\n atomicWrite(statePath(session.cwd, session.id), JSON.stringify(session, null, 2));\n}\n\nexport async function addAgent(cwd: string, sessionId: string, agent: Agent): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.agents.push(agent);\n saveSession(session);\n });\n}\n\nexport async function updateAgent(cwd: string, sessionId: string, agentId: string, updates: Partial<Agent>): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const agent = session.agents.slice().reverse().find((a: Agent) => a.id === agentId);\n if (!agent) throw new Error(`Agent ${agentId} not found in session ${sessionId}`);\n Object.assign(agent, updates);\n saveSession(session);\n });\n}\n\nexport async function addOrchestratorCycle(cwd: string, sessionId: string, cycle: OrchestratorCycle): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.orchestratorCycles.push(cycle);\n saveSession(session);\n });\n}\n\nexport async function updateSessionStatus(cwd: string, sessionId: string, status: SessionStatus, completionReport?: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.status = status;\n if (completionReport !== undefined) {\n session.completionReport = completionReport;\n }\n saveSession(session);\n });\n}\n\nexport async function appendAgentToLastCycle(cwd: string, sessionId: string, agentId: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const cycles = session.orchestratorCycles;\n if (cycles.length === 0) return;\n cycles[cycles.length - 1]!.agentsSpawned.push(agentId);\n saveSession(session);\n });\n}\n\nexport async function completeSession(cwd: string, sessionId: string, report: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.status = 'completed';\n session.completedAt = new Date().toISOString();\n session.completionReport = report;\n saveSession(session);\n });\n}\n\nexport async function appendAgentReport(cwd: string, sessionId: string, agentId: string, entry: AgentReport): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const agent = session.agents.slice().reverse().find((a: Agent) => a.id === agentId);\n if (!agent) throw new Error(`Agent ${agentId} not found in session ${sessionId}`);\n agent.reports.push(entry);\n saveSession(session);\n });\n}\n\nexport async function updateSessionTmux(cwd: string, sessionId: string, tmuxSessionName: string, tmuxWindowId: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n session.tmuxSessionName = tmuxSessionName;\n session.tmuxWindowId = tmuxWindowId;\n saveSession(session);\n });\n}\n\nexport async function completeOrchestratorCycle(cwd: string, sessionId: string, nextPrompt?: string): Promise<void> {\n return withSessionLock(sessionId, () => {\n const session = getSession(cwd, sessionId);\n const cycles = session.orchestratorCycles;\n if (cycles.length === 0) return;\n const cycle = cycles[cycles.length - 1]!;\n cycle.completedAt = new Date().toISOString();\n if (nextPrompt) cycle.nextPrompt = nextPrompt;\n saveSession(session);\n });\n}\n","import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { contextDir, logsPath, planPath, projectOrchestratorPromptPath, promptsDir, worktreeConfigPath } from '../shared/paths.js';\nimport type { Agent, Session } from '../shared/types.js';\nimport { ORCHESTRATOR_COLOR } from './colors.js';\nimport * as state from './state.js';\nimport * as tmux from './tmux.js';\n\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nconst sessionWindowMap = new Map<string, string>();\nconst sessionOrchestratorPane = new Map<string, string>();\n\nexport function getWindowId(sessionId: string): string | undefined {\n return sessionWindowMap.get(sessionId);\n}\n\nexport function setWindowId(sessionId: string, windowId: string): void {\n sessionWindowMap.set(sessionId, windowId);\n}\n\nexport function getOrchestratorPaneId(sessionId: string): string | undefined {\n return sessionOrchestratorPane.get(sessionId);\n}\n\nexport function setOrchestratorPaneId(sessionId: string, paneId: string): void {\n sessionOrchestratorPane.set(sessionId, paneId);\n}\n\nfunction loadOrchestratorPrompt(cwd: string): string {\n const projectPath = projectOrchestratorPromptPath(cwd);\n if (existsSync(projectPath)) {\n return readFileSync(projectPath, 'utf-8');\n }\n const bundledPath = resolve(import.meta.dirname, '../templates/orchestrator.md');\n return readFileSync(bundledPath, 'utf-8');\n}\n\nfunction formatStateForOrchestrator(session: Session): string {\n const shortId = session.id.slice(0, 8);\n const cycleNum = session.orchestratorCycles.length;\n\n const ctxDir = contextDir(session.cwd, session.id);\n let contextLines: string;\n if (existsSync(ctxDir)) {\n const files = readdirSync(ctxDir);\n contextLines = files.length > 0 ? files.map(f => `- ${f}`).join('\\n') : ' (none)';\n } else {\n contextLines = ' (none)';\n }\n\n const planFile = planPath(session.cwd, session.id);\n const planRef = existsSync(planFile) ? `@${planFile}` : '(empty)';\n\n const logsFile = logsPath(session.cwd, session.id);\n const logsRef = existsSync(logsFile) ? `@${logsFile}` : '(empty)';\n\n const agentLines = session.agents.length > 0\n ? session.agents.map((a: Agent) => {\n const header = `- ${a.id} (${a.name}): ${a.status} — ${a.reports.length} report(s)`;\n if (a.reports.length === 0) return header;\n let updateNum = 0;\n const reportLines = a.reports.map(r => {\n const label = r.type === 'final' ? '[final]' : `[update ${String(++updateNum).padStart(3, '0')}]`;\n return ` ${label} \"${r.summary}\" → ${r.filePath}`;\n });\n return [header, ...reportLines].join('\\n');\n }).join('\\n')\n : ' (none)';\n\n const cycleLines = session.orchestratorCycles.length > 0\n ? session.orchestratorCycles.map(c => {\n const spawnedList = c.agentsSpawned.length > 0 ? c.agentsSpawned.join(', ') : '(none)';\n return `Cycle ${c.cycle}: Spawned ${spawnedList}`;\n }).join('\\n')\n : ' (none)';\n\n // Worktree status — only if any agents have worktree info\n const worktreeAgents = session.agents.filter(a => a.worktreePath);\n let worktreeSection = '';\n if (worktreeAgents.length > 0) {\n const wtLines = worktreeAgents.map((a: Agent) => {\n if (a.mergeStatus === 'conflict') {\n return `- ${a.id}: conflict — ${a.mergeDetails ?? 'unknown'}\\n Branch: ${a.branchName}\\n Worktree: ${a.worktreePath}`;\n }\n const status = a.mergeStatus ?? 'pending';\n return `- ${a.id}: ${status} (branch ${a.branchName})`;\n }).join('\\n');\n worktreeSection = `\\n\\n## Worktrees\\n${wtLines}`;\n }\n\n // Worktree hint\n const worktreeHint = existsSync(worktreeConfigPath(session.cwd))\n ? 'Worktree config active (`.sisyphus/worktree.json`). Use `--worktree` flag with `sisyphus spawn` to isolate agents in their own worktrees. Recommended for feature work, especially with potential file overlap.'\n : 'No worktree configuration found. If this session involves parallel work where agents may edit overlapping files, use the `git-management` skill to set up `.sisyphus/worktree.json` and enable worktree isolation.';\n\n return `<state>\nsession: ${shortId} (cycle ${cycleNum})\ntask: ${session.task}\nstatus: ${session.status}\n\n## Plan\n${planRef}\n\n## Logs\n${logsRef}\n\n## Agents\n${agentLines}${worktreeSection}\n\n## Previous Cycles\n${cycleLines}\n\n## Context Files\n${contextLines}\n\n## Git Worktrees\n${worktreeHint}\n</state>`;\n}\n\nexport async function spawnOrchestrator(sessionId: string, cwd: string, windowId: string, message?: string): Promise<void> {\n const session = state.getSession(cwd, sessionId);\n const basePrompt = loadOrchestratorPrompt(cwd);\n const formattedState = formatStateForOrchestrator(session);\n\n // System prompt: template only (no state)\n const cycleNum = session.orchestratorCycles.length + 1;\n const promptFilePath = `${promptsDir(cwd, sessionId)}/orchestrator-system-${cycleNum}.md`;\n writeFileSync(promptFilePath, basePrompt, 'utf-8');\n\n sessionWindowMap.set(sessionId, windowId);\n\n const envExports = [\n `export SISYPHUS_SESSION_ID='${sessionId}'`,\n `export SISYPHUS_AGENT_ID='orchestrator'`,\n ].join(' && ');\n\n // User message: state block + contextual prompt\n let userPrompt: string;\n if (message) {\n userPrompt = `${formattedState}\\n\\nThe user resumed this session with new instructions: ${message}`;\n } else {\n // Check last completed cycle for a stored nextPrompt\n const lastCycle = [...session.orchestratorCycles].reverse().find(c => c.completedAt);\n const storedPrompt = lastCycle?.nextPrompt;\n if (storedPrompt) {\n userPrompt = `${formattedState}\\n\\n${storedPrompt}`;\n } else {\n userPrompt = `${formattedState}\\n\\nReview the current session and delegate the next cycle of work.`;\n }\n }\n\n const userPromptFilePath = `${promptsDir(cwd, sessionId)}/orchestrator-user-${cycleNum}.md`;\n writeFileSync(userPromptFilePath, userPrompt, 'utf-8');\n const pluginPath = resolve(import.meta.dirname, '../templates/orchestrator-plugin');\n const settingsPath = resolve(import.meta.dirname, '../templates/orchestrator-settings.json');\n const claudeCmd = `claude --dangerously-skip-permissions --settings \"${settingsPath}\" --plugin-dir \"${pluginPath}\" --append-system-prompt \"$(cat '${promptFilePath}')\" \"$(cat '${userPromptFilePath}')\"`;\n\n const paneId = tmux.createPane(windowId, cwd);\n\n sessionOrchestratorPane.set(sessionId, paneId);\n tmux.setPaneTitle(paneId, `orchestrator (${sessionId.slice(0, 8)})`);\n tmux.setPaneStyle(paneId, ORCHESTRATOR_COLOR);\n\n const bannerPath = resolve(import.meta.dirname, '../templates/banner.txt');\n const bannerCmd = existsSync(bannerPath) ? `cat '${bannerPath}' &&` : '';\n tmux.sendKeys(paneId, `${bannerCmd} ${envExports} && ${claudeCmd}`);\n\n await state.addOrchestratorCycle(cwd, sessionId, {\n cycle: cycleNum,\n timestamp: new Date().toISOString(),\n agentsSpawned: [],\n paneId,\n });\n}\n\nfunction resolveOrchestratorPane(sessionId: string, cwd: string): string | undefined {\n const memPane = sessionOrchestratorPane.get(sessionId);\n if (memPane) return memPane;\n const session = state.getSession(cwd, sessionId);\n const lastCycle = session.orchestratorCycles[session.orchestratorCycles.length - 1];\n return lastCycle?.paneId ?? undefined;\n}\n\nexport async function handleOrchestratorYield(sessionId: string, cwd: string, nextPrompt?: string): Promise<void> {\n const paneId = resolveOrchestratorPane(sessionId, cwd);\n if (paneId) {\n tmux.killPane(paneId);\n sessionOrchestratorPane.delete(sessionId);\n }\n\n const windowId = sessionWindowMap.get(sessionId);\n if (windowId) tmux.selectLayout(windowId);\n\n await state.completeOrchestratorCycle(cwd, sessionId, nextPrompt);\n\n const session = state.getSession(cwd, sessionId);\n const runningAgents = session.agents.filter(a => a.status === 'running');\n if (runningAgents.length === 0) {\n console.error(`[sisyphus] WARNING: Orchestrator yielded but no agents are running for session ${sessionId}`);\n }\n}\n\nexport async function handleOrchestratorComplete(sessionId: string, cwd: string, report: string): Promise<void> {\n await state.completeOrchestratorCycle(cwd, sessionId);\n await state.completeSession(cwd, sessionId, report);\n\n console.log(`[sisyphus] Session ${sessionId} completed: ${report}`);\n}\n\nexport function cleanupSessionMaps(sessionId: string): void {\n sessionOrchestratorPane.delete(sessionId);\n sessionWindowMap.delete(sessionId);\n}\n","import { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport const ORCHESTRATOR_COLOR = 'yellow';\n\nconst AGENT_PALETTE = ['blue', 'green', 'magenta', 'cyan', 'red', 'white'] as const;\n\nconst TMUX_COLOR_MAP: Record<string, string> = {\n orange: 'colour208',\n teal: 'colour6',\n};\n\nfunction normalizeTmuxColor(color: string): string {\n return TMUX_COLOR_MAP[color] ?? color;\n}\n\nconst sessionColorIndex = new Map<string, number>();\n\nexport function getNextColor(sessionId: string): string {\n const idx = sessionColorIndex.get(sessionId) ?? 0;\n const color = AGENT_PALETTE[idx % AGENT_PALETTE.length]!;\n sessionColorIndex.set(sessionId, idx + 1);\n return color;\n}\n\nexport function resetColors(sessionId: string): void {\n sessionColorIndex.delete(sessionId);\n}\n\nfunction extractFrontmatterColor(content: string): string | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const colorMatch = match[1]!.match(/^color:\\s*(.+)$/m);\n return colorMatch ? colorMatch[1]!.trim() : null;\n}\n\nfunction findPluginInstallPath(namespace: string): string | null {\n try {\n const registryPath = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');\n const registry = JSON.parse(readFileSync(registryPath, 'utf-8'));\n for (const key of Object.keys(registry)) {\n if (key.startsWith(`${namespace}@`)) {\n return registry[key].installPath ?? null;\n }\n }\n } catch {\n // File missing, parse error, or no match\n }\n return null;\n}\n\nexport function resolveAgentTypeColor(agentType: string, pluginDir: string, cwd: string): string | null {\n if (!agentType) return null;\n\n let namespace: string | undefined;\n let name: string;\n\n if (agentType.includes(':')) {\n [namespace, name] = agentType.split(':', 2) as [string, string];\n } else {\n name = agentType;\n }\n\n const searchPaths: string[] = [];\n\n if (namespace) {\n // Bundled (handles sisyphus:* via pluginDir)\n searchPaths.push(join(pluginDir, 'agents', `${name}.md`));\n // Installed plugin\n const installPath = findPluginInstallPath(namespace);\n if (installPath) {\n searchPaths.push(join(installPath, 'agents', `${name}.md`));\n }\n } else {\n // Project-local\n searchPaths.push(join(cwd, '.claude', 'agents', `${name}.md`));\n // User-global\n searchPaths.push(join(homedir(), '.claude', 'agents', `${name}.md`));\n // Bundled\n searchPaths.push(join(pluginDir, 'agents', `${name}.md`));\n }\n\n for (const path of searchPaths) {\n try {\n const content = readFileSync(path, 'utf-8');\n const color = extractFrontmatterColor(content);\n if (color) return normalizeTmuxColor(color);\n } catch {\n // File doesn't exist, try next\n }\n }\n\n return null;\n}\n","import { execSync } from 'node:child_process';\n\nconst EXEC_ENV = {\n ...process.env,\n PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env['PATH'] ?? '/usr/bin:/bin'}`,\n};\n\nfunction exec(cmd: string): string {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV }).trim();\n}\n\nfunction execSafe(cmd: string): string | null {\n try {\n return exec(cmd);\n } catch {\n return null;\n }\n}\n\nexport function getCurrentTmuxSession(): string {\n const tmuxEnv = process.env['TMUX'];\n if (!tmuxEnv) throw new Error('Not running inside tmux');\n return exec('tmux display-message -p \"#{session_name}\"');\n}\n\nexport function createWindow(sessionName: string, windowName: string, cwd?: string): string {\n const cwdFlag = cwd ? ` -c ${shellQuote(cwd)}` : '';\n exec(`tmux new-window -t \"${sessionName}\" -n \"${windowName}\"${cwdFlag} -P -F \"#{window_id}\"`);\n return exec(`tmux display-message -t \"${sessionName}:${windowName}\" -p \"#{window_id}\"`);\n}\n\nexport function createPane(windowTarget: string, cwd?: string): string {\n const cwdFlag = cwd ? ` -c ${shellQuote(cwd)}` : '';\n const paneId = exec(`tmux split-window -h -t \"${windowTarget}\"${cwdFlag} -P -F \"#{pane_id}\"`);\n execSafe(`tmux select-layout -t \"${windowTarget}\" even-horizontal`);\n return paneId;\n}\n\nexport function sendKeys(paneTarget: string, command: string): void {\n exec(`tmux send-keys -t \"${paneTarget}\" ${shellQuote(command)} Enter`);\n}\n\nexport function killPane(paneTarget: string): void {\n execSafe(`tmux kill-pane -t \"${paneTarget}\"`);\n}\n\nexport function killWindow(windowTarget: string): void {\n execSafe(`tmux kill-window -t \"${windowTarget}\"`);\n}\n\nexport interface PaneInfo {\n paneId: string;\n panePid: string;\n}\n\nexport function listPanes(windowTarget: string): PaneInfo[] {\n const output = execSafe(`tmux list-panes -t \"${windowTarget}\" -F \"#{pane_id} #{pane_pid}\"`);\n if (!output) return [];\n return output\n .split('\\n')\n .filter(Boolean)\n .map(line => {\n const [paneId, panePid] = line.split(' ');\n return { paneId: paneId!, panePid: panePid! };\n });\n}\n\nexport function setPaneTitle(paneTarget: string, title: string): void {\n execSafe(`tmux select-pane -t \"${paneTarget}\" -T ${shellQuote(title)}`);\n}\n\nexport function setPaneStyle(paneTarget: string, color: string): void {\n const fmt = `#[fg=${color},bold] #{pane_title} #[fg=${color}]#{pane_current_path} #[default]`;\n execSafe(`tmux set -p -t \"${paneTarget}\" pane-border-format ${shellQuote(fmt)}`);\n // Store color as a per-pane user variable. The window-level border styles use a\n // format string that resolves #{@pane_color} per-pane at render time, giving each\n // pane its own border color (pane-border-style itself is window-level / last-write-wins).\n execSafe(`tmux set -p -t \"${paneTarget}\" @pane_color \"${color}\"`);\n execSafe(`tmux set -w -t \"${paneTarget}\" pane-border-style \"fg=#{?#{@pane_color},#{@pane_color},default}\"`);\n execSafe(`tmux set -w -t \"${paneTarget}\" pane-active-border-style \"fg=#{?#{@pane_color},#{@pane_color},default}\"`);\n}\n\nexport function sendSignal(paneTarget: string, signal: string): void {\n const info = execSafe(`tmux list-panes -t \"${paneTarget}\" -F \"#{pane_pid}\"`);\n if (!info) return;\n const pid = info.split('\\n')[0]?.trim();\n if (pid) {\n execSafe(`kill -${signal} ${pid}`);\n }\n}\n\nexport function selectLayout(windowTarget: string, layout: string = 'even-horizontal'): void {\n execSafe(`tmux select-layout -t \"${windowTarget}\" ${layout}`);\n}\n\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n","import { readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { Agent, AgentReport } from '../shared/types.js';\nimport * as state from './state.js';\nimport * as tmux from './tmux.js';\nimport { getNextColor, resolveAgentTypeColor } from './colors.js';\nimport { getWindowId } from './orchestrator.js';\nimport { promptsDir, reportsDir, reportFilePath } from '../shared/paths.js';\nimport { createWorktree, countWorktreeAgents } from './worktree.js';\n\nconst agentCounters = new Map<string, number>();\n\nexport function resetAgentCounter(sessionId: string, value: number = 0): void {\n agentCounters.set(sessionId, value);\n}\n\nexport function resetAgentCounterFromState(sessionId: string, agents: { id: string }[]): void {\n let max = 0;\n for (const a of agents) {\n const match = a.id.match(/^agent-(\\d+)$/);\n if (match) max = Math.max(max, parseInt(match[1]!, 10));\n }\n agentCounters.set(sessionId, max);\n}\n\nexport function clearAgentCounter(sessionId: string): void {\n agentCounters.delete(sessionId);\n}\n\ninterface WorktreeContext {\n offset: number;\n total: number;\n branchName: string;\n}\n\nfunction renderAgentSuffix(sessionId: string, instruction: string, worktreeContext?: WorktreeContext): string {\n const templatePath = resolve(import.meta.dirname, '../templates/agent-suffix.md');\n let template: string;\n try {\n template = readFileSync(templatePath, 'utf-8');\n } catch {\n template = `# Sisyphus Agent\\nSession: {{SESSION_ID}}\\nTask: {{INSTRUCTION}}`;\n }\n\n let worktreeBlock = '';\n if (worktreeContext) {\n worktreeBlock = [\n '## Worktree Context',\n `You are working in worktree ${worktreeContext.offset} of ${worktreeContext.total} concurrent worktrees on branch \\`${worktreeContext.branchName}\\`.`,\n `If you start any services that require ports, add ${worktreeContext.offset} to the default port.`,\n ].join('\\n');\n }\n\n return template\n .replace(/\\{\\{SESSION_ID\\}\\}/g, sessionId)\n .replace(/\\{\\{INSTRUCTION\\}\\}/g, instruction)\n .replace(/\\{\\{WORKTREE_CONTEXT\\}\\}/g, worktreeBlock);\n}\n\nexport interface SpawnAgentOpts {\n sessionId: string;\n cwd: string;\n agentType: string;\n name: string;\n instruction: string;\n windowId: string;\n worktree?: boolean;\n}\n\nexport async function spawnAgent(opts: SpawnAgentOpts): Promise<Agent> {\n const { sessionId, cwd, agentType, name, instruction, windowId } = opts;\n const count = (agentCounters.get(sessionId) ?? 0) + 1;\n agentCounters.set(sessionId, count);\n const agentId = `agent-${String(count).padStart(3, '0')}`;\n const pluginPath = resolve(import.meta.dirname, '../templates/agent-plugin');\n const color = resolveAgentTypeColor(agentType, pluginPath, cwd) ?? getNextColor(sessionId);\n\n let paneCwd = cwd;\n let worktreePath: string | undefined;\n let branchName: string | undefined;\n let worktreeContext: WorktreeContext | undefined;\n\n if (opts.worktree) {\n const wt = createWorktree(cwd, sessionId, agentId);\n worktreePath = wt.worktreePath;\n branchName = wt.branchName;\n paneCwd = worktreePath;\n\n const session = state.getSession(cwd, sessionId);\n const portOffset = countWorktreeAgents(session.agents) + 1;\n worktreeContext = { offset: portOffset, total: portOffset, branchName };\n }\n\n const paneId = tmux.createPane(windowId, paneCwd);\n tmux.setPaneTitle(paneId, `${name} (${agentId})`);\n tmux.setPaneStyle(paneId, color);\n\n const suffix = renderAgentSuffix(sessionId, instruction, worktreeContext);\n const suffixFilePath = `${promptsDir(cwd, sessionId)}/${agentId}-system.md`;\n writeFileSync(suffixFilePath, suffix, 'utf-8');\n\n const bannerPath = resolve(import.meta.dirname, '../templates/banner.txt');\n const bannerCmd = existsSync(bannerPath) ? `cat '${bannerPath}' &&` : '';\n\n const envExports = [\n `export SISYPHUS_SESSION_ID='${sessionId}'`,\n `export SISYPHUS_AGENT_ID='${agentId}'`,\n ...(worktreeContext ? [`export SISYPHUS_PORT_OFFSET='${worktreeContext.offset}'`] : []),\n ].join(' && ');\n\n const agentFlag = agentType ? ` --agent ${shellQuote(agentType)}` : '';\n const claudeCmd = `claude --dangerously-skip-permissions --plugin-dir \"${pluginPath}\"${agentFlag} --append-system-prompt \"$(cat '${suffixFilePath}')\" ${shellQuote(instruction)}`;\n tmux.sendKeys(paneId, `${bannerCmd} ${envExports} && ${claudeCmd}`);\n\n const agent: Agent = {\n id: agentId,\n name,\n agentType,\n color,\n instruction,\n status: 'running',\n spawnedAt: new Date().toISOString(),\n completedAt: null,\n reports: [],\n paneId,\n ...(worktreePath ? { worktreePath, branchName, mergeStatus: 'pending' as const } : {}),\n };\n\n await state.addAgent(cwd, sessionId, agent);\n return agent;\n}\n\nfunction nextReportNumber(cwd: string, sessionId: string, agentId: string): string {\n const dir = reportsDir(cwd, sessionId);\n try {\n const files = readdirSync(dir).filter(f => f.startsWith(`${agentId}-`) && !f.endsWith('-final.md'));\n return String(files.length + 1).padStart(3, '0');\n } catch {\n return '001';\n }\n}\n\nexport async function handleAgentReport(\n cwd: string,\n sessionId: string,\n agentId: string,\n content: string,\n): Promise<void> {\n const dir = reportsDir(cwd, sessionId);\n mkdirSync(dir, { recursive: true });\n\n const num = nextReportNumber(cwd, sessionId, agentId);\n const filePath = reportFilePath(cwd, sessionId, agentId, num);\n writeFileSync(filePath, content, 'utf-8');\n\n const entry: AgentReport = {\n type: 'update',\n filePath,\n summary: content.slice(0, 200),\n timestamp: new Date().toISOString(),\n };\n await state.appendAgentReport(cwd, sessionId, agentId, entry);\n}\n\nexport async function handleAgentSubmit(\n cwd: string,\n sessionId: string,\n agentId: string,\n report: string,\n): Promise<boolean> {\n const dir = reportsDir(cwd, sessionId);\n mkdirSync(dir, { recursive: true });\n\n const filePath = reportFilePath(cwd, sessionId, agentId, 'final');\n writeFileSync(filePath, report, 'utf-8');\n\n const entry: AgentReport = {\n type: 'final',\n filePath,\n summary: report.slice(0, 200),\n timestamp: new Date().toISOString(),\n };\n await state.appendAgentReport(cwd, sessionId, agentId, entry);\n\n await state.updateAgent(cwd, sessionId, agentId, {\n status: 'completed',\n completedAt: new Date().toISOString(),\n });\n\n const session = state.getSession(cwd, sessionId);\n const agentArr = session.agents;\n const agent = agentArr.slice().reverse().find(a => a.id === agentId);\n if (agent) {\n tmux.killPane(agent.paneId);\n }\n\n const windowId = getWindowId(sessionId);\n if (windowId) tmux.selectLayout(windowId);\n\n return allAgentsDone(session);\n}\n\nexport async function handleAgentKilled(\n cwd: string,\n sessionId: string,\n agentId: string,\n reason: string,\n): Promise<boolean> {\n await state.updateAgent(cwd, sessionId, agentId, {\n status: 'killed',\n killedReason: reason,\n completedAt: new Date().toISOString(),\n });\n\n const session = state.getSession(cwd, sessionId);\n return allAgentsDone(session);\n}\n\n// Note: this checks ALL running agents in the session, not just orchestrator-spawned ones.\n// Agents can also call `sisyphus spawn`, and those child agents are included here —\n// the orchestrator won't respawn until every agent (including agent-spawned ones) finishes.\nfunction allAgentsDone(session: import('../shared/types.js').Session): boolean {\n const running = session.agents.filter(a => a.status === 'running');\n return running.length === 0 && session.agents.length > 0;\n}\n\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readFileSync, readdirSync, rmSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { Agent } from '../shared/types.js';\nimport type { WorktreeConfig } from '../shared/config.js';\nimport { worktreeConfigPath, worktreeBaseDir } from '../shared/paths.js';\n\nconst EXEC_ENV = {\n ...process.env,\n PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env['PATH'] ?? '/usr/bin:/bin'}`,\n};\n\nfunction exec(cmd: string, cwd?: string): string {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV, cwd }).trim();\n}\n\nfunction execSafe(cmd: string, cwd?: string): string | null {\n try {\n return exec(cmd, cwd);\n } catch {\n return null;\n }\n}\n\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nexport interface MergeResult {\n agentId: string;\n name: string;\n status: 'merged' | 'conflict' | 'no-changes';\n conflictDetails?: string;\n}\n\nexport function loadWorktreeConfig(cwd: string): WorktreeConfig | null {\n try {\n const content = readFileSync(worktreeConfigPath(cwd), 'utf-8');\n return JSON.parse(content) as WorktreeConfig;\n } catch {\n return null;\n }\n}\n\nexport function createWorktree(\n cwd: string,\n sessionId: string,\n agentId: string,\n): { worktreePath: string; branchName: string } {\n const branchName = `sisyphus/${sessionId.slice(0, 8)}/${agentId}`;\n const worktreePath = join(worktreeBaseDir(cwd), agentId);\n\n mkdirSync(dirname(worktreePath), { recursive: true });\n\n exec(`git -C ${shellQuote(cwd)} branch ${shellQuote(branchName)} HEAD`);\n exec(`git -C ${shellQuote(cwd)} worktree add ${shellQuote(worktreePath)} ${shellQuote(branchName)}`);\n\n // Always symlink .sisyphus and .claude from cwd into worktree\n const symlinks = ['.sisyphus', '.claude'];\n for (const entry of symlinks) {\n const src = join(cwd, entry);\n if (existsSync(src)) {\n execSafe(`ln -s ${shellQuote(src)} ${shellQuote(join(worktreePath, entry))}`);\n }\n }\n\n // Load worktree config and bootstrap if present\n const config = loadWorktreeConfig(cwd);\n if (config) {\n bootstrapWorktree(cwd, worktreePath, config);\n }\n\n return { worktreePath, branchName };\n}\n\nexport function bootstrapWorktree(cwd: string, worktreePath: string, config: WorktreeConfig): void {\n // Process copy entries\n if (config.copy) {\n for (const entry of config.copy) {\n const dest = join(worktreePath, entry);\n mkdirSync(dirname(dest), { recursive: true });\n execSafe(`cp -r ${shellQuote(join(cwd, entry))} ${shellQuote(dest)}`);\n }\n }\n\n // Process clone entries (APFS CoW on macOS, fallback to cp -r)\n if (config.clone) {\n for (const entry of config.clone) {\n const dest = join(worktreePath, entry);\n mkdirSync(dirname(dest), { recursive: true });\n const src = shellQuote(join(cwd, entry));\n const dstQ = shellQuote(dest);\n if (execSafe(`cp -Rc ${src} ${dstQ}`) === null) {\n execSafe(`cp -r ${src} ${dstQ}`);\n }\n }\n }\n\n // Process symlink entries\n if (config.symlink) {\n for (const entry of config.symlink) {\n const dest = join(worktreePath, entry);\n mkdirSync(dirname(dest), { recursive: true });\n execSafe(`ln -s ${shellQuote(join(cwd, entry))} ${shellQuote(dest)}`);\n }\n }\n\n // Process init command\n if (config.init) {\n try {\n exec(config.init, worktreePath);\n } catch (err) {\n console.error(`[sisyphus] worktree init command failed: ${err instanceof Error ? err.message : err}`);\n }\n }\n}\n\n/**\n * Resolve the branch checked out in a worktree by parsing `git worktree list --porcelain`.\n * Returns null if the worktree isn't found or has a detached HEAD.\n */\nfunction resolveWorktreeBranch(cwd: string, worktreePath: string): string | null {\n const output = execSafe(`git -C ${shellQuote(cwd)} worktree list --porcelain`);\n if (!output) return null;\n\n const lines = output.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n if (lines[i] === `worktree ${worktreePath}`) {\n for (let j = i + 1; j < lines.length; j++) {\n const line = lines[j]!;\n if (line === '') break; // end of this worktree block\n if (line.startsWith('branch refs/heads/')) {\n return line.slice('branch refs/heads/'.length);\n }\n }\n break;\n }\n }\n return null;\n}\n\nexport function mergeWorktrees(cwd: string, agents: Agent[]): MergeResult[] {\n const pending = agents.filter(\n a => a.worktreePath && a.mergeStatus === 'pending',\n );\n\n const results: MergeResult[] = [];\n\n for (const agent of pending) {\n const branch = resolveWorktreeBranch(cwd, agent.worktreePath!);\n\n if (!branch) {\n results.push({ agentId: agent.id, name: agent.name, status: 'no-changes' });\n // Best-effort cleanup — branch name unknown, just remove worktree dir\n execSafe(`git -C ${shellQuote(cwd)} worktree remove ${shellQuote(agent.worktreePath!)} --force`);\n continue;\n }\n\n // Check if branch has commits ahead of merge base\n const aheadLog = execSafe(`git -C ${shellQuote(cwd)} log HEAD..${shellQuote(branch)} --oneline`);\n if (!aheadLog) {\n results.push({ agentId: agent.id, name: agent.name, status: 'no-changes' });\n cleanupWorktree(cwd, agent.worktreePath!, branch);\n continue;\n }\n\n // Attempt merge — capture stderr on failure for conflict details\n const mergeMsg = `sisyphus: merge ${agent.id} (${agent.name})`;\n const mergeCmd = `git -C ${shellQuote(cwd)} merge --no-ff ${shellQuote(branch)} -m ${shellQuote(mergeMsg)}`;\n\n try {\n exec(mergeCmd);\n // Merge succeeded — clean up worktree and branch\n execSafe(`git -C ${shellQuote(cwd)} worktree remove ${shellQuote(agent.worktreePath!)}`);\n execSafe(`git -C ${shellQuote(cwd)} branch -d ${shellQuote(branch)}`);\n results.push({ agentId: agent.id, name: agent.name, status: 'merged' });\n } catch (err: unknown) {\n // Merge failed — abort and leave worktree intact for manual resolution\n execSafe(`git -C ${shellQuote(cwd)} merge --abort`);\n const stderr = (err as { stderr?: Buffer | string })?.stderr;\n const conflictDetails = stderr\n ? (typeof stderr === 'string' ? stderr : stderr.toString('utf-8')).trim()\n : (err instanceof Error ? err.message : String(err));\n results.push({ agentId: agent.id, name: agent.name, status: 'conflict', conflictDetails });\n }\n }\n\n return results;\n}\n\nexport function cleanupWorktree(cwd: string, worktreePath: string, branchName: string): void {\n execSafe(`git -C ${shellQuote(cwd)} worktree remove ${shellQuote(worktreePath)} --force`);\n execSafe(`git -C ${shellQuote(cwd)} branch -D ${shellQuote(branchName)}`);\n\n // Remove the worktree base dir if empty\n const baseDir = dirname(worktreePath);\n try {\n const entries = readdirSync(baseDir);\n if (entries.length === 0) {\n rmSync(baseDir, { recursive: true });\n }\n } catch {\n // Ignore — directory may already be gone\n }\n}\n\nexport function countWorktreeAgents(agents: Agent[]): number {\n return agents.filter(a => a.worktreePath && a.status === 'running').length;\n}\n","import * as state from './state.js';\nimport * as tmux from './tmux.js';\nimport { getOrchestratorPaneId, cleanupSessionMaps } from './orchestrator.js';\nimport { handleAgentKilled } from './agent.js';\n\ntype RespawnCallback = (sessionId: string, cwd: string, windowId: string) => void;\n\nlet monitorInterval: ReturnType<typeof setInterval> | null = null;\nlet onAllAgentsDone: RespawnCallback | null = null;\n\nexport function setRespawnCallback(cb: RespawnCallback): void {\n onAllAgentsDone = cb;\n}\n\nexport function startMonitor(pollIntervalMs: number = 1000): void {\n if (monitorInterval) return;\n monitorInterval = setInterval(() => {\n pollAllSessions().catch(err => {\n console.error('[sisyphus] Pane monitor error:', err);\n });\n }, pollIntervalMs);\n}\n\nexport function stopMonitor(): void {\n if (monitorInterval) {\n clearInterval(monitorInterval);\n monitorInterval = null;\n }\n}\n\nconst trackedSessions = new Map<string, { id: string; cwd: string; tmuxSession: string; windowId: string | null }>();\n\nexport function trackSession(sessionId: string, cwd: string, tmuxSession: string): void {\n // windowId is registered separately via updateTrackedWindow after spawnOrchestrator sets it\n const existing = trackedSessions.get(sessionId);\n trackedSessions.set(sessionId, { id: sessionId, cwd, tmuxSession, windowId: existing ? existing.windowId : null });\n}\n\nexport function updateTrackedWindow(sessionId: string, windowId: string): void {\n const entry = trackedSessions.get(sessionId);\n if (!entry) throw new Error(`Cannot update window for untracked session: ${sessionId}`);\n entry.windowId = windowId;\n}\n\nexport function untrackSession(sessionId: string): void {\n trackedSessions.delete(sessionId);\n}\n\nasync function pollAllSessions(): Promise<void> {\n for (const { id: sessionId, cwd, windowId } of trackedSessions.values()) {\n if (windowId) {\n await pollSession(sessionId, cwd, windowId);\n }\n }\n}\n\nasync function pollSession(sessionId: string, cwd: string, windowId: string): Promise<void> {\n let session;\n try {\n session = state.getSession(cwd, sessionId);\n } catch (err) {\n console.error(`[sisyphus] Failed to read state for session ${sessionId}:`, err);\n return;\n }\n\n if (session.status === 'completed') {\n const orchPaneId = getOrchestratorPaneId(sessionId);\n if (orchPaneId) {\n const livePanes = tmux.listPanes(windowId);\n const livePaneIds = new Set(livePanes.map(p => p.paneId));\n if (!livePaneIds.has(orchPaneId)) {\n cleanupSessionMaps(sessionId);\n untrackSession(sessionId);\n console.log(`[sisyphus] Session ${sessionId} cleaned up: orchestrator pane closed by user`);\n }\n } else {\n // No orchestrator pane tracked — clean up immediately\n cleanupSessionMaps(sessionId);\n untrackSession(sessionId);\n }\n return;\n }\n\n if (session.status !== 'active') return;\n\n const livePanes = tmux.listPanes(windowId);\n if (livePanes.length === 0) return;\n\n const livePaneIds = new Set(livePanes.map(p => p.paneId));\n\n let paneRemoved = false;\n for (const agent of session.agents) {\n if (agent.status !== 'running') continue;\n if (!livePaneIds.has(agent.paneId)) {\n paneRemoved = true;\n const allDone = await handleAgentKilled(cwd, sessionId, agent.id, 'pane closed by user');\n if (allDone && onAllAgentsDone) {\n onAllAgentsDone(sessionId, cwd, windowId);\n }\n }\n }\n\n if (paneRemoved) tmux.selectLayout(windowId);\n\n // Check orchestrator pane\n const orchPaneId = getOrchestratorPaneId(sessionId);\n if (orchPaneId && !livePaneIds.has(orchPaneId)) {\n // Orchestrator pane disappeared without a yield command\n const runningAgents = session.agents.filter(a => a.status === 'running');\n if (runningAgents.length === 0) {\n // No agents running and orchestrator gone — pause\n await state.updateSessionStatus(cwd, sessionId, 'paused');\n console.log(`[sisyphus] Session ${sessionId} paused: orchestrator pane disappeared`);\n }\n }\n\n // Re-read state since handleAgentKilled may have mutated it\n session = state.getSession(cwd, sessionId);\n if (\n session.status === 'active' &&\n session.agents.length > 0 &&\n session.agents.every(a => a.status !== 'running') &&\n (!orchPaneId || !livePaneIds.has(orchPaneId)) &&\n onAllAgentsDone\n ) {\n console.log(`[sisyphus] Detected stuck session ${sessionId}: all agents done, no orchestrator — triggering respawn`);\n onAllAgentsDone(sessionId, cwd, windowId);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAAA,YAAW,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,cAAAC,mBAAkB;;;ACA/E,SAAS,oBAAoB;AAiB7B,IAAM,iBAAyB;AAAA,EAC7B,gBAAgB;AAClB;AAEA,SAAS,aAAa,UAAmC;AACvD,MAAI;AACF,UAAM,UAAU,aAAa,UAAU,OAAO;AAC9C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,WAAW,KAAqB;AAC9C,QAAM,SAAS,aAAa,iBAAiB,CAAC;AAC9C,QAAM,UAAU,aAAa,kBAAkB,GAAG,CAAC;AACnD,SAAO,EAAE,GAAG,gBAAgB,GAAG,QAAQ,GAAG,QAAQ;AACpD;;;AClCA,SAAS,oBAAiC;AAC1C,SAAS,YAAY,cAAAC,aAAY,iBAAAC,gBAAe,gBAAAC,eAAc,aAAAC,kBAAiB;AAE/E,SAAS,QAAAC,aAAY;;;ACHrB,SAAS,MAAM,cAAc;AAC7B,SAAS,cAAAC,aAAY,eAAAC,oBAAmB;;;ACDxC,SAAS,gBAAAC,eAAc,eAAe,WAAW,kBAAkB;AACnE,SAAS,SAAS,YAAY;AAC9B,SAAS,kBAAkB;AAI3B,IAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASlB,IAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUlB,IAAM,eAAe,oBAAI,IAA2B;AAEpD,eAAe,gBAAmB,WAAmB,IAAyB;AAC5E,QAAM,OAAO,aAAa,IAAI,SAAS,KAAK,QAAQ,QAAQ;AAC5D,MAAIC;AACJ,QAAM,OAAO,IAAI,QAAc,OAAK;AAAE,IAAAA,WAAU;AAAA,EAAG,CAAC;AACpD,eAAa,IAAI,WAAW,IAAI;AAChC,QAAM;AACN,MAAI;AACF,WAAO,GAAG;AAAA,EACZ,UAAE;AACA,IAAAA,SAAS;AAAA,EACX;AACF;AAEA,SAAS,YAAY,UAAkB,MAAoB;AACzD,QAAM,MAAM,QAAQ,QAAQ;AAC5B,QAAM,UAAU,KAAK,KAAK,UAAU,WAAW,CAAC,MAAM;AACtD,gBAAc,SAAS,MAAM,OAAO;AACpC,aAAW,SAAS,QAAQ;AAC9B;AAEO,SAAS,cAAc,IAAY,MAAc,KAAsB;AAC5E,QAAM,MAAM,WAAW,KAAK,EAAE;AAC9B,YAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,YAAU,WAAW,KAAK,EAAE,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,YAAU,WAAW,KAAK,EAAE,GAAG,EAAE,WAAW,KAAK,CAAC;AAElD,gBAAc,SAAS,KAAK,EAAE,GAAG,WAAW,OAAO;AACnD,gBAAc,SAAS,KAAK,EAAE,GAAG,WAAW,OAAO;AAEnD,QAAM,UAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,QAAQ,CAAC;AAAA,IACT,oBAAoB,CAAC;AAAA,EACvB;AAEA,cAAY,UAAU,KAAK,EAAE,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAChE,SAAO;AACT;AAEO,SAAS,WAAW,KAAa,WAA4B;AAClE,QAAM,UAAUC,cAAa,UAAU,KAAK,SAAS,GAAG,OAAO;AAC/D,SAAO,KAAK,MAAM,OAAO;AAC3B;AAEA,SAAS,YAAY,SAAwB;AAC3C,cAAY,UAAU,QAAQ,KAAK,QAAQ,EAAE,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAClF;AAEA,eAAsB,SAAS,KAAa,WAAmB,OAA6B;AAC1F,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,YAAQ,OAAO,KAAK,KAAK;AACzB,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,YAAY,KAAa,WAAmB,SAAiB,SAAwC;AACzH,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,UAAM,QAAQ,QAAQ,OAAO,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAa,EAAE,OAAO,OAAO;AAClF,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,SAAS,OAAO,yBAAyB,SAAS,EAAE;AAChF,WAAO,OAAO,OAAO,OAAO;AAC5B,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,qBAAqB,KAAa,WAAmB,OAAyC;AAClH,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,YAAQ,mBAAmB,KAAK,KAAK;AACrC,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,oBAAoB,KAAa,WAAmB,QAAuB,kBAA0C;AACzI,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,YAAQ,SAAS;AACjB,QAAI,qBAAqB,QAAW;AAClC,cAAQ,mBAAmB;AAAA,IAC7B;AACA,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,uBAAuB,KAAa,WAAmB,SAAgC;AAC3G,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,UAAM,SAAS,QAAQ;AACvB,QAAI,OAAO,WAAW,EAAG;AACzB,WAAO,OAAO,SAAS,CAAC,EAAG,cAAc,KAAK,OAAO;AACrD,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,gBAAgB,KAAa,WAAmB,QAA+B;AACnG,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,YAAQ,SAAS;AACjB,YAAQ,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC7C,YAAQ,mBAAmB;AAC3B,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,kBAAkB,KAAa,WAAmB,SAAiB,OAAmC;AAC1H,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,UAAM,QAAQ,QAAQ,OAAO,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAa,EAAE,OAAO,OAAO;AAClF,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,SAAS,OAAO,yBAAyB,SAAS,EAAE;AAChF,UAAM,QAAQ,KAAK,KAAK;AACxB,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,kBAAkB,KAAa,WAAmB,iBAAyB,cAAqC;AACpI,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,YAAQ,kBAAkB;AAC1B,YAAQ,eAAe;AACvB,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;AAEA,eAAsB,0BAA0B,KAAa,WAAmB,YAAoC;AAClH,SAAO,gBAAgB,WAAW,MAAM;AACtC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,UAAM,SAAS,QAAQ;AACvB,QAAI,OAAO,WAAW,EAAG;AACzB,UAAM,QAAQ,OAAO,OAAO,SAAS,CAAC;AACtC,UAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,QAAI,WAAY,OAAM,aAAa;AACnC,gBAAY,OAAO;AAAA,EACrB,CAAC;AACH;;;ACrKA,SAAS,YAAY,aAAa,gBAAAC,eAAc,iBAAAC,sBAAqB;AACrE,SAAS,eAAe;;;ACDxB,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,QAAAC,aAAY;AAEd,IAAM,qBAAqB;AAElC,IAAM,gBAAgB,CAAC,QAAQ,SAAS,WAAW,QAAQ,OAAO,OAAO;AAEzE,IAAM,iBAAyC;AAAA,EAC7C,QAAQ;AAAA,EACR,MAAM;AACR;AAEA,SAAS,mBAAmB,OAAuB;AACjD,SAAO,eAAe,KAAK,KAAK;AAClC;AAEA,IAAM,oBAAoB,oBAAI,IAAoB;AAE3C,SAAS,aAAa,WAA2B;AACtD,QAAM,MAAM,kBAAkB,IAAI,SAAS,KAAK;AAChD,QAAM,QAAQ,cAAc,MAAM,cAAc,MAAM;AACtD,oBAAkB,IAAI,WAAW,MAAM,CAAC;AACxC,SAAO;AACT;AAEO,SAAS,YAAY,WAAyB;AACnD,oBAAkB,OAAO,SAAS;AACpC;AAEA,SAAS,wBAAwB,SAAgC;AAC/D,QAAM,QAAQ,QAAQ,MAAM,uBAAuB;AACnD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,aAAa,MAAM,CAAC,EAAG,MAAM,kBAAkB;AACrD,SAAO,aAAa,WAAW,CAAC,EAAG,KAAK,IAAI;AAC9C;AAEA,SAAS,sBAAsB,WAAkC;AAC/D,MAAI;AACF,UAAMC,gBAAeD,MAAK,QAAQ,GAAG,WAAW,WAAW,wBAAwB;AACnF,UAAM,WAAW,KAAK,MAAMD,cAAaE,eAAc,OAAO,CAAC;AAC/D,eAAW,OAAO,OAAO,KAAK,QAAQ,GAAG;AACvC,UAAI,IAAI,WAAW,GAAG,SAAS,GAAG,GAAG;AACnC,eAAO,SAAS,GAAG,EAAE,eAAe;AAAA,MACtC;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB,WAAmB,WAAmB,KAA4B;AACtG,MAAI,CAAC,UAAW,QAAO;AAEvB,MAAI;AACJ,MAAI;AAEJ,MAAI,UAAU,SAAS,GAAG,GAAG;AAC3B,KAAC,WAAW,IAAI,IAAI,UAAU,MAAM,KAAK,CAAC;AAAA,EAC5C,OAAO;AACL,WAAO;AAAA,EACT;AAEA,QAAM,cAAwB,CAAC;AAE/B,MAAI,WAAW;AAEb,gBAAY,KAAKD,MAAK,WAAW,UAAU,GAAG,IAAI,KAAK,CAAC;AAExD,UAAM,cAAc,sBAAsB,SAAS;AACnD,QAAI,aAAa;AACf,kBAAY,KAAKA,MAAK,aAAa,UAAU,GAAG,IAAI,KAAK,CAAC;AAAA,IAC5D;AAAA,EACF,OAAO;AAEL,gBAAY,KAAKA,MAAK,KAAK,WAAW,UAAU,GAAG,IAAI,KAAK,CAAC;AAE7D,gBAAY,KAAKA,MAAK,QAAQ,GAAG,WAAW,UAAU,GAAG,IAAI,KAAK,CAAC;AAEnE,gBAAY,KAAKA,MAAK,WAAW,UAAU,GAAG,IAAI,KAAK,CAAC;AAAA,EAC1D;AAEA,aAAW,QAAQ,aAAa;AAC9B,QAAI;AACF,YAAM,UAAUD,cAAa,MAAM,OAAO;AAC1C,YAAM,QAAQ,wBAAwB,OAAO;AAC7C,UAAI,MAAO,QAAO,mBAAmB,KAAK;AAAA,IAC5C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;;;AC9FA,SAAS,gBAAgB;AAEzB,IAAM,WAAW;AAAA,EACf,GAAG,QAAQ;AAAA,EACX,MAAM,oCAAoC,QAAQ,IAAI,MAAM,KAAK,eAAe;AAClF;AAEA,SAAS,KAAK,KAAqB;AACjC,SAAO,SAAS,KAAK,EAAE,UAAU,SAAS,KAAK,SAAS,CAAC,EAAE,KAAK;AAClE;AAEA,SAAS,SAAS,KAA4B;AAC5C,MAAI;AACF,WAAO,KAAK,GAAG;AAAA,EACjB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAcO,SAAS,WAAW,cAAsB,KAAsB;AACrE,QAAM,UAAU,MAAM,OAAO,WAAW,GAAG,CAAC,KAAK;AACjD,QAAM,SAAS,KAAK,4BAA4B,YAAY,IAAI,OAAO,qBAAqB;AAC5F,WAAS,0BAA0B,YAAY,mBAAmB;AAClE,SAAO;AACT;AAEO,SAAS,SAAS,YAAoBG,UAAuB;AAClE,OAAK,sBAAsB,UAAU,KAAK,WAAWA,QAAO,CAAC,QAAQ;AACvE;AAEO,SAAS,SAAS,YAA0B;AACjD,WAAS,sBAAsB,UAAU,GAAG;AAC9C;AAEO,SAAS,WAAW,cAA4B;AACrD,WAAS,wBAAwB,YAAY,GAAG;AAClD;AAOO,SAAS,UAAU,cAAkC;AAC1D,QAAM,SAAS,SAAS,uBAAuB,YAAY,+BAA+B;AAC1F,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,SAAO,OACJ,MAAM,IAAI,EACV,OAAO,OAAO,EACd,IAAI,UAAQ;AACX,UAAM,CAAC,QAAQ,OAAO,IAAI,KAAK,MAAM,GAAG;AACxC,WAAO,EAAE,QAAiB,QAAkB;AAAA,EAC9C,CAAC;AACL;AAEO,SAAS,aAAa,YAAoB,OAAqB;AACpE,WAAS,wBAAwB,UAAU,QAAQ,WAAW,KAAK,CAAC,EAAE;AACxE;AAEO,SAAS,aAAa,YAAoB,OAAqB;AACpE,QAAM,MAAM,QAAQ,KAAK,6BAA6B,KAAK;AAC3D,WAAS,mBAAmB,UAAU,wBAAwB,WAAW,GAAG,CAAC,EAAE;AAI/E,WAAS,mBAAmB,UAAU,kBAAkB,KAAK,GAAG;AAChE,WAAS,mBAAmB,UAAU,oEAAoE;AAC1G,WAAS,mBAAmB,UAAU,2EAA2E;AACnH;AAWO,SAAS,aAAa,cAAsB,SAAiB,mBAAyB;AAC3F,WAAS,0BAA0B,YAAY,KAAK,MAAM,EAAE;AAC9D;AAEA,SAAS,WAAW,GAAmB;AACrC,SAAO,IAAI,EAAE,QAAQ,MAAM,OAAO,CAAC;AACrC;;;AFrFA,IAAM,mBAAmB,oBAAI,IAAoB;AACjD,IAAM,0BAA0B,oBAAI,IAAoB;AAEjD,SAAS,YAAY,WAAuC;AACjE,SAAO,iBAAiB,IAAI,SAAS;AACvC;AAEO,SAAS,YAAY,WAAmB,UAAwB;AACrE,mBAAiB,IAAI,WAAW,QAAQ;AAC1C;AAEO,SAAS,sBAAsB,WAAuC;AAC3E,SAAO,wBAAwB,IAAI,SAAS;AAC9C;AAEO,SAAS,sBAAsB,WAAmB,QAAsB;AAC7E,0BAAwB,IAAI,WAAW,MAAM;AAC/C;AAEA,SAAS,uBAAuB,KAAqB;AACnD,QAAM,cAAc,8BAA8B,GAAG;AACrD,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAOC,cAAa,aAAa,OAAO;AAAA,EAC1C;AACA,QAAM,cAAc,QAAQ,YAAY,SAAS,8BAA8B;AAC/E,SAAOA,cAAa,aAAa,OAAO;AAC1C;AAEA,SAAS,2BAA2B,SAA0B;AAC5D,QAAM,UAAU,QAAQ,GAAG,MAAM,GAAG,CAAC;AACrC,QAAM,WAAW,QAAQ,mBAAmB;AAE5C,QAAM,SAAS,WAAW,QAAQ,KAAK,QAAQ,EAAE;AACjD,MAAI;AACJ,MAAI,WAAW,MAAM,GAAG;AACtB,UAAM,QAAQ,YAAY,MAAM;AAChC,mBAAe,MAAM,SAAS,IAAI,MAAM,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,IAAI;AAAA,EAC1E,OAAO;AACL,mBAAe;AAAA,EACjB;AAEA,QAAM,WAAW,SAAS,QAAQ,KAAK,QAAQ,EAAE;AACjD,QAAM,UAAU,WAAW,QAAQ,IAAI,IAAI,QAAQ,KAAK;AAExD,QAAM,WAAW,SAAS,QAAQ,KAAK,QAAQ,EAAE;AACjD,QAAM,UAAU,WAAW,QAAQ,IAAI,IAAI,QAAQ,KAAK;AAExD,QAAM,aAAa,QAAQ,OAAO,SAAS,IACvC,QAAQ,OAAO,IAAI,CAAC,MAAa;AAC/B,UAAM,SAAS,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,MAAM,WAAM,EAAE,QAAQ,MAAM;AACvE,QAAI,EAAE,QAAQ,WAAW,EAAG,QAAO;AACnC,QAAI,YAAY;AAChB,UAAM,cAAc,EAAE,QAAQ,IAAI,OAAK;AACrC,YAAM,QAAQ,EAAE,SAAS,UAAU,YAAY,WAAW,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAC9F,aAAO,KAAK,KAAK,KAAK,EAAE,OAAO,YAAO,EAAE,QAAQ;AAAA,IAClD,CAAC;AACD,WAAO,CAAC,QAAQ,GAAG,WAAW,EAAE,KAAK,IAAI;AAAA,EAC3C,CAAC,EAAE,KAAK,IAAI,IACZ;AAEJ,QAAM,aAAa,QAAQ,mBAAmB,SAAS,IACnD,QAAQ,mBAAmB,IAAI,OAAK;AAClC,UAAM,cAAc,EAAE,cAAc,SAAS,IAAI,EAAE,cAAc,KAAK,IAAI,IAAI;AAC9E,WAAO,SAAS,EAAE,KAAK,aAAa,WAAW;AAAA,EACjD,CAAC,EAAE,KAAK,IAAI,IACZ;AAGJ,QAAM,iBAAiB,QAAQ,OAAO,OAAO,OAAK,EAAE,YAAY;AAChE,MAAI,kBAAkB;AACtB,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,UAAU,eAAe,IAAI,CAAC,MAAa;AAC/C,UAAI,EAAE,gBAAgB,YAAY;AAChC,eAAO,KAAK,EAAE,EAAE,qBAAgB,EAAE,gBAAgB,SAAS;AAAA,YAAe,EAAE,UAAU;AAAA,cAAiB,EAAE,YAAY;AAAA,MACvH;AACA,YAAM,SAAS,EAAE,eAAe;AAChC,aAAO,KAAK,EAAE,EAAE,KAAK,MAAM,YAAY,EAAE,UAAU;AAAA,IACrD,CAAC,EAAE,KAAK,IAAI;AACZ,sBAAkB;AAAA;AAAA;AAAA,EAAqB,OAAO;AAAA,EAChD;AAGA,QAAM,eAAe,WAAW,mBAAmB,QAAQ,GAAG,CAAC,IAC3D,oNACA;AAEJ,SAAO;AAAA,WACE,OAAO,WAAW,QAAQ;AAAA,QAC7B,QAAQ,IAAI;AAAA,UACV,QAAQ,MAAM;AAAA;AAAA;AAAA,EAGtB,OAAO;AAAA;AAAA;AAAA,EAGP,OAAO;AAAA;AAAA;AAAA,EAGP,UAAU,GAAG,eAAe;AAAA;AAAA;AAAA,EAG5B,UAAU;AAAA;AAAA;AAAA,EAGV,YAAY;AAAA;AAAA;AAAA,EAGZ,YAAY;AAAA;AAEd;AAEA,eAAsB,kBAAkB,WAAmB,KAAa,UAAkB,SAAiC;AACzH,QAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,QAAM,aAAa,uBAAuB,GAAG;AAC7C,QAAM,iBAAiB,2BAA2B,OAAO;AAGzD,QAAM,WAAW,QAAQ,mBAAmB,SAAS;AACrD,QAAM,iBAAiB,GAAG,WAAW,KAAK,SAAS,CAAC,wBAAwB,QAAQ;AACpF,EAAAC,eAAc,gBAAgB,YAAY,OAAO;AAEjD,mBAAiB,IAAI,WAAW,QAAQ;AAExC,QAAM,aAAa;AAAA,IACjB,+BAA+B,SAAS;AAAA,IACxC;AAAA,EACF,EAAE,KAAK,MAAM;AAGb,MAAI;AACJ,MAAI,SAAS;AACX,iBAAa,GAAG,cAAc;AAAA;AAAA,uDAA4D,OAAO;AAAA,EACnG,OAAO;AAEL,UAAM,YAAY,CAAC,GAAG,QAAQ,kBAAkB,EAAE,QAAQ,EAAE,KAAK,OAAK,EAAE,WAAW;AACnF,UAAM,eAAe,WAAW;AAChC,QAAI,cAAc;AAChB,mBAAa,GAAG,cAAc;AAAA;AAAA,EAAO,YAAY;AAAA,IACnD,OAAO;AACL,mBAAa,GAAG,cAAc;AAAA;AAAA;AAAA,IAChC;AAAA,EACF;AAEA,QAAM,qBAAqB,GAAG,WAAW,KAAK,SAAS,CAAC,sBAAsB,QAAQ;AACtF,EAAAA,eAAc,oBAAoB,YAAY,OAAO;AACrD,QAAM,aAAa,QAAQ,YAAY,SAAS,kCAAkC;AAClF,QAAM,eAAe,QAAQ,YAAY,SAAS,yCAAyC;AAC3F,QAAM,YAAY,qDAAqD,YAAY,mBAAmB,UAAU,oCAAoC,cAAc,eAAe,kBAAkB;AAEnM,QAAM,SAAc,WAAW,UAAU,GAAG;AAE5C,0BAAwB,IAAI,WAAW,MAAM;AAC7C,EAAK,aAAa,QAAQ,iBAAiB,UAAU,MAAM,GAAG,CAAC,CAAC,GAAG;AACnE,EAAK,aAAa,QAAQ,kBAAkB;AAE5C,QAAM,aAAa,QAAQ,YAAY,SAAS,yBAAyB;AACzE,QAAM,YAAY,WAAW,UAAU,IAAI,QAAQ,UAAU,SAAS;AACtE,EAAK,SAAS,QAAQ,GAAG,SAAS,IAAI,UAAU,OAAO,SAAS,EAAE;AAElE,QAAY,qBAAqB,KAAK,WAAW;AAAA,IAC/C,OAAO;AAAA,IACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,eAAe,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,wBAAwB,WAAmB,KAAiC;AACnF,QAAM,UAAU,wBAAwB,IAAI,SAAS;AACrD,MAAI,QAAS,QAAO;AACpB,QAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,QAAM,YAAY,QAAQ,mBAAmB,QAAQ,mBAAmB,SAAS,CAAC;AAClF,SAAO,WAAW,UAAU;AAC9B;AAEA,eAAsB,wBAAwB,WAAmB,KAAa,YAAoC;AAChH,QAAM,SAAS,wBAAwB,WAAW,GAAG;AACrD,MAAI,QAAQ;AACV,IAAK,SAAS,MAAM;AACpB,4BAAwB,OAAO,SAAS;AAAA,EAC1C;AAEA,QAAM,WAAW,iBAAiB,IAAI,SAAS;AAC/C,MAAI,SAAU,CAAK,aAAa,QAAQ;AAExC,QAAY,0BAA0B,KAAK,WAAW,UAAU;AAEhE,QAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,QAAM,gBAAgB,QAAQ,OAAO,OAAO,OAAK,EAAE,WAAW,SAAS;AACvE,MAAI,cAAc,WAAW,GAAG;AAC9B,YAAQ,MAAM,kFAAkF,SAAS,EAAE;AAAA,EAC7G;AACF;AAEA,eAAsB,2BAA2B,WAAmB,KAAa,QAA+B;AAC9G,QAAY,0BAA0B,KAAK,SAAS;AACpD,QAAY,gBAAgB,KAAK,WAAW,MAAM;AAElD,UAAQ,IAAI,sBAAsB,SAAS,eAAe,MAAM,EAAE;AACpE;AAEO,SAAS,mBAAmB,WAAyB;AAC1D,0BAAwB,OAAO,SAAS;AACxC,mBAAiB,OAAO,SAAS;AACnC;;;AGxNA,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,aAAAC,YAAW,eAAAC,cAAa,cAAAC,mBAAkB;AAChF,SAAS,WAAAC,gBAAe;;;ACDxB,SAAS,YAAAC,iBAAgB;AACzB,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,eAAAC,cAAa,cAAc;AACzE,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAK9B,IAAMC,YAAW;AAAA,EACf,GAAG,QAAQ;AAAA,EACX,MAAM,oCAAoC,QAAQ,IAAI,MAAM,KAAK,eAAe;AAClF;AAEA,SAASC,MAAK,KAAa,KAAsB;AAC/C,SAAOC,UAAS,KAAK,EAAE,UAAU,SAAS,KAAKF,WAAU,IAAI,CAAC,EAAE,KAAK;AACvE;AAEA,SAASG,UAAS,KAAa,KAA6B;AAC1D,MAAI;AACF,WAAOF,MAAK,KAAK,GAAG;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAASG,YAAW,GAAmB;AACrC,SAAO,IAAI,EAAE,QAAQ,MAAM,OAAO,CAAC;AACrC;AASO,SAAS,mBAAmB,KAAoC;AACrE,MAAI;AACF,UAAM,UAAUC,cAAa,mBAAmB,GAAG,GAAG,OAAO;AAC7D,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eACd,KACA,WACA,SAC8C;AAC9C,QAAM,aAAa,YAAY,UAAU,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO;AAC/D,QAAM,eAAeC,MAAK,gBAAgB,GAAG,GAAG,OAAO;AAEvD,EAAAC,WAAUC,SAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAEpD,EAAAP,MAAK,UAAUG,YAAW,GAAG,CAAC,WAAWA,YAAW,UAAU,CAAC,OAAO;AACtE,EAAAH,MAAK,UAAUG,YAAW,GAAG,CAAC,iBAAiBA,YAAW,YAAY,CAAC,IAAIA,YAAW,UAAU,CAAC,EAAE;AAGnG,QAAM,WAAW,CAAC,aAAa,SAAS;AACxC,aAAW,SAAS,UAAU;AAC5B,UAAM,MAAME,MAAK,KAAK,KAAK;AAC3B,QAAIG,YAAW,GAAG,GAAG;AACnB,MAAAN,UAAS,SAASC,YAAW,GAAG,CAAC,IAAIA,YAAWE,MAAK,cAAc,KAAK,CAAC,CAAC,EAAE;AAAA,IAC9E;AAAA,EACF;AAGA,QAAM,SAAS,mBAAmB,GAAG;AACrC,MAAI,QAAQ;AACV,sBAAkB,KAAK,cAAc,MAAM;AAAA,EAC7C;AAEA,SAAO,EAAE,cAAc,WAAW;AACpC;AAEO,SAAS,kBAAkB,KAAa,cAAsB,QAA8B;AAEjG,MAAI,OAAO,MAAM;AACf,eAAW,SAAS,OAAO,MAAM;AAC/B,YAAM,OAAOA,MAAK,cAAc,KAAK;AACrC,MAAAC,WAAUC,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,MAAAL,UAAS,SAASC,YAAWE,MAAK,KAAK,KAAK,CAAC,CAAC,IAAIF,YAAW,IAAI,CAAC,EAAE;AAAA,IACtE;AAAA,EACF;AAGA,MAAI,OAAO,OAAO;AAChB,eAAW,SAAS,OAAO,OAAO;AAChC,YAAM,OAAOE,MAAK,cAAc,KAAK;AACrC,MAAAC,WAAUC,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,YAAM,MAAMJ,YAAWE,MAAK,KAAK,KAAK,CAAC;AACvC,YAAM,OAAOF,YAAW,IAAI;AAC5B,UAAID,UAAS,UAAU,GAAG,IAAI,IAAI,EAAE,MAAM,MAAM;AAC9C,QAAAA,UAAS,SAAS,GAAG,IAAI,IAAI,EAAE;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,SAAS;AAClB,eAAW,SAAS,OAAO,SAAS;AAClC,YAAM,OAAOG,MAAK,cAAc,KAAK;AACrC,MAAAC,WAAUC,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,MAAAL,UAAS,SAASC,YAAWE,MAAK,KAAK,KAAK,CAAC,CAAC,IAAIF,YAAW,IAAI,CAAC,EAAE;AAAA,IACtE;AAAA,EACF;AAGA,MAAI,OAAO,MAAM;AACf,QAAI;AACF,MAAAH,MAAK,OAAO,MAAM,YAAY;AAAA,IAChC,SAAS,KAAK;AACZ,cAAQ,MAAM,4CAA4C,eAAe,QAAQ,IAAI,UAAU,GAAG,EAAE;AAAA,IACtG;AAAA,EACF;AACF;AAMA,SAAS,sBAAsB,KAAa,cAAqC;AAC/E,QAAM,SAASE,UAAS,UAAUC,YAAW,GAAG,CAAC,4BAA4B;AAC7E,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,MAAM,CAAC,MAAM,YAAY,YAAY,IAAI;AAC3C,eAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,cAAM,OAAO,MAAM,CAAC;AACpB,YAAI,SAAS,GAAI;AACjB,YAAI,KAAK,WAAW,oBAAoB,GAAG;AACzC,iBAAO,KAAK,MAAM,qBAAqB,MAAM;AAAA,QAC/C;AAAA,MACF;AACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,eAAe,KAAa,QAAgC;AAC1E,QAAM,UAAU,OAAO;AAAA,IACrB,OAAK,EAAE,gBAAgB,EAAE,gBAAgB;AAAA,EAC3C;AAEA,QAAM,UAAyB,CAAC;AAEhC,aAAW,SAAS,SAAS;AAC3B,UAAM,SAAS,sBAAsB,KAAK,MAAM,YAAa;AAE7D,QAAI,CAAC,QAAQ;AACX,cAAQ,KAAK,EAAE,SAAS,MAAM,IAAI,MAAM,MAAM,MAAM,QAAQ,aAAa,CAAC;AAE1E,MAAAD,UAAS,UAAUC,YAAW,GAAG,CAAC,oBAAoBA,YAAW,MAAM,YAAa,CAAC,UAAU;AAC/F;AAAA,IACF;AAGA,UAAM,WAAWD,UAAS,UAAUC,YAAW,GAAG,CAAC,cAAcA,YAAW,MAAM,CAAC,YAAY;AAC/F,QAAI,CAAC,UAAU;AACb,cAAQ,KAAK,EAAE,SAAS,MAAM,IAAI,MAAM,MAAM,MAAM,QAAQ,aAAa,CAAC;AAC1E,sBAAgB,KAAK,MAAM,cAAe,MAAM;AAChD;AAAA,IACF;AAGA,UAAM,WAAW,mBAAmB,MAAM,EAAE,KAAK,MAAM,IAAI;AAC3D,UAAM,WAAW,UAAUA,YAAW,GAAG,CAAC,kBAAkBA,YAAW,MAAM,CAAC,OAAOA,YAAW,QAAQ,CAAC;AAEzG,QAAI;AACF,MAAAH,MAAK,QAAQ;AAEb,MAAAE,UAAS,UAAUC,YAAW,GAAG,CAAC,oBAAoBA,YAAW,MAAM,YAAa,CAAC,EAAE;AACvF,MAAAD,UAAS,UAAUC,YAAW,GAAG,CAAC,cAAcA,YAAW,MAAM,CAAC,EAAE;AACpE,cAAQ,KAAK,EAAE,SAAS,MAAM,IAAI,MAAM,MAAM,MAAM,QAAQ,SAAS,CAAC;AAAA,IACxE,SAAS,KAAc;AAErB,MAAAD,UAAS,UAAUC,YAAW,GAAG,CAAC,gBAAgB;AAClD,YAAM,SAAU,KAAsC;AACtD,YAAM,kBAAkB,UACnB,OAAO,WAAW,WAAW,SAAS,OAAO,SAAS,OAAO,GAAG,KAAK,IACrE,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACpD,cAAQ,KAAK,EAAE,SAAS,MAAM,IAAI,MAAM,MAAM,MAAM,QAAQ,YAAY,gBAAgB,CAAC;AAAA,IAC3F;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,gBAAgB,KAAa,cAAsB,YAA0B;AAC3F,EAAAD,UAAS,UAAUC,YAAW,GAAG,CAAC,oBAAoBA,YAAW,YAAY,CAAC,UAAU;AACxF,EAAAD,UAAS,UAAUC,YAAW,GAAG,CAAC,cAAcA,YAAW,UAAU,CAAC,EAAE;AAGxE,QAAM,UAAUI,SAAQ,YAAY;AACpC,MAAI;AACF,UAAM,UAAUE,aAAY,OAAO;AACnC,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,IACrC;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,oBAAoB,QAAyB;AAC3D,SAAO,OAAO,OAAO,OAAK,EAAE,gBAAgB,EAAE,WAAW,SAAS,EAAE;AACtE;;;ADtMA,IAAM,gBAAgB,oBAAI,IAAoB;AAMvC,SAAS,2BAA2B,WAAmB,QAAgC;AAC5F,MAAI,MAAM;AACV,aAAW,KAAK,QAAQ;AACtB,UAAM,QAAQ,EAAE,GAAG,MAAM,eAAe;AACxC,QAAI,MAAO,OAAM,KAAK,IAAI,KAAK,SAAS,MAAM,CAAC,GAAI,EAAE,CAAC;AAAA,EACxD;AACA,gBAAc,IAAI,WAAW,GAAG;AAClC;AAEO,SAAS,kBAAkB,WAAyB;AACzD,gBAAc,OAAO,SAAS;AAChC;AAQA,SAAS,kBAAkB,WAAmB,aAAqB,iBAA2C;AAC5G,QAAM,eAAeC,SAAQ,YAAY,SAAS,8BAA8B;AAChF,MAAI;AACJ,MAAI;AACF,eAAWC,cAAa,cAAc,OAAO;AAAA,EAC/C,QAAQ;AACN,eAAW;AAAA;AAAA;AAAA,EACb;AAEA,MAAI,gBAAgB;AACpB,MAAI,iBAAiB;AACnB,oBAAgB;AAAA,MACd;AAAA,MACA,+BAA+B,gBAAgB,MAAM,OAAO,gBAAgB,KAAK,qCAAqC,gBAAgB,UAAU;AAAA,MAChJ,qDAAqD,gBAAgB,MAAM;AAAA,IAC7E,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,SAAO,SACJ,QAAQ,uBAAuB,SAAS,EACxC,QAAQ,wBAAwB,WAAW,EAC3C,QAAQ,6BAA6B,aAAa;AACvD;AAYA,eAAsB,WAAW,MAAsC;AACrE,QAAM,EAAE,WAAW,KAAK,WAAW,MAAM,aAAa,SAAS,IAAI;AACnE,QAAM,SAAS,cAAc,IAAI,SAAS,KAAK,KAAK;AACpD,gBAAc,IAAI,WAAW,KAAK;AAClC,QAAM,UAAU,SAAS,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AACvD,QAAM,aAAaD,SAAQ,YAAY,SAAS,2BAA2B;AAC3E,QAAM,QAAQ,sBAAsB,WAAW,YAAY,GAAG,KAAK,aAAa,SAAS;AAEzF,MAAI,UAAU;AACd,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,KAAK,UAAU;AACjB,UAAM,KAAK,eAAe,KAAK,WAAW,OAAO;AACjD,mBAAe,GAAG;AAClB,iBAAa,GAAG;AAChB,cAAU;AAEV,UAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,UAAM,aAAa,oBAAoB,QAAQ,MAAM,IAAI;AACzD,sBAAkB,EAAE,QAAQ,YAAY,OAAO,YAAY,WAAW;AAAA,EACxE;AAEA,QAAM,SAAc,WAAW,UAAU,OAAO;AAChD,EAAK,aAAa,QAAQ,GAAG,IAAI,KAAK,OAAO,GAAG;AAChD,EAAK,aAAa,QAAQ,KAAK;AAE/B,QAAM,SAAS,kBAAkB,WAAW,aAAa,eAAe;AACxE,QAAM,iBAAiB,GAAG,WAAW,KAAK,SAAS,CAAC,IAAI,OAAO;AAC/D,EAAAE,eAAc,gBAAgB,QAAQ,OAAO;AAE7C,QAAM,aAAaF,SAAQ,YAAY,SAAS,yBAAyB;AACzE,QAAM,YAAYG,YAAW,UAAU,IAAI,QAAQ,UAAU,SAAS;AAEtE,QAAM,aAAa;AAAA,IACjB,+BAA+B,SAAS;AAAA,IACxC,6BAA6B,OAAO;AAAA,IACpC,GAAI,kBAAkB,CAAC,gCAAgC,gBAAgB,MAAM,GAAG,IAAI,CAAC;AAAA,EACvF,EAAE,KAAK,MAAM;AAEb,QAAM,YAAY,YAAY,YAAYC,YAAW,SAAS,CAAC,KAAK;AACpE,QAAM,YAAY,uDAAuD,UAAU,IAAI,SAAS,mCAAmC,cAAc,OAAOA,YAAW,WAAW,CAAC;AAC/K,EAAK,SAAS,QAAQ,GAAG,SAAS,IAAI,UAAU,OAAO,SAAS,EAAE;AAElE,QAAM,QAAe;AAAA,IACnB,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,aAAa;AAAA,IACb,SAAS,CAAC;AAAA,IACV;AAAA,IACA,GAAI,eAAe,EAAE,cAAc,YAAY,aAAa,UAAmB,IAAI,CAAC;AAAA,EACtF;AAEA,QAAY,SAAS,KAAK,WAAW,KAAK;AAC1C,SAAO;AACT;AAEA,SAAS,iBAAiB,KAAa,WAAmB,SAAyB;AACjF,QAAM,MAAM,WAAW,KAAK,SAAS;AACrC,MAAI;AACF,UAAM,QAAQC,aAAY,GAAG,EAAE,OAAO,OAAK,EAAE,WAAW,GAAG,OAAO,GAAG,KAAK,CAAC,EAAE,SAAS,WAAW,CAAC;AAClG,WAAO,OAAO,MAAM,SAAS,CAAC,EAAE,SAAS,GAAG,GAAG;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,kBACpB,KACA,WACA,SACA,SACe;AACf,QAAM,MAAM,WAAW,KAAK,SAAS;AACrC,EAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,QAAM,MAAM,iBAAiB,KAAK,WAAW,OAAO;AACpD,QAAM,WAAW,eAAe,KAAK,WAAW,SAAS,GAAG;AAC5D,EAAAJ,eAAc,UAAU,SAAS,OAAO;AAExC,QAAM,QAAqB;AAAA,IACzB,MAAM;AAAA,IACN;AAAA,IACA,SAAS,QAAQ,MAAM,GAAG,GAAG;AAAA,IAC7B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AACA,QAAY,kBAAkB,KAAK,WAAW,SAAS,KAAK;AAC9D;AAEA,eAAsB,kBACpB,KACA,WACA,SACA,QACkB;AAClB,QAAM,MAAM,WAAW,KAAK,SAAS;AACrC,EAAAI,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,QAAM,WAAW,eAAe,KAAK,WAAW,SAAS,OAAO;AAChE,EAAAJ,eAAc,UAAU,QAAQ,OAAO;AAEvC,QAAM,QAAqB;AAAA,IACzB,MAAM;AAAA,IACN;AAAA,IACA,SAAS,OAAO,MAAM,GAAG,GAAG;AAAA,IAC5B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AACA,QAAY,kBAAkB,KAAK,WAAW,SAAS,KAAK;AAE5D,QAAY,YAAY,KAAK,WAAW,SAAS;AAAA,IAC/C,QAAQ;AAAA,IACR,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,EACtC,CAAC;AAED,QAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,QAAM,WAAW,QAAQ;AACzB,QAAM,QAAQ,SAAS,MAAM,EAAE,QAAQ,EAAE,KAAK,OAAK,EAAE,OAAO,OAAO;AACnE,MAAI,OAAO;AACT,IAAK,SAAS,MAAM,MAAM;AAAA,EAC5B;AAEA,QAAM,WAAW,YAAY,SAAS;AACtC,MAAI,SAAU,CAAK,aAAa,QAAQ;AAExC,SAAO,cAAc,OAAO;AAC9B;AAEA,eAAsB,kBACpB,KACA,WACA,SACA,QACkB;AAClB,QAAY,YAAY,KAAK,WAAW,SAAS;AAAA,IAC/C,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,EACtC,CAAC;AAED,QAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,SAAO,cAAc,OAAO;AAC9B;AAKA,SAAS,cAAc,SAAwD;AAC7E,QAAM,UAAU,QAAQ,OAAO,OAAO,OAAK,EAAE,WAAW,SAAS;AACjE,SAAO,QAAQ,WAAW,KAAK,QAAQ,OAAO,SAAS;AACzD;AAEA,SAASE,YAAW,GAAmB;AACrC,SAAO,IAAI,EAAE,QAAQ,MAAM,OAAO,CAAC;AACrC;;;AE7NA,IAAI,kBAAyD;AAC7D,IAAI,kBAA0C;AAEvC,SAAS,mBAAmB,IAA2B;AAC5D,oBAAkB;AACpB;AAEO,SAAS,aAAa,iBAAyB,KAAY;AAChE,MAAI,gBAAiB;AACrB,oBAAkB,YAAY,MAAM;AAClC,oBAAgB,EAAE,MAAM,SAAO;AAC7B,cAAQ,MAAM,kCAAkC,GAAG;AAAA,IACrD,CAAC;AAAA,EACH,GAAG,cAAc;AACnB;AAEO,SAAS,cAAoB;AAClC,MAAI,iBAAiB;AACnB,kBAAc,eAAe;AAC7B,sBAAkB;AAAA,EACpB;AACF;AAEA,IAAM,kBAAkB,oBAAI,IAAuF;AAE5G,SAAS,aAAa,WAAmB,KAAa,aAA2B;AAEtF,QAAM,WAAW,gBAAgB,IAAI,SAAS;AAC9C,kBAAgB,IAAI,WAAW,EAAE,IAAI,WAAW,KAAK,aAAa,UAAU,WAAW,SAAS,WAAW,KAAK,CAAC;AACnH;AAEO,SAAS,oBAAoB,WAAmB,UAAwB;AAC7E,QAAM,QAAQ,gBAAgB,IAAI,SAAS;AAC3C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,+CAA+C,SAAS,EAAE;AACtF,QAAM,WAAW;AACnB;AAEO,SAAS,eAAe,WAAyB;AACtD,kBAAgB,OAAO,SAAS;AAClC;AAEA,eAAe,kBAAiC;AAC9C,aAAW,EAAE,IAAI,WAAW,KAAK,SAAS,KAAK,gBAAgB,OAAO,GAAG;AACvE,QAAI,UAAU;AACZ,YAAM,YAAY,WAAW,KAAK,QAAQ;AAAA,IAC5C;AAAA,EACF;AACF;AAEA,eAAe,YAAY,WAAmB,KAAa,UAAiC;AAC1F,MAAI;AACJ,MAAI;AACF,cAAgB,WAAW,KAAK,SAAS;AAAA,EAC3C,SAAS,KAAK;AACZ,YAAQ,MAAM,+CAA+C,SAAS,KAAK,GAAG;AAC9E;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,aAAa;AAClC,UAAMG,cAAa,sBAAsB,SAAS;AAClD,QAAIA,aAAY;AACd,YAAMC,aAAiB,UAAU,QAAQ;AACzC,YAAMC,eAAc,IAAI,IAAID,WAAU,IAAI,OAAK,EAAE,MAAM,CAAC;AACxD,UAAI,CAACC,aAAY,IAAIF,WAAU,GAAG;AAChC,2BAAmB,SAAS;AAC5B,uBAAe,SAAS;AACxB,gBAAQ,IAAI,sBAAsB,SAAS,+CAA+C;AAAA,MAC5F;AAAA,IACF,OAAO;AAEL,yBAAmB,SAAS;AAC5B,qBAAe,SAAS;AAAA,IAC1B;AACA;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,SAAU;AAEjC,QAAM,YAAiB,UAAU,QAAQ;AACzC,MAAI,UAAU,WAAW,EAAG;AAE5B,QAAM,cAAc,IAAI,IAAI,UAAU,IAAI,OAAK,EAAE,MAAM,CAAC;AAExD,MAAI,cAAc;AAClB,aAAW,SAAS,QAAQ,QAAQ;AAClC,QAAI,MAAM,WAAW,UAAW;AAChC,QAAI,CAAC,YAAY,IAAI,MAAM,MAAM,GAAG;AAClC,oBAAc;AACd,YAAM,UAAU,MAAM,kBAAkB,KAAK,WAAW,MAAM,IAAI,qBAAqB;AACvF,UAAI,WAAW,iBAAiB;AAC9B,wBAAgB,WAAW,KAAK,QAAQ;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAa,CAAK,aAAa,QAAQ;AAG3C,QAAM,aAAa,sBAAsB,SAAS;AAClD,MAAI,cAAc,CAAC,YAAY,IAAI,UAAU,GAAG;AAE9C,UAAM,gBAAgB,QAAQ,OAAO,OAAO,OAAK,EAAE,WAAW,SAAS;AACvE,QAAI,cAAc,WAAW,GAAG;AAE9B,YAAY,oBAAoB,KAAK,WAAW,QAAQ;AACxD,cAAQ,IAAI,sBAAsB,SAAS,wCAAwC;AAAA,IACrF;AAAA,EACF;AAGA,YAAgB,WAAW,KAAK,SAAS;AACzC,MACE,QAAQ,WAAW,YACnB,QAAQ,OAAO,SAAS,KACxB,QAAQ,OAAO,MAAM,OAAK,EAAE,WAAW,SAAS,MAC/C,CAAC,cAAc,CAAC,YAAY,IAAI,UAAU,MAC3C,iBACA;AACA,YAAQ,IAAI,qCAAqC,SAAS,8DAAyD;AACnH,oBAAgB,WAAW,KAAK,QAAQ;AAAA,EAC1C;AACF;;;APpHA,eAAsB,aAAa,MAAc,KAAa,aAAqB,UAAoC;AACrH,QAAM,YAAY,OAAO;AACzB,QAAM,UAAgB,cAAc,WAAW,MAAM,GAAG;AACxD,QAAY,kBAAkB,KAAK,WAAW,aAAa,QAAQ;AAEnE,eAAa,WAAW,KAAK,WAAW;AACxC,QAAmB,kBAAkB,WAAW,KAAK,QAAQ;AAC7D,sBAAoB,WAAW,QAAQ;AAEvC,SAAO;AACT;AAEA,eAAsB,cAAc,WAAmB,KAAa,aAAqB,UAAkB,SAAoC;AAC7I,QAAM,UAAgB,WAAW,KAAK,SAAS;AAE/C,MAAI,QAAQ,WAAW,UAAU;AAE/B,UAAM,cAAc,oBAAI,IAAY;AACpC,QAAI,QAAQ,cAAc;AACxB,YAAM,QAAa,UAAU,QAAQ,YAAY;AACjD,iBAAW,QAAQ,OAAO;AACxB,oBAAY,IAAI,KAAK,MAAM;AAAA,MAC7B;AAAA,IACF;AAGA,eAAW,SAAS,QAAQ,QAAQ;AAClC,UAAI,MAAM,WAAW,WAAW;AAC9B,cAAM,UAAU,MAAM,UAAU,QAAQ,YAAY,IAAI,MAAM,MAAM;AACpE,YAAI,CAAC,SAAS;AACZ,gBAAY,YAAY,KAAK,WAAW,MAAM,IAAI;AAAA,YAChD,QAAQ;AAAA,YACR,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,YACpC,cAAc;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAY,oBAAoB,KAAK,WAAW,QAAQ;AACxD,QAAY,kBAAkB,KAAK,WAAW,aAAa,QAAQ;AAGnE,6BAA2B,WAAW,QAAQ,MAAM;AACpD,cAAY,SAAS;AAErB,eAAa,WAAW,KAAK,WAAW;AACxC,QAAmB,kBAAkB,WAAW,KAAK,UAAU,OAAO;AACtE,sBAAoB,WAAW,QAAQ;AAEvC,SAAa,WAAW,KAAK,SAAS;AACxC;AAEO,SAAS,iBAAiB,KAAa,WAA4B;AACxE,SAAa,WAAW,KAAK,SAAS;AACxC;AAEO,SAAS,aAAa,KAAyG;AACpI,QAAM,MAAM,YAAY,GAAG;AAC3B,MAAI,CAACG,YAAW,GAAG,EAAG,QAAO,CAAC;AAE9B,QAAM,UAAUC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AACxD,QAAM,WAAuG,CAAC;AAE9G,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,QAAI;AACF,YAAM,UAAgB,WAAW,KAAK,MAAM,IAAI;AAChD,eAAS,KAAK;AAAA,QACZ,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ;AAAA,QACd,QAAQ,QAAQ;AAAA,QAChB,WAAW,QAAQ;AAAA,QACnB,YAAY,QAAQ,OAAO;AAAA,MAC7B,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,cAAQ,MAAM,qCAAqC,MAAM,IAAI,KAAK,GAAG;AAAA,IACvE;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAASC,iBAAgB,WAAmB,KAAa,UAAwB;AACtF,QAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,MAAI,QAAQ,WAAW,SAAU;AAGjC,QAAM,iBAAiB,QAAQ,OAAO,OAAO,OAAK,EAAE,gBAAgB,EAAE,gBAAgB,SAAS;AAC/F,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,UAAU,eAAe,KAAK,cAAc;AAClD,eAAW,UAAU,SAAS;AAC5B,YAAM,cAAc,OAAO,WAAW,aAAa,aAAsB;AACzE,MAAM,YAAY,KAAK,WAAW,OAAO,SAAS;AAAA,QAChD;AAAA,QACA,cAAc,OAAO;AAAA,MACvB,CAAC,EAAE,MAAM,CAAC,QAAiB,QAAQ,MAAM,gDAAgD,OAAO,OAAO,KAAK,GAAG,CAAC;AAAA,IAClH;AAAA,EACF;AAGA,aAAW,MAAM;AACf,IAAa,kBAAkB,WAAW,KAAK,QAAQ,EACpD,KAAK,MAAM,oBAAoB,WAAW,QAAQ,CAAC,EACnD,MAAM,CAAC,QAAiB,QAAQ,MAAM,yDAAyD,SAAS,KAAK,GAAG,CAAC;AAAA,EACtH,GAAG,GAAI;AACT;AAEA,eAAsB,YACpB,WACA,KACA,WACA,MACA,aACA,UAC8B;AAC9B,QAAM,WAAwB,YAAY,SAAS;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,oCAAoC,SAAS,EAAE;AAE9E,QAAM,QAAQ,MAAM,WAAW;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAY,uBAAuB,KAAK,WAAW,MAAM,EAAE;AAE3D,SAAO,EAAE,SAAS,MAAM,GAAG;AAC7B;AAEA,eAAsB,aAAa,KAAa,WAAmB,SAAiB,QAAgB,UAAiC;AACnI,QAAM,UAAU,MAAM,kBAAkB,KAAK,WAAW,SAAS,MAAM;AACvE,MAAI,SAAS;AACX,IAAAA,iBAAgB,WAAW,KAAK,QAAQ;AAAA,EAC1C;AACF;AAEA,eAAsB,aAAa,KAAa,WAAmB,SAAiB,SAAgC;AAClH,QAAM,kBAAkB,KAAK,WAAW,SAAS,OAAO;AAC1D;AAEA,eAAsB,YAAY,WAAmB,KAAa,YAAoC;AACpG,QAAmB,wBAAwB,WAAW,KAAK,UAAU;AACvE;AAEA,eAAsB,eAAe,WAAmB,KAAa,QAA+B;AAClG,QAAmB,2BAA2B,WAAW,KAAK,MAAM;AACtE;AAEA,eAAsB,4BACpB,KACA,WACA,SACA,iBACe;AACf,QAAY,YAAY,KAAK,WAAW,SAAS,EAAE,gBAAgB,CAAC;AACtE;AAEA,eAAsB,WAAW,WAAmB,KAA8B;AAChF,QAAM,UAAgB,WAAW,KAAK,SAAS;AAC/C,QAAM,WAAwB,YAAY,SAAS;AAGnD,MAAI,eAAe;AACnB,aAAW,SAAS,QAAQ,QAAQ;AAClC,QAAI,MAAM,WAAW,WAAW;AAC9B,YAAY,YAAY,KAAK,WAAW,MAAM,IAAI;AAAA,QAChD,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACtC,CAAC;AACD;AAAA,IACF;AAAA,EACF;AAGA,aAAW,SAAS,QAAQ,QAAQ;AAClC,QAAI,MAAM,gBAAgB,MAAM,YAAY;AAC1C,sBAAgB,KAAK,MAAM,cAAc,MAAM,UAAU;AAAA,IAC3D;AAAA,EACF;AAGA,QAAM,aAA0B,sBAAsB,SAAS;AAC/D,MAAI,YAAY;AACd,IAAK,SAAS,UAAU;AAAA,EAC1B;AAGA,QAAY,oBAAoB,KAAK,WAAW,WAAW;AAG3D,iBAAe,SAAS;AAGxB,MAAI,UAAU;AACZ,IAAK,WAAW,QAAQ;AAAA,EAC1B;AAGA,oBAAkB,SAAS;AAE3B,SAAO;AACT;;;ADrNA,IAAI,SAAwB;AAG5B,IAAM,gBAAgB,oBAAI,IAAoB;AAE9C,IAAM,iBAAiB,oBAAI,IAAoB;AAE/C,IAAMC,oBAAmB,oBAAI,IAAoB;AAUjD,SAAS,eAAuB;AAC9B,SAAOC,MAAK,UAAU,GAAG,uBAAuB;AAClD;AAEA,SAAS,yBAA+B;AACtC,QAAM,MAAM,UAAU;AACtB,EAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,QAAM,WAAmC,CAAC;AAC1C,aAAW,CAAC,IAAI,GAAG,KAAK,eAAe;AACrC,aAAS,EAAE,IAAI;AAAA,EACjB;AACA,EAAAC,eAAc,aAAa,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AAC1E;AAEO,SAAS,sBAA8C;AAC5D,QAAM,IAAI,aAAa;AACvB,MAAI,CAACC,YAAW,CAAC,EAAG,QAAO,CAAC;AAC5B,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,GAAG,OAAO,CAAC;AAAA,EAC5C,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,mBAAmB,WAAmB,KAAmB;AACvE,gBAAc,IAAI,WAAW,GAAG;AAChC,yBAAuB;AACzB;AAEO,SAAS,oBAAoB,WAAmB,aAAqB,UAAwB;AAClG,iBAAe,IAAI,WAAW,WAAW;AACzC,EAAAC,kBAAiB,IAAI,WAAW,QAAQ;AAC1C;AAEA,eAAe,cAAc,KAAiC;AAC5D,MAAI;AACF,YAAQ,IAAI,MAAM;AAAA,MAChB,KAAK,SAAS;AACZ,cAAM,UAAU,MAAqB,aAAa,IAAI,MAAM,IAAI,KAAK,IAAI,aAAa,IAAI,UAAU;AACpG,2BAAmB,QAAQ,IAAI,IAAI,GAAG;AACtC,uBAAe,IAAI,QAAQ,IAAI,IAAI,WAAW;AAC9C,QAAAA,kBAAiB,IAAI,QAAQ,IAAI,IAAI,UAAU;AAC/C,eAAO,EAAE,IAAI,MAAM,MAAM,EAAE,WAAW,QAAQ,GAAG,EAAE;AAAA,MACrD;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,YAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,cAAM,SAAS,MAAqB,YAAY,IAAI,WAAW,KAAK,IAAI,WAAW,IAAI,MAAM,IAAI,aAAa,IAAI,QAAQ;AAC1H,eAAO,EAAE,IAAI,MAAM,MAAM,EAAE,SAAS,OAAO,QAAQ,EAAE;AAAA,MACvD;AAAA,MAEA,KAAK,UAAU;AACb,cAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,YAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,cAAM,WAAWA,kBAAiB,IAAI,IAAI,SAAS;AACnD,YAAI,CAAC,SAAU,QAAO,EAAE,IAAI,OAAO,OAAO,qCAAqC,IAAI,SAAS,GAAG;AAC/F,cAAqB,aAAa,KAAK,IAAI,WAAW,IAAI,SAAS,IAAI,QAAQ,QAAQ;AACvF,eAAO,EAAE,IAAI,KAAK;AAAA,MACpB;AAAA,MAEA,KAAK,UAAU;AACb,cAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,YAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,cAAqB,aAAa,KAAK,IAAI,WAAW,IAAI,SAAS,IAAI,OAAO;AAC9E,eAAO,EAAE,IAAI,KAAK;AAAA,MACpB;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,YAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,cAAqB,YAAY,IAAI,WAAW,KAAK,IAAI,UAAU;AACnE,eAAO,EAAE,IAAI,KAAK;AAAA,MACpB;AAAA,MAEA,KAAK,YAAY;AACf,cAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,YAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,cAAqB,eAAe,IAAI,WAAW,KAAK,IAAI,MAAM;AAClE,eAAO,EAAE,IAAI,KAAK;AAAA,MACpB;AAAA,MAEA,KAAK,UAAU;AACb,YAAI,IAAI,WAAW;AACjB,gBAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,cAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,gBAAM,UAAyB,iBAAiB,KAAK,IAAI,SAAS;AAClE,iBAAO,EAAE,IAAI,MAAM,MAAM,EAAE,QAAuD,EAAE;AAAA,QACtF;AACA,eAAO,EAAE,IAAI,MAAM,MAAM,EAAE,SAAS,iBAAiB,EAAE;AAAA,MACzD;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,cAA8C,CAAC;AACrD,YAAI,IAAI,KAAK;AAEX,gBAAM,WAAW,oBAAI,IAAY;AACjC,qBAAW,OAAO,cAAc,OAAO,GAAG;AACxC,gBAAI,SAAS,IAAI,GAAG,EAAG;AACvB,qBAAS,IAAI,GAAG;AAChB,kBAAM,WAA0B,aAAa,GAAG;AAChD,wBAAY,KAAK,GAAG,SAAS,IAAI,QAAM,EAAE,GAAG,GAAG,IAAI,EAAwC,CAAC;AAAA,UAC9F;AAAA,QACF,OAAO;AAEL,gBAAM,WAA0B,aAAa,IAAI,GAAG;AACpD,sBAAY,KAAK,GAAG,SAAS,IAAI,QAAM,EAAE,GAAG,GAAG,KAAK,IAAI,IAAI,EAAwC,CAAC;AAErG,cAAI,aAAa,YAAY;AAC7B,gBAAM,WAAW,oBAAI,IAAY,CAAC,IAAI,GAAG,CAAC;AAC1C,qBAAW,OAAO,cAAc,OAAO,GAAG;AACxC,gBAAI,SAAS,IAAI,GAAG,EAAG;AACvB,qBAAS,IAAI,GAAG;AAChB,0BAA6B,aAAa,GAAG,EAAE;AAAA,UACjD;AACA,cAAI,aAAa,YAAY,QAAQ;AACnC,mBAAO,EAAE,IAAI,MAAM,MAAM,EAAE,UAAU,aAAa,YAAY,UAAU,KAAK,EAAE;AAAA,UACjF;AAAA,QACF;AACA,eAAO,EAAE,IAAI,MAAM,MAAM,EAAE,UAAU,YAAY,EAAE;AAAA,MACrD;AAAA,MAEA,KAAK,UAAU;AACb,YAAI,MAAM,cAAc,IAAI,IAAI,SAAS;AACzC,YAAI,CAAC,KAAK;AAER,gBAAM,YAAY,GAAG,IAAI,GAAG,uBAAuB,IAAI,SAAS;AAChE,cAAIF,YAAW,SAAS,GAAG;AACzB,kBAAM,IAAI;AACV,+BAAmB,IAAI,WAAW,GAAG;AAAA,UACvC,OAAO;AACL,mBAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,4BAA4B,SAAS,GAAG;AAAA,UACtG;AAAA,QACF;AACA,uBAAe,IAAI,IAAI,WAAW,IAAI,WAAW;AACjD,QAAAE,kBAAiB,IAAI,IAAI,WAAW,IAAI,UAAU;AAClD,cAAM,UAAU,MAAqB,cAAc,IAAI,WAAW,KAAK,IAAI,aAAa,IAAI,YAAY,IAAI,OAAO;AACnH,eAAO,EAAE,IAAI,MAAM,MAAM,EAAE,WAAW,QAAQ,IAAI,QAAQ,QAAQ,OAAO,EAAE;AAAA,MAC7E;AAAA,MAEA,KAAK,2BAA2B;AAC9B,cAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,YAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,cAAqB,4BAA4B,KAAK,IAAI,WAAW,IAAI,SAAS,IAAI,eAAe;AACrG,eAAO,EAAE,IAAI,KAAK;AAAA,MACpB;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,MAAM,cAAc,IAAI,IAAI,SAAS;AAC3C,YAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,oBAAoB,IAAI,SAAS,GAAG;AACzE,cAAM,eAAe,MAAqB,WAAW,IAAI,WAAW,GAAG;AACvE,sBAAc,OAAO,IAAI,SAAS;AAClC,uBAAe,OAAO,IAAI,SAAS;AACnC,QAAAA,kBAAiB,OAAO,IAAI,SAAS;AACrC,+BAAuB;AACvB,eAAO,EAAE,IAAI,MAAM,MAAM,EAAE,cAAc,WAAW,IAAI,UAAU,EAAE;AAAA,MACtE;AAAA,MAEA;AACE,eAAO,EAAE,IAAI,OAAO,OAAO,yBAA0B,IAAgC,IAAI,GAAG;AAAA,IAChG;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,EAAE,IAAI,OAAO,OAAO,QAAQ;AAAA,EACrC;AACF;AAEO,SAAS,cAA+B;AAC7C,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAM,OAAO,WAAW;AAExB,QAAIH,YAAW,IAAI,GAAG;AACpB,iBAAW,IAAI;AAAA,IACjB;AAEA,aAAS,aAAa,CAAC,SAAS;AAC9B,UAAI,SAAS;AAEb,WAAK,GAAG,QAAQ,CAAC,UAAU;AACzB,kBAAU,MAAM,SAAS;AACzB,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI;AAEnB,mBAAW,QAAQ,OAAO;AACxB,cAAI,CAAC,KAAK,KAAK,EAAG;AAClB,cAAI;AACJ,cAAI;AACF,kBAAM,KAAK,MAAM,IAAI;AAAA,UACvB,QAAQ;AACN,iBAAK,MAAM,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,eAAe,CAAC,IAAI,IAAI;AACtE;AAAA,UACF;AAEA,wBAAc,GAAG,EAAE,KAAK,CAAC,QAAQ;AAC/B,iBAAK,MAAM,KAAK,UAAU,GAAG,IAAI,IAAI;AAAA,UACvC,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAED,WAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,gBAAQ,MAAM,gCAAgC,IAAI,OAAO;AAAA,MAC3D,CAAC;AAAA,IACH,CAAC;AAED,WAAO,GAAG,SAAS,MAAM;AAEzB,WAAO,OAAO,MAAM,MAAM;AACxB,cAAQ,IAAI,kCAAkC,IAAI,EAAE;AACpD,MAAAG,SAAQ,MAAO;AAAA,IACjB,CAAC;AAAA,EACH,CAAC;AACH;AAEO,SAAS,aAA4B;AAC1C,SAAO,IAAI,QAAQ,CAACA,aAAY;AAC9B,QAAI,CAAC,QAAQ;AACX,MAAAA,SAAQ;AACR;AAAA,IACF;AACA,WAAO,MAAM,MAAM;AACjB,YAAM,OAAO,WAAW;AACxB,UAAIH,YAAW,IAAI,GAAG;AACpB,mBAAW,IAAI;AAAA,MACjB;AACA,eAAS;AACT,MAAAG,SAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;;;AFhPA,SAAS,aAAmB;AAC1B,EAAAC,WAAU,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C;AAEA,SAAS,eAAe,KAAsB;AAC5C,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAyB;AAChC,QAAM,UAAU,cAAc;AAC9B,MAAI;AACF,UAAM,MAAM,SAASC,cAAa,SAAS,OAAO,EAAE,KAAK,GAAG,EAAE;AAC9D,WAAO,OAAO,eAAe,GAAG,IAAI,MAAM;AAAA,EAC5C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAuB;AAC9B,QAAM,MAAM,QAAQ;AACpB,MAAI,KAAK;AACP,YAAQ,MAAM,0CAA0C,GAAG,uDAAuD;AAClH,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,EAAAC,eAAc,cAAc,GAAG,OAAO,QAAQ,GAAG,GAAG,OAAO;AAC7D;AAEA,SAAS,iBAAuB;AAC9B,MAAI;AACF,IAAAC,YAAW,cAAc,CAAC;AAAA,EAC5B,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,aAAsB;AAC7B,QAAM,MAAM,QAAQ;AACpB,MAAI,CAAC,KAAK;AACR,YAAQ,IAAI,kCAAkC;AAE9C,mBAAe;AACf,WAAO;AAAA,EACT;AAEA,UAAQ,IAAI,mCAAmC,GAAG,MAAM;AACxD,MAAI;AACF,YAAQ,KAAK,KAAK,SAAS;AAAA,EAC7B,QAAQ;AACN,YAAQ,MAAM,4CAA4C,GAAG,EAAE;AAC/D,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,CAAC,eAAe,GAAG,GAAG;AACxB,cAAQ,IAAI,2BAA2B;AACvC,qBAAe;AACf,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,KAAK,IAAI,IAAI;AAC1B,WAAO,KAAK,IAAI,IAAI,MAAM;AAAA,IAAa;AAAA,EACzC;AAEA,UAAQ,MAAM,0BAA0B,GAAG,2CAA2C;AACtF,MAAI;AACF,YAAQ,KAAK,KAAK,SAAS;AAAA,EAC7B,QAAQ;AAAA,EAAqB;AAC7B,iBAAe;AACf,SAAO;AACT;AAEA,eAAe,kBAAiC;AAC9C,QAAM,WAAW,oBAAoB;AACrC,QAAM,UAAU,OAAO,QAAQ,QAAQ;AAEvC,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,mCAAmC;AAC/C;AAAA,EACF;AAEA,MAAI,YAAY;AAChB,aAAW,CAAC,WAAW,GAAG,KAAK,SAAS;AACtC,UAAM,YAAY,UAAU,KAAK,SAAS;AAC1C,QAAI,CAACC,YAAW,SAAS,GAAG;AAC1B;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,KAAK,MAAMH,cAAa,WAAW,OAAO,CAAC;AAC3D,UAAI,QAAQ,WAAW,YAAY,QAAQ,WAAW,UAAU;AAC9D,2BAAmB,WAAW,GAAG;AACjC,mCAA2B,WAAW,QAAQ,UAAU,CAAC,CAAC;AAG1D,YAAI,QAAQ,mBAAmB,QAAQ,cAAc;AACnD,gBAAM,YAAY,UAAU,QAAQ,YAAY;AAChD,cAAI,UAAU,SAAS,GAAG;AACxB,gCAAoB,WAAW,QAAQ,iBAAiB,QAAQ,YAAY;AAC5E,wBAAY,WAAW,QAAQ,YAAY;AAC3C,yBAAa,WAAW,KAAK,QAAQ,eAAe;AACpD,gCAAoB,WAAW,QAAQ,YAAY;AAGnD,kBAAM,sBAAsB,CAAC,GAAG,QAAQ,kBAAkB,EAAE,QAAQ,EAAE,KAAK,OAAK,CAAC,EAAE,eAAe,EAAE,MAAM;AAC1G,gBAAI,qBAAqB,QAAQ;AAC/B,oCAAsB,WAAW,oBAAoB,MAAM;AAAA,YAC7D;AAEA,oBAAQ,IAAI,kCAAkC,SAAS,mBAAmB,QAAQ,YAAY,EAAE;AAGhG,gBAAI,QAAQ,WAAW,YAAY,QAAQ,OAAO,SAAS,GAAG;AAC5D,oBAAM,mBAAmB,QAAQ,OAAO,KAAK,OAAK,EAAE,WAAW,SAAS;AACxE,kBAAI,CAAC,kBAAkB;AACrB,sBAAM,cAAc,IAAI,IAAI,UAAU,IAAI,OAAK,EAAE,MAAM,CAAC;AACxD,sBAAM,qBAAqB,sBAAsB,SAAS;AAC1D,sBAAM,oBAAoB,sBAAsB,YAAY,IAAI,kBAAkB;AAClF,oBAAI,CAAC,mBAAmB;AACtB,0BAAQ,IAAI,qCAAqC,SAAS,+CAA+C;AACzG,wBAAMI,iBAAgB,WAAW,KAAK,QAAQ,YAAa;AAAA,gBAC7D;AAAA,cACF;AAAA,YACF;AAAA,UACF,OAAO;AAEL,gBAAI,QAAQ,WAAW,UAAU;AAC/B,oBAAkB,oBAAoB,KAAK,WAAW,QAAQ;AAC9D,sBAAQ,IAAI,sBAAsB,SAAS,uCAAuC;AAAA,YACpF;AAAA,UACF;AAAA,QACF;AAEA;AAAA,MACF;AAAA,IACF,QAAQ;AACN,cAAQ,MAAM,+CAA+C,SAAS,YAAY;AAAA,IACpF;AAAA,EACF;AAEA,UAAQ,IAAI,wBAAwB,SAAS,2BAA2B;AAC1E;AAEA,eAAe,cAA6B;AAC1C,UAAQ,IAAI,+BAA+B;AAC3C,aAAW;AACX,iBAAe;AAEf,QAAM,SAAS,WAAW,QAAQ,IAAI,CAAC;AAEvC,qBAAmBA,gBAAe;AAElC,QAAM,YAAY;AAClB,eAAa,OAAO,cAAc;AAElC,QAAM,gBAAgB;AAEtB,QAAM,WAAW,YAAY;AAC3B,YAAQ,IAAI,6BAA6B;AACzC,gBAAY;AACZ,UAAM,WAAW;AACjB,mBAAe;AACf,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,WAAW,QAAQ;AAC9B,UAAQ,GAAG,UAAU,QAAQ;AAC/B;AAEA,IAAM,UAAU,QAAQ,KAAK,CAAC;AAE9B,QAAQ,SAAS;AAAA,EACf,KAAK;AACH,eAAW;AACX;AAAA,EAEF,KAAK,WAAW;AACd,eAAW;AAEX,UAAM,OAAO,KAAK,IAAI,IAAI;AAC1B,WAAO,KAAK,IAAI,IAAI,MAAM;AAAA,IAAa;AACvC,gBAAY,EAAE,MAAM,CAAC,QAAQ;AAC3B,cAAQ,MAAM,2BAA2B,GAAG;AAC5C,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EACF;AAAA,EAEA,KAAK;AAAA,EACL,KAAK;AACH,gBAAY,EAAE,MAAM,CAAC,QAAQ;AAC3B,cAAQ,MAAM,2BAA2B,GAAG;AAC5C,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EAEF;AACE,YAAQ,MAAM,+BAA+B,OAAO,EAAE;AACtD,YAAQ,MAAM,uCAAuC;AACrD,YAAQ,KAAK,CAAC;AAClB;","names":["mkdirSync","readFileSync","writeFileSync","unlinkSync","existsSync","existsSync","writeFileSync","readFileSync","mkdirSync","join","existsSync","readdirSync","readFileSync","resolve","readFileSync","readFileSync","writeFileSync","readFileSync","join","registryPath","command","readFileSync","writeFileSync","readFileSync","writeFileSync","mkdirSync","readdirSync","existsSync","resolve","execSync","existsSync","mkdirSync","readFileSync","readdirSync","dirname","join","EXEC_ENV","exec","execSync","execSafe","shellQuote","readFileSync","join","mkdirSync","dirname","existsSync","readdirSync","resolve","readFileSync","writeFileSync","existsSync","shellQuote","readdirSync","mkdirSync","orchPaneId","livePanes","livePaneIds","existsSync","readdirSync","onAllAgentsDone","sessionWindowMap","join","mkdirSync","writeFileSync","existsSync","readFileSync","sessionWindowMap","resolve","mkdirSync","readFileSync","writeFileSync","unlinkSync","existsSync","onAllAgentsDone"]}
@@ -0,0 +1,50 @@
1
+ # templates/
2
+
3
+ System prompt templates for orchestrator and agent initialization.
4
+
5
+ ## Core Templates
6
+
7
+ - **orchestrator.md** — Orchestrator system prompt. Defines orchestrator role (coordinator, not implementer), cycle workflow, phase-based thinking (explore → spec → plan → implement → review → test), context persistence via plan.md/logs.md, work right-sizing (~30 tool calls per item), and validation patterns. Rendered with `<state>` block injected containing agent reports, cycle history, plan/logs references.
8
+ - **agent-suffix.md** — Agent system prompt suffix. Contains `{{SESSION_ID}}` and `{{INSTRUCTION}}` placeholders. Rendered once per agent spawn.
9
+ - **banner.txt** — ASCII banner (cosmetic, displayed on daemon startup or CLI output).
10
+
11
+ ## Configuration Files
12
+
13
+ - **orchestrator-settings.json** — Default orchestrator configuration (model, behavior flags, rendering options). Overridden by project `.sisyphus/orchestrator-settings.json`.
14
+ - **agent-settings.json** — Default agent configuration (model, behavior flags, plugin overrides). Overridden by project `.sisyphus/agent-settings.json`.
15
+
16
+ ## Subdirectories
17
+
18
+ - **agent-plugin/** — Agent system prompts for crouton-kit plugin agent types (e.g., `debug`, `implement`, `plan`). Each file named `{agent-type}.md` provides specialized role & strategy.
19
+ - **orchestrator-plugin/** — Orchestrator overrides for crouton-kit plugin workflows.
20
+
21
+ ## Rendering Rules
22
+
23
+ **Orchestrator prompt**:
24
+ 1. Read `orchestrator.md` (or project override `.sisyphus/orchestrator.md`)
25
+ 2. Load settings from `orchestrator-settings.json` (or project override)
26
+ 3. Append `<state>` block with: agent reports, cycle count, history, plan.md and logs.md references
27
+ 4. Pass to Claude via `--append-system-prompt` flag
28
+ 5. User prompt: concise cycle instruction ("review reports, delegate next phase")
29
+
30
+ **Agent prompt**:
31
+ 1. Read `agent-suffix.md`
32
+ 2. Load settings from `agent-settings.json` (or project override)
33
+ 3. Replace `{{SESSION_ID}}` with session UUID
34
+ 4. Replace `{{INSTRUCTION}}` with task instruction (e.g., "implement login feature")
35
+ 5. Pass via `--append-system-prompt` flag
36
+ 6. User prompt: instruction again (for clarity)
37
+
38
+ **Plugin prompts** (`agent-plugin/*.md`):
39
+ - Used only when agent spawned with `--agent-type sisyphus:{type}`
40
+ - Replaces default agent-suffix.md rendering
41
+ - Same placeholder substitution rules apply
42
+
43
+ ## Important Boundaries
44
+
45
+ - Do **not** hardcode session IDs or agent names—use placeholders
46
+ - Do **not** include raw JSON in prompts—use human-readable `<state>` formatting
47
+ - Do **not** reference external files (only relative paths in `.sisyphus/`)
48
+ - Do **keep prompts concise**—Claude reads full state separately
49
+ - Settings files must be valid JSON; use project overrides to customize behavior per-workspace
50
+ - Orchestrator template should emphasize phase-based methodology and context preservation, not encourage autonomous rushing
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: debug
3
+ description: Systematic bug diagnosis. Investigate only — no code changes.
4
+ model: opus
5
+ color: red
6
+ ---
7
+
8
+ You are a systematic debugger. Follow this 3-phase methodology:
9
+
10
+ ## Phase 1: Reconnaissance
11
+
12
+ Read the key files yourself. You need firsthand context.
13
+
14
+ - Entry points and failure points
15
+ - Data flow through the bug area
16
+ - `git log`/`git blame` near the failure (recent changes are high-signal)
17
+ - Error messages, stack traces, or symptoms
18
+
19
+ ## Phase 2: Investigate
20
+
21
+ Based on recon, assess difficulty and scale your response:
22
+
23
+ **Simple** (clear error, obvious area): Investigate solo. Use Explore subagents for code tracing if the area is large.
24
+
25
+ **Medium** (unclear cause, multiple origins, crosses 2-3 modules): Spawn 2-3 parallel senior-advisor subagents with concrete tasks:
26
+ - Data Flow Tracer: trace values from entry to failure
27
+ - Assumption Auditor: list and verify assumptions about types/nullability/ordering/timing
28
+ - Change Investigator: git log/blame for recent regressions
29
+
30
+ **Hard** (intermittent, race conditions, crosses many modules): Create an agent team with 3-5 teammates, each with precise scope. Teammates must actively challenge each other's theories.
31
+
32
+ ## Phase 3: Synthesize & Report
33
+
34
+ 1. **Root Cause**: Exact failing line(s) and why
35
+ 2. **Evidence**: Code snippets, data flow, git blame findings
36
+ 3. **Confidence**: High / Medium / Low
37
+ 4. **Recommended Fix**: Concrete approach
38
+
39
+ No code changes — investigate only (reproduction tests are the exception).