panopticon-cli 0.3.2 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/tmux.ts","../../src/lib/hooks.ts","../../src/lib/cv.ts","../../src/lib/agents.ts","../../package.json","../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/commands/sync.ts","../../src/cli/commands/restore.ts","../../src/cli/commands/backup.ts","../../src/cli/commands/skills.ts","../../src/cli/commands/work/index.ts","../../src/cli/commands/work/issue.ts","../../src/cli/commands/work/status.ts","../../src/cli/commands/work/tell.ts","../../src/cli/commands/work/kill.ts","../../src/cli/commands/work/pending.ts","../../src/cli/commands/work/approve.ts","../../src/cli/commands/work/plan.ts","../../src/cli/commands/work/list.ts","../../src/cli/commands/work/triage.ts","../../src/cli/commands/work/hook.ts","../../src/cli/commands/work/recover.ts","../../src/cli/commands/work/cv.ts","../../src/cli/commands/work/context.ts","../../src/lib/context.ts","../../src/cli/commands/work/health.ts","../../src/lib/health.ts","../../src/cli/commands/workspace.ts","../../src/lib/worktree.ts","../../src/lib/template.ts","../../src/lib/skills-merge.ts","../../src/cli/commands/install.ts","../../src/cli/commands/cloister/index.ts","../../src/cli/commands/cloister/status.ts","../../src/lib/cloister/service.ts","../../src/lib/cloister/config.ts","../../src/lib/cloister/health.ts","../../src/lib/cloister/database.ts","../../src/lib/cloister/specialists.ts","../../src/lib/cost-parsers/jsonl-parser.ts","../../src/lib/cost.ts","../../src/lib/runtimes/index.ts","../../src/lib/runtimes/types.ts","../../src/lib/runtimes/claude-code.ts","../../src/lib/cloister/triggers.ts","../../src/lib/cloister/handoff.ts","../../src/lib/cloister/handoff-context.ts","../../src/lib/cloister/handoff-logger.ts","../../src/cli/commands/cloister/start.ts","../../src/cli/commands/cloister/stop.ts","../../src/cli/commands/setup/index.ts","../../src/cli/commands/setup/hooks.ts","../../src/cli/commands/project.ts","../../src/cli/commands/doctor.ts","../../src/cli/commands/update.ts"],"sourcesContent":["import { execSync } from 'child_process';\n\nexport interface TmuxSession {\n name: string;\n created: Date;\n attached: boolean;\n windows: number;\n}\n\nexport function listSessions(): TmuxSession[] {\n try {\n const output = execSync('tmux list-sessions -F \"#{session_name}|#{session_created}|#{session_attached}|#{session_windows}\"', {\n encoding: 'utf8',\n });\n\n return output.trim().split('\\n').filter(Boolean).map(line => {\n const [name, created, attached, windows] = line.split('|');\n return {\n name,\n created: new Date(parseInt(created) * 1000),\n attached: attached === '1',\n windows: parseInt(windows),\n };\n });\n } catch {\n return []; // No sessions\n }\n}\n\nexport function sessionExists(name: string): boolean {\n try {\n execSync(`tmux has-session -t ${name} 2>/dev/null`);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function createSession(\n name: string,\n cwd: string,\n initialCommand?: string,\n options?: { env?: Record<string, string> }\n): void {\n const escapedCwd = cwd.replace(/\"/g, '\\\\\"');\n\n // Build environment variable flags for tmux\n let envFlags = '';\n if (options?.env) {\n for (const [key, value] of Object.entries(options.env)) {\n envFlags += ` -e ${key}=\"${value.replace(/\"/g, '\\\\\"')}\"`;\n }\n }\n\n // For complex commands (with special chars), start session first then send command\n if (initialCommand && (initialCommand.includes('`') || initialCommand.includes('\\n') || initialCommand.length > 500)) {\n // Create session without command\n execSync(`tmux new-session -d -s ${name} -c \"${escapedCwd}\"${envFlags}`);\n\n // Small delay to let session initialize\n execSync('sleep 0.5');\n\n // Send the command in chunks if needed (tmux has buffer limits)\n // First, write to a temp file and source it\n const tmpFile = `/tmp/pan-cmd-${name}.sh`;\n const fs = require('fs');\n fs.writeFileSync(tmpFile, initialCommand);\n fs.chmodSync(tmpFile, '755');\n\n // Execute the script\n execSync(`tmux send-keys -t ${name} \"bash ${tmpFile}\" Enter`);\n } else if (initialCommand) {\n // Simple command - use inline\n const cmd = `tmux new-session -d -s ${name} -c \"${escapedCwd}\"${envFlags} \"${initialCommand.replace(/\"/g, '\\\\\"')}\"`;\n execSync(cmd);\n } else {\n execSync(`tmux new-session -d -s ${name} -c \"${escapedCwd}\"${envFlags}`);\n }\n}\n\nexport function killSession(name: string): void {\n execSync(`tmux kill-session -t ${name}`);\n}\n\nexport function sendKeys(sessionName: string, keys: string): void {\n // CRITICAL: Send keys and Enter as separate commands\n // This is the correct way - combining them doesn't work\n const escapedKeys = keys.replace(/\"/g, '\\\\\"');\n execSync(`tmux send-keys -t ${sessionName} \"${escapedKeys}\"`);\n execSync(`tmux send-keys -t ${sessionName} Enter`);\n}\n\nexport function capturePane(sessionName: string, lines: number = 50): string {\n try {\n return execSync(`tmux capture-pane -t ${sessionName} -p -S -${lines}`, {\n encoding: 'utf8',\n });\n } catch {\n return '';\n }\n}\n\nexport function getAgentSessions(): TmuxSession[] {\n return listSessions().filter(s => s.name.startsWith('agent-'));\n}\n","/**\n * GUPP Hooks System\n *\n * \"If there is work on your Hook, YOU MUST RUN IT.\"\n *\n * Hooks are persistent work queues for agents. When an agent starts,\n * it checks its hook for pending work and executes immediately.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from './paths.js';\n\nexport interface HookItem {\n id: string;\n type: 'task' | 'message' | 'notification';\n priority: 'urgent' | 'high' | 'normal' | 'low';\n source: string;\n payload: {\n issueId?: string;\n message?: string;\n action?: string;\n context?: Record<string, any>;\n };\n createdAt: string;\n expiresAt?: string;\n}\n\nexport interface Hook {\n agentId: string;\n items: HookItem[];\n lastChecked?: string;\n}\n\nfunction getHookDir(agentId: string): string {\n return join(AGENTS_DIR, agentId);\n}\n\nfunction getHookFile(agentId: string): string {\n return join(getHookDir(agentId), 'hook.json');\n}\n\nfunction getMailDir(agentId: string): string {\n return join(getHookDir(agentId), 'mail');\n}\n\n/**\n * Initialize hook structure for an agent\n */\nexport function initHook(agentId: string): void {\n const hookDir = getHookDir(agentId);\n const mailDir = getMailDir(agentId);\n\n mkdirSync(hookDir, { recursive: true });\n mkdirSync(mailDir, { recursive: true });\n\n const hookFile = getHookFile(agentId);\n if (!existsSync(hookFile)) {\n const hook: Hook = {\n agentId,\n items: [],\n };\n writeFileSync(hookFile, JSON.stringify(hook, null, 2));\n }\n}\n\n/**\n * Get the hook for an agent\n */\nexport function getHook(agentId: string): Hook | null {\n const hookFile = getHookFile(agentId);\n if (!existsSync(hookFile)) {\n return null;\n }\n\n try {\n const content = readFileSync(hookFile, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Add work to an agent's hook (GUPP trigger)\n */\nexport function pushToHook(agentId: string, item: Omit<HookItem, 'id' | 'createdAt'>): HookItem {\n initHook(agentId);\n\n const hook = getHook(agentId) || { agentId, items: [] };\n\n const newItem: HookItem = {\n ...item,\n id: `hook-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n createdAt: new Date().toISOString(),\n };\n\n hook.items.push(newItem);\n writeFileSync(getHookFile(agentId), JSON.stringify(hook, null, 2));\n\n return newItem;\n}\n\n/**\n * Check if agent has pending work (GUPP check)\n */\nexport function checkHook(agentId: string): { hasWork: boolean; urgentCount: number; items: HookItem[] } {\n const hook = getHook(agentId);\n\n if (!hook || hook.items.length === 0) {\n // Also check mail directory for incoming messages\n const mailDir = getMailDir(agentId);\n if (existsSync(mailDir)) {\n const mails = readdirSync(mailDir).filter((f) => f.endsWith('.json'));\n if (mails.length > 0) {\n // Convert mail to hook items\n const mailItems: HookItem[] = mails.map((file) => {\n try {\n const content = readFileSync(join(mailDir, file), 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n }).filter(Boolean) as HookItem[];\n\n return {\n hasWork: mailItems.length > 0,\n urgentCount: mailItems.filter((i) => i.priority === 'urgent').length,\n items: mailItems,\n };\n }\n }\n\n return { hasWork: false, urgentCount: 0, items: [] };\n }\n\n // Filter out expired items\n const now = new Date();\n const activeItems = hook.items.filter((item) => {\n if (item.expiresAt) {\n return new Date(item.expiresAt) > now;\n }\n return true;\n });\n\n // Sort by priority: urgent > high > normal > low\n const priorityOrder = { urgent: 0, high: 1, normal: 2, low: 3 };\n activeItems.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);\n\n return {\n hasWork: activeItems.length > 0,\n urgentCount: activeItems.filter((i) => i.priority === 'urgent').length,\n items: activeItems,\n };\n}\n\n/**\n * Pop the next work item from hook (after execution)\n */\nexport function popFromHook(agentId: string, itemId: string): boolean {\n const hook = getHook(agentId);\n if (!hook) return false;\n\n const index = hook.items.findIndex((i) => i.id === itemId);\n if (index === -1) return false;\n\n hook.items.splice(index, 1);\n hook.lastChecked = new Date().toISOString();\n writeFileSync(getHookFile(agentId), JSON.stringify(hook, null, 2));\n\n return true;\n}\n\n/**\n * Clear all items from hook\n */\nexport function clearHook(agentId: string): void {\n const hook = getHook(agentId);\n if (!hook) return;\n\n hook.items = [];\n hook.lastChecked = new Date().toISOString();\n writeFileSync(getHookFile(agentId), JSON.stringify(hook, null, 2));\n}\n\n/**\n * Send a message to an agent's mailbox\n */\nexport function sendMail(\n toAgentId: string,\n from: string,\n message: string,\n priority: HookItem['priority'] = 'normal'\n): void {\n initHook(toAgentId);\n const mailDir = getMailDir(toAgentId);\n\n const mailItem: HookItem = {\n id: `mail-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n type: 'message',\n priority,\n source: from,\n payload: { message },\n createdAt: new Date().toISOString(),\n };\n\n writeFileSync(\n join(mailDir, `${mailItem.id}.json`),\n JSON.stringify(mailItem, null, 2)\n );\n}\n\n/**\n * Get and clear mail for an agent\n */\nexport function collectMail(agentId: string): HookItem[] {\n const mailDir = getMailDir(agentId);\n if (!existsSync(mailDir)) return [];\n\n const mails: HookItem[] = [];\n const files = readdirSync(mailDir).filter((f) => f.endsWith('.json'));\n\n for (const file of files) {\n const filePath = join(mailDir, file);\n try {\n const content = readFileSync(filePath, 'utf-8');\n mails.push(JSON.parse(content));\n unlinkSync(filePath); // Remove after reading\n } catch {\n // Skip invalid mail\n }\n }\n\n return mails;\n}\n\n/**\n * Generate GUPP prompt for agent startup\n */\nexport function generateGUPPPrompt(agentId: string): string | null {\n const { hasWork, urgentCount, items } = checkHook(agentId);\n\n if (!hasWork) return null;\n\n const lines: string[] = [\n '# GUPP: Work Found on Your Hook',\n '',\n '> \"If there is work on your Hook, YOU MUST RUN IT.\"',\n '',\n ];\n\n if (urgentCount > 0) {\n lines.push(`⚠️ **${urgentCount} URGENT item(s) require immediate attention**`);\n lines.push('');\n }\n\n lines.push(`## Pending Work Items (${items.length})`);\n lines.push('');\n\n for (const item of items) {\n const priorityEmoji = {\n urgent: '🔴',\n high: '🟠',\n normal: '🟢',\n low: '⚪',\n }[item.priority];\n\n lines.push(`### ${priorityEmoji} ${item.type.toUpperCase()}: ${item.id}`);\n lines.push(`- Source: ${item.source}`);\n lines.push(`- Created: ${item.createdAt}`);\n\n if (item.payload.issueId) {\n lines.push(`- Issue: ${item.payload.issueId}`);\n }\n if (item.payload.message) {\n lines.push(`- Message: ${item.payload.message}`);\n }\n if (item.payload.action) {\n lines.push(`- Action: ${item.payload.action}`);\n }\n lines.push('');\n }\n\n lines.push('---');\n lines.push('');\n lines.push('Execute these items in priority order. Use `bd hook pop <id>` after completing each item.');\n\n return lines.join('\\n');\n}\n","/**\n * Agent CV (Work History) System\n *\n * Tracks agent performance over time to enable capability-based routing.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from './paths.js';\n\nexport interface WorkEntry {\n issueId: string;\n startedAt: string;\n completedAt?: string;\n outcome: 'success' | 'failed' | 'abandoned' | 'in_progress';\n duration?: number; // minutes\n skills?: string[];\n failureReason?: string;\n commits?: number;\n linesChanged?: number;\n}\n\nexport interface AgentCV {\n agentId: string;\n createdAt: string;\n lastActive: string;\n runtime: string;\n model: string;\n stats: {\n totalIssues: number;\n successCount: number;\n failureCount: number;\n abandonedCount: number;\n avgDuration: number; // minutes\n successRate: number; // 0-1\n };\n skillsUsed: string[];\n recentWork: WorkEntry[];\n}\n\nfunction getCVFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'cv.json');\n}\n\n/**\n * Get or create an agent's CV\n */\nexport function getAgentCV(agentId: string): AgentCV {\n const cvFile = getCVFile(agentId);\n\n if (existsSync(cvFile)) {\n try {\n return JSON.parse(readFileSync(cvFile, 'utf-8'));\n } catch {}\n }\n\n // Create new CV\n const cv: AgentCV = {\n agentId,\n createdAt: new Date().toISOString(),\n lastActive: new Date().toISOString(),\n runtime: 'claude',\n model: 'sonnet',\n stats: {\n totalIssues: 0,\n successCount: 0,\n failureCount: 0,\n abandonedCount: 0,\n avgDuration: 0,\n successRate: 0,\n },\n skillsUsed: [],\n recentWork: [],\n };\n\n saveAgentCV(cv);\n return cv;\n}\n\n/**\n * Save an agent's CV\n */\nexport function saveAgentCV(cv: AgentCV): void {\n const dir = join(AGENTS_DIR, cv.agentId);\n mkdirSync(dir, { recursive: true });\n writeFileSync(getCVFile(cv.agentId), JSON.stringify(cv, null, 2));\n}\n\n/**\n * Start tracking work for an agent\n */\nexport function startWork(agentId: string, issueId: string, skills?: string[]): void {\n const cv = getAgentCV(agentId);\n\n const entry: WorkEntry = {\n issueId,\n startedAt: new Date().toISOString(),\n outcome: 'in_progress',\n skills,\n };\n\n cv.recentWork.unshift(entry);\n cv.stats.totalIssues++;\n cv.lastActive = new Date().toISOString();\n\n // Track skills\n if (skills) {\n for (const skill of skills) {\n if (!cv.skillsUsed.includes(skill)) {\n cv.skillsUsed.push(skill);\n }\n }\n }\n\n // Keep only last 50 entries\n if (cv.recentWork.length > 50) {\n cv.recentWork = cv.recentWork.slice(0, 50);\n }\n\n saveAgentCV(cv);\n}\n\n/**\n * Complete work for an agent\n */\nexport function completeWork(\n agentId: string,\n issueId: string,\n outcome: 'success' | 'failed' | 'abandoned',\n details?: { commits?: number; linesChanged?: number; failureReason?: string }\n): void {\n const cv = getAgentCV(agentId);\n\n // Find the work entry\n const entry = cv.recentWork.find(\n (w) => w.issueId === issueId && w.outcome === 'in_progress'\n );\n\n if (entry) {\n entry.outcome = outcome;\n entry.completedAt = new Date().toISOString();\n entry.duration = Math.round(\n (new Date().getTime() - new Date(entry.startedAt).getTime()) / (1000 * 60)\n );\n if (details?.commits) entry.commits = details.commits;\n if (details?.linesChanged) entry.linesChanged = details.linesChanged;\n if (details?.failureReason) entry.failureReason = details.failureReason;\n }\n\n // Update stats\n if (outcome === 'success') {\n cv.stats.successCount++;\n } else if (outcome === 'failed') {\n cv.stats.failureCount++;\n } else if (outcome === 'abandoned') {\n cv.stats.abandonedCount++;\n }\n\n // Calculate success rate\n const completed = cv.stats.successCount + cv.stats.failureCount + cv.stats.abandonedCount;\n cv.stats.successRate = completed > 0 ? cv.stats.successCount / completed : 0;\n\n // Calculate average duration (only from completed work)\n const completedEntries = cv.recentWork.filter(\n (w) => w.duration !== undefined && w.outcome !== 'in_progress'\n );\n if (completedEntries.length > 0) {\n const totalDuration = completedEntries.reduce((sum, w) => sum + (w.duration || 0), 0);\n cv.stats.avgDuration = Math.round(totalDuration / completedEntries.length);\n }\n\n cv.lastActive = new Date().toISOString();\n saveAgentCV(cv);\n}\n\n/**\n * Get agent rankings by success rate\n */\nexport function getAgentRankings(): Array<{\n agentId: string;\n successRate: number;\n totalIssues: number;\n avgDuration: number;\n}> {\n const rankings: Array<{\n agentId: string;\n successRate: number;\n totalIssues: number;\n avgDuration: number;\n }> = [];\n\n if (!existsSync(AGENTS_DIR)) return rankings;\n\n const dirs = readdirSync(AGENTS_DIR, { withFileTypes: true }).filter(\n (d) => d.isDirectory()\n );\n\n for (const dir of dirs) {\n const cv = getAgentCV(dir.name);\n if (cv.stats.totalIssues > 0) {\n rankings.push({\n agentId: dir.name,\n successRate: cv.stats.successRate,\n totalIssues: cv.stats.totalIssues,\n avgDuration: cv.stats.avgDuration,\n });\n }\n }\n\n // Sort by success rate, then by total issues\n rankings.sort((a, b) => {\n if (b.successRate !== a.successRate) {\n return b.successRate - a.successRate;\n }\n return b.totalIssues - a.totalIssues;\n });\n\n return rankings;\n}\n\n/**\n * Format CV for display\n */\nexport function formatCV(cv: AgentCV): string {\n const lines: string[] = [\n `# Agent CV: ${cv.agentId}`,\n '',\n `Runtime: ${cv.runtime} (${cv.model})`,\n `Created: ${cv.createdAt}`,\n `Last Active: ${cv.lastActive}`,\n '',\n '## Statistics',\n '',\n `- Total Issues: ${cv.stats.totalIssues}`,\n `- Success Rate: ${(cv.stats.successRate * 100).toFixed(1)}%`,\n `- Successes: ${cv.stats.successCount}`,\n `- Failures: ${cv.stats.failureCount}`,\n `- Abandoned: ${cv.stats.abandonedCount}`,\n `- Avg Duration: ${cv.stats.avgDuration} minutes`,\n '',\n ];\n\n if (cv.skillsUsed.length > 0) {\n lines.push('## Skills Used');\n lines.push('');\n lines.push(cv.skillsUsed.join(', '));\n lines.push('');\n }\n\n if (cv.recentWork.length > 0) {\n lines.push('## Recent Work');\n lines.push('');\n\n for (const work of cv.recentWork.slice(0, 10)) {\n const statusIcon = {\n success: '✓',\n failed: '✗',\n abandoned: '⊘',\n in_progress: '●',\n }[work.outcome];\n\n const duration = work.duration ? ` (${work.duration}m)` : '';\n lines.push(`${statusIcon} ${work.issueId}${duration}`);\n\n if (work.failureReason) {\n lines.push(` Reason: ${work.failureReason}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { AGENTS_DIR } from './paths.js';\nimport { createSession, killSession, sendKeys, sessionExists, getAgentSessions } from './tmux.js';\nimport { initHook, checkHook, generateGUPPPrompt } from './hooks.js';\nimport { startWork, completeWork, getAgentCV } from './cv.js';\nimport type { ComplexityLevel } from './cloister/complexity.js';\n\nexport interface AgentState {\n id: string;\n issueId: string;\n workspace: string;\n runtime: string;\n model: string;\n status: 'starting' | 'running' | 'stopped' | 'error';\n startedAt: string;\n lastActivity?: string;\n\n // Model routing & handoffs (Phase 4)\n complexity?: ComplexityLevel;\n handoffCount?: number;\n costSoFar?: number;\n sessionId?: string; // For resuming sessions after handoff\n}\n\nexport function getAgentDir(agentId: string): string {\n return join(AGENTS_DIR, agentId);\n}\n\nexport function getAgentState(agentId: string): AgentState | null {\n const stateFile = join(getAgentDir(agentId), 'state.json');\n if (!existsSync(stateFile)) return null;\n\n const content = readFileSync(stateFile, 'utf8');\n return JSON.parse(content);\n}\n\nexport function saveAgentState(state: AgentState): void {\n const dir = getAgentDir(state.id);\n mkdirSync(dir, { recursive: true });\n\n writeFileSync(\n join(dir, 'state.json'),\n JSON.stringify(state, null, 2)\n );\n}\n\nexport interface SpawnOptions {\n issueId: string;\n workspace: string;\n runtime?: string;\n model?: string;\n prompt?: string;\n}\n\nexport function spawnAgent(options: SpawnOptions): AgentState {\n const agentId = `agent-${options.issueId.toLowerCase()}`;\n\n // Check if already running\n if (sessionExists(agentId)) {\n throw new Error(`Agent ${agentId} already running. Use 'pan work tell' to message it.`);\n }\n\n // Initialize hook for this agent (GUPP support)\n initHook(agentId);\n\n // Create state\n const state: AgentState = {\n id: agentId,\n issueId: options.issueId,\n workspace: options.workspace,\n runtime: options.runtime || 'claude',\n model: options.model || 'sonnet',\n status: 'starting',\n startedAt: new Date().toISOString(),\n // Initialize Phase 4 fields\n handoffCount: 0,\n costSoFar: 0,\n };\n\n saveAgentState(state);\n\n // Build prompt with GUPP work if available\n let prompt = options.prompt || '';\n\n // GUPP: Check for pending work on hook\n const { hasWork, items } = checkHook(agentId);\n if (hasWork) {\n const guppPrompt = generateGUPPPrompt(agentId);\n if (guppPrompt) {\n prompt = guppPrompt + '\\n\\n---\\n\\n' + prompt;\n }\n }\n\n // Write prompt to file for complex prompts (avoids shell escaping issues)\n const promptFile = join(getAgentDir(agentId), 'initial-prompt.md');\n if (prompt) {\n writeFileSync(promptFile, prompt);\n }\n\n // Auto-setup hooks if not configured\n checkAndSetupHooks();\n\n // Write initial task cache for heartbeat hook\n writeTaskCache(agentId, options.issueId);\n\n // Create tmux session and start claude\n const claudeCmd = `claude --dangerously-skip-permissions --model ${state.model}`;\n createSession(agentId, options.workspace, claudeCmd, {\n env: {\n PANOPTICON_AGENT_ID: agentId\n }\n });\n\n // If there's a prompt, load it via tmux buffer after claude starts\n if (prompt) {\n // Wait for claude to be ready by checking for the prompt character\n // Claude shows \"❯\" when ready for input\n let ready = false;\n for (let i = 0; i < 15; i++) { // Max 15 seconds\n execSync('sleep 1');\n try {\n const pane = execSync(`tmux capture-pane -t ${agentId} -p`, { encoding: 'utf-8' });\n if (pane.includes('❯') || pane.includes('>')) {\n ready = true;\n break;\n }\n } catch {}\n }\n\n if (ready) {\n // Use tmux load-buffer and paste-buffer to send the prompt\n // This avoids all shell escaping issues\n execSync(`tmux load-buffer \"${promptFile}\"`);\n execSync(`tmux paste-buffer -t ${agentId}`);\n // Small delay to let paste complete, then send Enter\n execSync('sleep 0.5');\n execSync(`tmux send-keys -t ${agentId} Enter`);\n } else {\n console.error('Claude did not become ready in time, prompt not sent');\n }\n }\n\n // Update status\n state.status = 'running';\n saveAgentState(state);\n\n // Track work in CV\n startWork(agentId, options.issueId);\n\n return state;\n}\n\nexport function listRunningAgents(): (AgentState & { tmuxActive: boolean })[] {\n const tmuxSessions = getAgentSessions();\n const tmuxNames = new Set(tmuxSessions.map(s => s.name));\n\n const agents: (AgentState & { tmuxActive: boolean })[] = [];\n\n // Read all agent states\n if (!existsSync(AGENTS_DIR)) return agents;\n\n const dirs = readdirSync(AGENTS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n for (const dir of dirs) {\n const state = getAgentState(dir.name);\n if (state) {\n agents.push({\n ...state,\n tmuxActive: tmuxNames.has(state.id),\n });\n }\n }\n\n return agents;\n}\n\nexport function stopAgent(agentId: string): void {\n // Normalize agent ID\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n\n if (sessionExists(normalizedId)) {\n killSession(normalizedId);\n }\n\n const state = getAgentState(normalizedId);\n if (state) {\n state.status = 'stopped';\n saveAgentState(state);\n }\n}\n\nexport function messageAgent(agentId: string, message: string): void {\n // Normalize agent ID\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n\n if (!sessionExists(normalizedId)) {\n throw new Error(`Agent ${normalizedId} not running`);\n }\n\n sendKeys(normalizedId, message);\n\n // Also save to mail queue\n const mailDir = join(getAgentDir(normalizedId), 'mail');\n mkdirSync(mailDir, { recursive: true });\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n writeFileSync(\n join(mailDir, `${timestamp}.md`),\n `# Message\\n\\n${message}\\n`\n );\n}\n\n/**\n * Detect crashed agents (state shows running but tmux session is gone)\n */\nexport function detectCrashedAgents(): AgentState[] {\n const agents = listRunningAgents();\n return agents.filter(\n (agent) => agent.status === 'running' && !agent.tmuxActive\n );\n}\n\n/**\n * Recover a crashed agent by restarting it with context\n */\nexport function recoverAgent(agentId: string): AgentState | null {\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n const state = getAgentState(normalizedId);\n\n if (!state) {\n return null;\n }\n\n // Check if already running\n if (sessionExists(normalizedId)) {\n return state;\n }\n\n // Update crash count in health file\n const healthFile = join(getAgentDir(normalizedId), 'health.json');\n let health = { consecutiveFailures: 0, killCount: 0, recoveryCount: 0 };\n if (existsSync(healthFile)) {\n try {\n health = { ...health, ...JSON.parse(readFileSync(healthFile, 'utf-8')) };\n } catch {}\n }\n health.recoveryCount = (health.recoveryCount || 0) + 1;\n writeFileSync(healthFile, JSON.stringify(health, null, 2));\n\n // Build recovery prompt\n const recoveryPrompt = generateRecoveryPrompt(state);\n\n // Restart the agent with recovery context (YOLO mode - skip permissions)\n const claudeCmd = `claude --dangerously-skip-permissions --model ${state.model} \"${recoveryPrompt.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n')}\"`;\n createSession(normalizedId, state.workspace, claudeCmd);\n\n // Update state\n state.status = 'running';\n state.lastActivity = new Date().toISOString();\n saveAgentState(state);\n\n return state;\n}\n\n/**\n * Generate a recovery prompt for a crashed agent\n */\nfunction generateRecoveryPrompt(state: AgentState): string {\n const lines: string[] = [\n '# Agent Recovery',\n '',\n '⚠️ This agent session was recovered after a crash.',\n '',\n '## Previous Context',\n `- Issue: ${state.issueId}`,\n `- Workspace: ${state.workspace}`,\n `- Started: ${state.startedAt}`,\n '',\n '## Recovery Steps',\n '1. Check beads for context: `bd show ' + state.issueId + '`',\n '2. Review recent git commits: `git log --oneline -10`',\n '3. Check hook for pending work: `pan work hook check`',\n '4. Resume from last known state',\n '',\n '## GUPP Reminder',\n '> \"If there is work on your Hook, YOU MUST RUN IT.\"',\n '',\n ];\n\n // Add GUPP work if available\n const { hasWork } = checkHook(state.id);\n if (hasWork) {\n const guppPrompt = generateGUPPPrompt(state.id);\n if (guppPrompt) {\n lines.push('---');\n lines.push('');\n lines.push(guppPrompt);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Auto-recover all crashed agents\n */\nexport function autoRecoverAgents(): { recovered: string[]; failed: string[] } {\n const crashed = detectCrashedAgents();\n const recovered: string[] = [];\n const failed: string[] = [];\n\n for (const agent of crashed) {\n try {\n const result = recoverAgent(agent.id);\n if (result) {\n recovered.push(agent.id);\n } else {\n failed.push(agent.id);\n }\n } catch (error) {\n failed.push(agent.id);\n }\n }\n\n return { recovered, failed };\n}\n\n/**\n * Check if Panopticon hooks are configured, and auto-setup if not\n */\nfunction checkAndSetupHooks(): void {\n const { homedir } = require('os');\n const settingsPath = join(homedir(), '.claude', 'settings.json');\n const hookPath = join(homedir(), '.panopticon', 'bin', 'heartbeat-hook');\n\n // Check if settings.json exists and has heartbeat hook configured\n if (existsSync(settingsPath)) {\n try {\n const settingsContent = readFileSync(settingsPath, 'utf-8');\n const settings = JSON.parse(settingsContent);\n const postToolUse = settings?.hooks?.PostToolUse || [];\n\n const hookConfigured = postToolUse.some((hookConfig: any) =>\n hookConfig.hooks?.some((hook: any) =>\n hook.command === hookPath ||\n hook.command?.includes('panopticon') ||\n hook.command?.includes('heartbeat-hook')\n )\n );\n\n if (hookConfigured) {\n return; // Already configured\n }\n } catch {\n // Ignore errors, will attempt setup\n }\n }\n\n // Hooks not configured - run setup silently\n try {\n console.log('Configuring Panopticon heartbeat hooks...');\n execSync('pan setup hooks', { stdio: 'pipe' });\n console.log('✓ Heartbeat hooks configured');\n } catch (error) {\n console.warn('⚠ Failed to auto-configure hooks. Run `pan setup hooks` manually.');\n }\n}\n\n/**\n * Write task cache for heartbeat hook to use\n */\nfunction writeTaskCache(agentId: string, issueId: string): void {\n const cacheDir = join(getAgentDir(agentId));\n mkdirSync(cacheDir, { recursive: true });\n\n const cacheFile = join(cacheDir, 'current-task.json');\n writeFileSync(\n cacheFile,\n JSON.stringify({\n id: issueId,\n title: `Working on ${issueId}`,\n updated_at: new Date().toISOString()\n }, null, 2)\n );\n}\n","{\n \"name\": \"panopticon-cli\",\n \"version\": \"0.3.2\",\n \"description\": \"Multi-agent orchestration for AI coding assistants (Claude Code, Codex, Cursor, Gemini CLI)\",\n \"keywords\": [\n \"ai-agents\",\n \"orchestration\",\n \"claude-code\",\n \"codex\",\n \"cursor\",\n \"gemini\",\n \"multi-agent\",\n \"devtools\",\n \"linear\"\n ],\n \"author\": \"Edward Becker <edward.becker@mindyournow.com>\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/eltmon/panopticon-cli.git\"\n },\n \"homepage\": \"https://github.com/eltmon/panopticon-cli#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/eltmon/panopticon-cli/issues\"\n },\n \"type\": \"module\",\n \"bin\": {\n \"pan\": \"./dist/cli/index.js\",\n \"panopticon\": \"./dist/cli/index.js\"\n },\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"templates\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"scripts\": {\n \"dev\": \"tsx watch src/cli/index.ts\",\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"eslint src/\",\n \"test\": \"vitest --no-file-parallelism\",\n \"test:unit\": \"vitest run tests/unit\",\n \"test:integration\": \"vitest run tests/integration\",\n \"test:e2e\": \"vitest run tests/e2e\",\n \"test:coverage\": \"vitest run --coverage\",\n \"docs\": \"typedoc\",\n \"docs:watch\": \"typedoc --watch\",\n \"prepublishOnly\": \"npm run build\",\n \"postinstall\": \"node scripts/postinstall.mjs || true\"\n },\n \"dependencies\": {\n \"@iarna/toml\": \"^2.2.5\",\n \"@linear/sdk\": \"^70.0.0\",\n \"@octokit/rest\": \"^22.0.1\",\n \"better-sqlite3\": \"^12.6.2\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^12.1.0\",\n \"conf\": \"^12.0.0\",\n \"execa\": \"^8.0.1\",\n \"inquirer\": \"^9.3.8\",\n \"ora\": \"^8.2.0\",\n \"rally\": \"^2.1.3\",\n \"yaml\": \"^2.8.2\"\n },\n \"devDependencies\": {\n \"@types/better-sqlite3\": \"^7.6.13\",\n \"@types/inquirer\": \"^9.0.9\",\n \"@types/node\": \"^20.10.0\",\n \"@vitest/coverage-v8\": \"^1.0.4\",\n \"eslint\": \"^8.55.0\",\n \"tsup\": \"^8.0.1\",\n \"tsx\": \"^4.6.2\",\n \"typedoc\": \"^0.25.0\",\n \"typescript\": \"^5.3.2\",\n \"vitest\": \"^1.0.4\"\n }\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { initCommand } from './commands/init.js';\nimport { syncCommand } from './commands/sync.js';\nimport { restoreCommand } from './commands/restore.js';\nimport { backupListCommand, backupCleanCommand } from './commands/backup.js';\nimport { skillsCommand } from './commands/skills.js';\nimport { registerWorkCommands, statusCommand } from './commands/work/index.js';\nimport { registerWorkspaceCommands } from './commands/workspace.js';\nimport { registerInstallCommand } from './commands/install.js';\nimport { registerCloisterCommands } from './commands/cloister/index.js';\nimport { registerSetupCommands } from './commands/setup/index.js';\nimport { projectAddCommand, projectListCommand, projectRemoveCommand, projectInitCommand, projectShowCommand } from './commands/project.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { updateCommand } from './commands/update.js';\n\nconst program = new Command();\n\nprogram\n .name('pan')\n .description('Multi-agent orchestration for AI coding assistants')\n .version('0.1.3');\n\nprogram\n .command('init')\n .description('Initialize Panopticon (~/.panopticon/)')\n .action(initCommand);\n\nprogram\n .command('sync')\n .description('Sync skills/commands to AI tools')\n .option('--dry-run', 'Show what would be synced')\n .option('--force', 'Overwrite without prompts')\n .option('--backup-only', 'Only create backup')\n .action(syncCommand);\n\nprogram\n .command('restore [timestamp]')\n .description('Restore from backup')\n .action(restoreCommand);\n\n// Backup management\nconst backup = program.command('backup').description('Manage backups');\n\nbackup\n .command('list')\n .description('List all backups')\n .option('--json', 'Output as JSON')\n .action(backupListCommand);\n\nbackup\n .command('clean')\n .description('Remove old backups')\n .option('--keep <count>', 'Number of backups to keep', '10')\n .action(backupCleanCommand);\n\nprogram\n .command('skills')\n .description('List and manage skills')\n .option('--json', 'Output as JSON')\n .action(skillsCommand);\n\n// Register work commands (pan work issue, pan work status, etc.)\nregisterWorkCommands(program);\n\n// Register workspace commands (pan workspace create, pan workspace list, etc.)\nregisterWorkspaceCommands(program);\n\n// Register cloister commands (pan cloister status, pan cloister start, etc.)\nregisterCloisterCommands(program);\n\n// Register setup commands (pan setup hooks, etc.)\nregisterSetupCommands(program);\n\n// Register install command\nregisterInstallCommand(program);\n\n// Shorthand: pan status = pan work status\nprogram\n .command('status')\n .description('Show running agents (shorthand for work status)')\n .option('--json', 'Output as JSON')\n .action(statusCommand);\n\n// Dashboard commands\nprogram\n .command('up')\n .description('Start dashboard (and Traefik if enabled)')\n .option('--detach', 'Run in background')\n .option('--skip-traefik', 'Skip Traefik startup')\n .action(async (options) => {\n const { spawn, execSync } = await import('child_process');\n const { join, dirname } = await import('path');\n const { fileURLToPath } = await import('url');\n const { readFileSync, existsSync } = await import('fs');\n const { parse } = await import('@iarna/toml');\n\n // Find dashboard directory relative to CLI\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const dashboardDir = join(__dirname, '..', 'dashboard');\n\n // Check if Traefik is enabled\n const configFile = join(process.env.HOME || '', '.panopticon', 'config.toml');\n let traefikEnabled = false;\n let traefikDomain = 'pan.localhost';\n\n if (existsSync(configFile)) {\n try {\n const configContent = readFileSync(configFile, 'utf-8');\n const config = parse(configContent) as any;\n traefikEnabled = config.traefik?.enabled === true;\n traefikDomain = config.traefik?.domain || 'pan.localhost';\n } catch (error) {\n console.log(chalk.yellow('Warning: Could not read config.toml'));\n }\n }\n\n console.log(chalk.bold('Starting Panopticon...\\n'));\n\n // Start Traefik if enabled\n if (traefikEnabled && !options.skipTraefik) {\n const traefikDir = join(process.env.HOME || '', '.panopticon', 'traefik');\n if (existsSync(traefikDir)) {\n try {\n console.log(chalk.dim('Starting Traefik...'));\n execSync('docker-compose up -d', {\n cwd: traefikDir,\n stdio: 'pipe',\n });\n console.log(chalk.green('✓ Traefik started'));\n console.log(chalk.dim(` Dashboard: https://traefik.${traefikDomain}:8080\\n`));\n } catch (error) {\n console.log(chalk.yellow('⚠ Failed to start Traefik (continuing anyway)'));\n console.log(chalk.dim(' Run with --skip-traefik to suppress this message\\n'));\n }\n }\n }\n\n // Start dashboard\n console.log(chalk.dim('Starting dashboard...'));\n\n if (options.detach) {\n // Run in background\n const child = spawn('npm', ['run', 'dev'], {\n cwd: dashboardDir,\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n console.log(chalk.green('✓ Dashboard started in background'));\n if (traefikEnabled) {\n console.log(` Frontend: ${chalk.cyan(`https://${traefikDomain}`)}`);\n console.log(` API: ${chalk.cyan(`https://${traefikDomain}/api`)}`);\n } else {\n console.log(` Frontend: ${chalk.cyan('http://localhost:3001')}`);\n console.log(` API: ${chalk.cyan('http://localhost:3002')}`);\n }\n } else {\n // Run in foreground\n if (traefikEnabled) {\n console.log(` Frontend: ${chalk.cyan(`https://${traefikDomain}`)}`);\n console.log(` API: ${chalk.cyan(`https://${traefikDomain}/api`)}`);\n } else {\n console.log(` Frontend: ${chalk.cyan('http://localhost:3001')}`);\n console.log(` API: ${chalk.cyan('http://localhost:3002')}`);\n }\n console.log(chalk.dim('\\nPress Ctrl+C to stop\\n'));\n\n const child = spawn('npm', ['run', 'dev'], {\n cwd: dashboardDir,\n stdio: 'inherit',\n });\n\n child.on('error', (err) => {\n console.error(chalk.red('Failed to start dashboard:'), err.message);\n process.exit(1);\n });\n }\n });\n\nprogram\n .command('down')\n .description('Stop dashboard (and Traefik if enabled)')\n .option('--skip-traefik', 'Skip Traefik shutdown')\n .action(async (options) => {\n const { execSync } = await import('child_process');\n const { join } = await import('path');\n const { readFileSync, existsSync } = await import('fs');\n const { parse } = await import('@iarna/toml');\n\n console.log(chalk.bold('Stopping Panopticon...\\n'));\n\n // Stop dashboard\n console.log(chalk.dim('Stopping dashboard...'));\n try {\n // Kill processes on dashboard ports\n execSync('lsof -ti:3001 | xargs kill -9 2>/dev/null || true', { stdio: 'pipe' });\n execSync('lsof -ti:3002 | xargs kill -9 2>/dev/null || true', { stdio: 'pipe' });\n console.log(chalk.green('✓ Dashboard stopped'));\n } catch {\n console.log(chalk.dim(' No dashboard processes found'));\n }\n\n // Check if Traefik is enabled\n const configFile = join(process.env.HOME || '', '.panopticon', 'config.toml');\n let traefikEnabled = false;\n\n if (existsSync(configFile)) {\n try {\n const configContent = readFileSync(configFile, 'utf-8');\n const config = parse(configContent) as any;\n traefikEnabled = config.traefik?.enabled === true;\n } catch (error) {\n // Ignore config read errors\n }\n }\n\n // Stop Traefik if enabled\n if (traefikEnabled && !options.skipTraefik) {\n const traefikDir = join(process.env.HOME || '', '.panopticon', 'traefik');\n if (existsSync(traefikDir)) {\n console.log(chalk.dim('Stopping Traefik...'));\n try {\n execSync('docker-compose down', {\n cwd: traefikDir,\n stdio: 'pipe',\n });\n console.log(chalk.green('✓ Traefik stopped'));\n } catch (error) {\n console.log(chalk.yellow('⚠ Failed to stop Traefik'));\n }\n }\n }\n\n console.log('');\n });\n\n// Project management commands\nconst project = program.command('project').description('Project registry for multi-project workspace support');\n\nproject\n .command('add <path>')\n .description('Register a project with Panopticon')\n .option('--name <name>', 'Project name')\n .option('--type <type>', 'Project type (standalone/monorepo)', 'standalone')\n .option('--linear-team <team>', 'Linear team prefix (e.g., MIN, PAN)')\n .action(projectAddCommand);\n\nproject\n .command('list')\n .description('List all registered projects')\n .option('--json', 'Output as JSON')\n .action(projectListCommand);\n\nproject\n .command('show <key>')\n .description('Show details for a specific project')\n .action(projectShowCommand);\n\nproject\n .command('remove <nameOrPath>')\n .description('Remove a project from the registry')\n .action(projectRemoveCommand);\n\nproject\n .command('init')\n .description('Initialize projects.yaml with example configuration')\n .action(projectInitCommand);\n\n// Doctor command\nprogram\n .command('doctor')\n .description('Check system health and dependencies')\n .action(doctorCommand);\n\n// Update command\nprogram\n .command('update')\n .description('Update Panopticon to latest version')\n .option('--check', 'Only check for updates, don\\'t install')\n .option('--force', 'Force update even if on latest')\n .action(updateCommand);\n\n// Parse and execute\nprogram.parse();\n","import { existsSync, mkdirSync, readdirSync, cpSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { INIT_DIRS, CONFIG_FILE, PANOPTICON_HOME, SKILLS_DIR, AGENTS_DIR } from '../../lib/paths.js';\nimport { getDefaultConfig, saveConfig } from '../../lib/config.js';\nimport { detectShell, getShellRcFile, addAlias, getAliasInstructions } from '../../lib/shell.js';\n\n// Get the package root directory (where skills/ and agents/ live)\n// Note: After bundling, code runs from dist/cli/index.js, so go up 2 levels\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst PACKAGE_ROOT = join(__dirname, '..', '..'); // dist/cli -> dist -> package root\nconst BUNDLED_SKILLS_DIR = join(PACKAGE_ROOT, 'skills');\nconst BUNDLED_AGENTS_DIR = join(PACKAGE_ROOT, 'agents');\n\n/**\n * Copy bundled skills from package to ~/.panopticon/skills/\n * Returns the number of skills copied\n */\nfunction copyBundledSkills(): number {\n if (!existsSync(BUNDLED_SKILLS_DIR)) {\n return 0;\n }\n\n // Ensure skills directory exists\n if (!existsSync(SKILLS_DIR)) {\n mkdirSync(SKILLS_DIR, { recursive: true });\n }\n\n const skills = readdirSync(BUNDLED_SKILLS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n let copied = 0;\n for (const skill of skills) {\n const sourcePath = join(BUNDLED_SKILLS_DIR, skill.name);\n const targetPath = join(SKILLS_DIR, skill.name);\n\n // Copy skill directory (overwrites existing)\n cpSync(sourcePath, targetPath, { recursive: true });\n copied++;\n }\n\n return copied;\n}\n\n/**\n * Copy bundled agents from package to ~/.panopticon/agents/\n * Returns the number of agents copied\n */\nfunction copyBundledAgents(): number {\n if (!existsSync(BUNDLED_AGENTS_DIR)) {\n return 0;\n }\n\n // Ensure agents directory exists\n if (!existsSync(AGENTS_DIR)) {\n mkdirSync(AGENTS_DIR, { recursive: true });\n }\n\n const agents = readdirSync(BUNDLED_AGENTS_DIR, { withFileTypes: true })\n .filter(entry => entry.isFile() && entry.name.endsWith('.md'));\n\n let copied = 0;\n for (const agent of agents) {\n const sourcePath = join(BUNDLED_AGENTS_DIR, agent.name);\n const targetPath = join(AGENTS_DIR, agent.name);\n\n // Copy agent file (overwrites existing)\n cpSync(sourcePath, targetPath);\n copied++;\n }\n\n return copied;\n}\n\nexport async function initCommand(): Promise<void> {\n const spinner = ora('Initializing Panopticon...').start();\n\n // Check if already initialized\n if (existsSync(CONFIG_FILE)) {\n spinner.info('Panopticon already initialized');\n console.log(chalk.dim(` Config: ${CONFIG_FILE}`));\n console.log(chalk.dim(` Home: ${PANOPTICON_HOME}`));\n console.log(chalk.dim(' Run `pan sync` to update skills'));\n return;\n }\n\n try {\n // Create all directories\n for (const dir of INIT_DIRS) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n spinner.text = 'Created directories...';\n\n // Write default config\n const config = getDefaultConfig();\n saveConfig(config);\n spinner.text = 'Created config...';\n\n // Copy bundled skills from package\n spinner.text = 'Installing bundled skills...';\n const skillsCopied = copyBundledSkills();\n\n // Copy bundled agents from package\n spinner.text = 'Installing bundled agents...';\n const agentsCopied = copyBundledAgents();\n\n // Detect shell and add alias\n const shell = detectShell();\n const rcFile = getShellRcFile(shell);\n\n if (rcFile && existsSync(rcFile)) {\n addAlias(rcFile);\n spinner.succeed('Panopticon initialized!');\n console.log('');\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(PANOPTICON_HOME));\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(CONFIG_FILE));\n if (skillsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${skillsCopied} bundled skills`);\n }\n if (agentsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${agentsCopied} bundled agents`);\n }\n console.log(chalk.green('✓') + ' ' + getAliasInstructions(shell));\n } else {\n spinner.succeed('Panopticon initialized!');\n console.log('');\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(PANOPTICON_HOME));\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(CONFIG_FILE));\n if (skillsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${skillsCopied} bundled skills`);\n }\n if (agentsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${agentsCopied} bundled agents`);\n }\n console.log(chalk.yellow('!') + ' Could not detect shell. Add alias manually:');\n console.log(chalk.dim(' alias pan=\"panopticon\"'));\n }\n\n console.log('');\n console.log('Next steps:');\n console.log(chalk.dim(' 1. Run: pan sync'));\n console.log(chalk.dim(' 2. Start dashboard: pan up'));\n\n } catch (error: any) {\n spinner.fail('Failed to initialize');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { loadConfig } from '../../lib/config.js';\nimport { createBackup } from '../../lib/backup.js';\nimport { planSync, executeSync, planHooksSync, syncHooks } from '../../lib/sync.js';\nimport { SYNC_TARGETS, Runtime } from '../../lib/paths.js';\n\ninterface SyncOptions {\n dryRun?: boolean;\n force?: boolean;\n backupOnly?: boolean;\n}\n\nexport async function syncCommand(options: SyncOptions): Promise<void> {\n const config = loadConfig();\n const targets = config.sync?.targets;\n\n // Defensive check: ensure targets is defined and is a valid array\n if (!targets || !Array.isArray(targets) || targets.length === 0) {\n console.log(chalk.yellow('No sync targets configured.'));\n console.log(chalk.dim('Edit ~/.panopticon/config.toml to add targets to the [sync] section.'));\n console.log(chalk.dim('Example: targets = [\"claude-code\", \"cursor\"]'));\n return;\n }\n\n // Type assertion is now safe since we've validated the array\n const validTargets = targets as Runtime[];\n\n // Dry run mode\n if (options.dryRun) {\n console.log(chalk.bold('Sync Plan (dry run):\\n'));\n\n // Show hooks plan\n const hooksPlan = planHooksSync();\n if (hooksPlan.length > 0) {\n console.log(chalk.cyan('hooks (bin scripts):'));\n for (const hook of hooksPlan) {\n const icon = hook.status === 'new' ? chalk.green('+') : chalk.blue('↻');\n const status = hook.status === 'new' ? '' : chalk.dim('[update]');\n console.log(` ${icon} ${hook.name} ${status}`);\n }\n console.log('');\n }\n\n for (const runtime of validTargets) {\n const plan = planSync(runtime);\n\n console.log(chalk.cyan(`${runtime}:`));\n\n if (plan.skills.length === 0 && plan.commands.length === 0 && plan.agents.length === 0) {\n console.log(chalk.dim(' (nothing to sync)'));\n continue;\n }\n\n for (const item of plan.skills) {\n const icon = item.status === 'conflict' ? chalk.yellow('!') : chalk.green('+');\n const status = item.status === 'conflict' ? chalk.yellow('[conflict]') : '';\n console.log(` ${icon} skill/${item.name} ${status}`);\n }\n\n for (const item of plan.commands) {\n const icon = item.status === 'conflict' ? chalk.yellow('!') : chalk.green('+');\n const status = item.status === 'conflict' ? chalk.yellow('[conflict]') : '';\n console.log(` ${icon} command/${item.name} ${status}`);\n }\n\n for (const item of plan.agents) {\n const icon = item.status === 'conflict' ? chalk.yellow('!') : chalk.green('+');\n const status = item.status === 'conflict' ? chalk.yellow('[conflict]') : '';\n console.log(` ${icon} agent/${item.name} ${status}`);\n }\n\n console.log('');\n }\n\n console.log(chalk.dim('Run without --dry-run to apply changes.'));\n return;\n }\n\n // Create backup if enabled\n if (config.sync.backup_before_sync) {\n const spinner = ora('Creating backup...').start();\n\n const backupDirs = validTargets.flatMap((r) => [\n SYNC_TARGETS[r].skills,\n SYNC_TARGETS[r].commands,\n SYNC_TARGETS[r].agents,\n ]);\n\n const backup = createBackup(backupDirs);\n\n if (backup.targets.length > 0) {\n spinner.succeed(`Backup created: ${backup.timestamp}`);\n } else {\n spinner.info('No existing content to backup');\n }\n\n if (options.backupOnly) {\n return;\n }\n }\n\n // Execute sync\n const spinner = ora('Syncing...').start();\n\n let totalCreated = 0;\n let totalConflicts = 0;\n\n for (const runtime of validTargets) {\n spinner.text = `Syncing to ${runtime}...`;\n\n const result = executeSync(runtime, { force: options.force });\n\n totalCreated += result.created.length;\n totalConflicts += result.conflicts.length;\n\n if (result.conflicts.length > 0 && !options.force) {\n console.log('');\n console.log(chalk.yellow(`Conflicts in ${runtime}:`));\n for (const name of result.conflicts) {\n console.log(chalk.dim(` - ${name} (use --force to overwrite)`));\n }\n }\n }\n\n if (totalConflicts > 0 && !options.force) {\n spinner.warn(`Synced ${totalCreated} items, ${totalConflicts} conflicts`);\n console.log('');\n console.log(chalk.dim('Use --force to overwrite conflicting items.'));\n } else {\n spinner.succeed(`Synced ${totalCreated} items to ${validTargets.join(', ')}`);\n }\n\n // Sync hooks (bin scripts)\n const hooksSpinner = ora('Syncing hooks...').start();\n const hooksResult = syncHooks();\n\n if (hooksResult.errors.length > 0) {\n hooksSpinner.warn(`Synced ${hooksResult.synced.length} hooks, ${hooksResult.errors.length} errors`);\n for (const error of hooksResult.errors) {\n console.log(chalk.red(` ✗ ${error}`));\n }\n } else if (hooksResult.synced.length > 0) {\n hooksSpinner.succeed(`Synced ${hooksResult.synced.length} hooks to ~/.panopticon/bin/`);\n } else {\n hooksSpinner.info('No hooks to sync');\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport inquirer from 'inquirer';\nimport { listBackups, restoreBackup } from '../../lib/backup.js';\nimport { loadConfig } from '../../lib/config.js';\nimport { SYNC_TARGETS, Runtime } from '../../lib/paths.js';\n\nexport async function restoreCommand(timestamp?: string): Promise<void> {\n const backups = listBackups();\n\n if (backups.length === 0) {\n console.log(chalk.yellow('No backups found.'));\n return;\n }\n\n // If no timestamp provided, let user choose\n if (!timestamp) {\n console.log(chalk.bold('Available backups:\\n'));\n\n for (const backup of backups.slice(0, 10)) {\n console.log(` ${chalk.cyan(backup.timestamp)} - ${backup.targets.join(', ')}`);\n }\n\n if (backups.length > 10) {\n console.log(chalk.dim(` ... and ${backups.length - 10} more`));\n }\n\n console.log('');\n\n const { selected } = await inquirer.prompt([\n {\n type: 'list',\n name: 'selected',\n message: 'Select backup to restore:',\n choices: backups.slice(0, 10).map((b) => ({\n name: `${b.timestamp} (${b.targets.join(', ')})`,\n value: b.timestamp,\n })),\n },\n ]);\n\n timestamp = selected;\n }\n\n // Confirm restore\n const { confirm } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'confirm',\n message: `Restore backup ${timestamp}? This will overwrite current files.`,\n default: false,\n },\n ]);\n\n if (!confirm) {\n console.log(chalk.dim('Restore cancelled.'));\n return;\n }\n\n const spinner = ora('Restoring backup...').start();\n\n try {\n const config = loadConfig();\n const targets = config.sync.targets as Runtime[];\n\n // Build target dirs map\n const targetDirs: Record<string, string> = {};\n\n for (const runtime of targets) {\n targetDirs[`${runtime}-skills`] = SYNC_TARGETS[runtime].skills;\n targetDirs[`${runtime}-commands`] = SYNC_TARGETS[runtime].commands;\n // Also try simple names for backwards compatibility\n targetDirs['skills'] = SYNC_TARGETS[runtime].skills;\n targetDirs['commands'] = SYNC_TARGETS[runtime].commands;\n }\n\n restoreBackup(timestamp!, targetDirs);\n\n spinner.succeed(`Restored backup: ${timestamp}`);\n\n } catch (error: any) {\n spinner.fail('Failed to restore');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { listBackups, cleanOldBackups } from '../../lib/backup.js';\n\nexport async function backupListCommand(options: { json?: boolean }): Promise<void> {\n const backups = listBackups();\n\n if (options.json) {\n console.log(JSON.stringify(backups, null, 2));\n return;\n }\n\n if (backups.length === 0) {\n console.log(chalk.dim('No backups found.'));\n console.log(chalk.dim('Backups are created automatically during sync.'));\n return;\n }\n\n console.log(chalk.bold('Backups:\\n'));\n\n for (const backup of backups) {\n console.log(` ${chalk.cyan(backup.timestamp)}`);\n console.log(` ${chalk.dim('Contains:')} ${backup.targets.join(', ')}`);\n }\n\n console.log();\n console.log(chalk.dim(`Total: ${backups.length} backups`));\n console.log(chalk.dim('Use `pan restore <timestamp>` to restore a backup.'));\n}\n\nexport async function backupCleanCommand(options: { keep?: string }): Promise<void> {\n const keepCount = parseInt(options.keep || '10', 10);\n const removed = cleanOldBackups(keepCount);\n\n if (removed === 0) {\n console.log(chalk.dim(`No backups removed (keeping ${keepCount}).`));\n } else {\n console.log(chalk.green(`Removed ${removed} old backup(s), keeping ${keepCount}.`));\n }\n}\n","import { readdirSync, readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport { SKILLS_DIR } from '../../lib/paths.js';\n\nexport interface SkillMeta {\n name: string;\n description: string;\n path: string;\n}\n\nfunction parseSkillFrontmatter(content: string): { name?: string; description?: string } {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n\n const frontmatter = match[1];\n const name = frontmatter.match(/name:\\s*(.+)/)?.[1]?.trim();\n const description = frontmatter.match(/description:\\s*(.+)/)?.[1]?.trim();\n\n return { name, description };\n}\n\nexport function listSkills(): SkillMeta[] {\n if (!existsSync(SKILLS_DIR)) return [];\n\n const skills: SkillMeta[] = [];\n const dirs = readdirSync(SKILLS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n for (const dir of dirs) {\n const skillFile = join(SKILLS_DIR, dir.name, 'SKILL.md');\n if (!existsSync(skillFile)) continue;\n\n const content = readFileSync(skillFile, 'utf8');\n const { name, description } = parseSkillFrontmatter(content);\n\n skills.push({\n name: name || dir.name,\n description: description || '(no description)',\n path: skillFile,\n });\n }\n\n return skills.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport async function skillsCommand(options: { json?: boolean }): Promise<void> {\n const skills = listSkills();\n\n if (options.json) {\n console.log(JSON.stringify(skills, null, 2));\n return;\n }\n\n console.log(chalk.bold(`\\nPanopticon Skills (${skills.length})\\n`));\n\n if (skills.length === 0) {\n console.log(chalk.yellow('No skills found.'));\n console.log(chalk.dim('Skills should be in ~/.panopticon/skills/<name>/SKILL.md'));\n return;\n }\n\n for (const skill of skills) {\n console.log(chalk.cyan(skill.name));\n console.log(chalk.dim(` ${skill.description}`));\n }\n\n console.log(`\\n${chalk.dim('Run \"pan sync\" to sync skills to Claude Code')}`);\n}\n","import { Command } from 'commander';\nimport { issueCommand } from './issue.js';\nimport { statusCommand } from './status.js';\nimport { tellCommand } from './tell.js';\nimport { killCommand } from './kill.js';\nimport { pendingCommand } from './pending.js';\nimport { approveCommand } from './approve.js';\nimport { planCommand } from './plan.js';\nimport { listCommand } from './list.js';\nimport { triageCommand } from './triage.js';\nimport { hookCommand } from './hook.js';\nimport { recoverCommand } from './recover.js';\nimport { cvCommand } from './cv.js';\nimport { contextCommand } from './context.js';\nimport { healthCommand } from './health.js';\n\nexport function registerWorkCommands(program: Command): void {\n const work = program\n .command('work')\n .description('Agent and work management');\n\n work\n .command('issue <id>')\n .description('Spawn agent for Linear issue')\n .option('--model <model>', 'Claude model (sonnet/opus/haiku)', 'sonnet')\n .option('--runtime <runtime>', 'AI runtime (claude/codex)', 'claude')\n .option('--dry-run', 'Show what would be created')\n .action(issueCommand);\n\n work\n .command('status')\n .description('Show all running agents')\n .option('--json', 'Output as JSON')\n .action(statusCommand);\n\n work\n .command('tell <id> <message>')\n .description('Send message to running agent')\n .action(tellCommand);\n\n work\n .command('kill <id>')\n .description('Kill an agent')\n .option('--force', 'Kill without confirmation')\n .action(killCommand);\n\n work\n .command('pending')\n .description('Show completed work awaiting review')\n .action(pendingCommand);\n\n work\n .command('approve <id>')\n .description('Approve agent work, merge MR, update Linear')\n .option('--no-merge', 'Skip MR merge')\n .option('--no-linear', 'Skip Linear status update')\n .action(approveCommand);\n\n work\n .command('plan <id>')\n .description('Create execution plan before spawning')\n .option('-o, --output <path>', 'Output file path')\n .option('--json', 'Output as JSON')\n .option('--skip-discovery', 'Skip interactive discovery phase')\n .option('--force', 'Force planning even for simple issues')\n .action(planCommand);\n\n work\n .command('list')\n .description('List issues from configured trackers')\n .option('--all', 'Include closed issues')\n .option('--mine', 'Show only my assigned issues')\n .option('--json', 'Output as JSON')\n .option('--tracker <type>', 'Query specific tracker (linear/github/gitlab)')\n .option('--all-trackers', 'Query all configured trackers')\n .action(listCommand);\n\n work\n .command('triage [id]')\n .description('Triage secondary tracker issues')\n .option('--create', 'Create primary issue from secondary')\n .option('--dismiss <reason>', 'Dismiss from triage')\n .action(triageCommand);\n\n work\n .command('hook [action] [idOrMessage...]')\n .description('GUPP hooks: check, push, pop, clear, mail, gupp')\n .option('--json', 'Output as JSON')\n .action((action, idOrMessage, options) => {\n hookCommand(action || 'help', idOrMessage?.join(' '), options);\n });\n\n work\n .command('recover [id]')\n .description('Recover crashed agents')\n .option('--all', 'Auto-recover all crashed agents')\n .option('--json', 'Output as JSON')\n .action(recoverCommand);\n\n work\n .command('cv [agentId]')\n .description('View agent CVs (work history) and rankings')\n .option('--json', 'Output as JSON')\n .option('--rankings', 'Show agent rankings')\n .action(cvCommand);\n\n work\n .command('context [action] [arg1] [arg2]')\n .description('Context engineering: state, checkpoint, history, materialize')\n .option('--json', 'Output as JSON')\n .action((action, arg1, arg2, options) => {\n contextCommand(action || 'help', arg1, arg2, options);\n });\n\n work\n .command('health [action] [id]')\n .description('Health monitoring: check, status, ping, recover, daemon')\n .option('--json', 'Output as JSON')\n .option('--interval <seconds>', 'Daemon check interval', '30')\n .action((action, id, options) => {\n healthCommand(action || 'help', id, {\n json: options.json,\n interval: parseInt(options.interval, 10),\n });\n });\n}\n\n// Re-export individual commands for direct use\nexport { statusCommand } from './status.js';\nexport { issueCommand } from './issue.js';\nexport { tellCommand } from './tell.js';\nexport { killCommand } from './kill.js';\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { spawnAgent } from '../../../lib/agents.js';\nimport { resolveProjectFromIssue, hasProjects, listProjects } from '../../../lib/projects.js';\n\ninterface IssueOptions {\n model: string;\n runtime: string;\n dryRun?: boolean;\n}\n\n/**\n * Find the workspace directory for an issue.\n * First checks project registry for the correct project path,\n * then looks for workspaces/feature-{issue-id}/ in the project root.\n */\nfunction findWorkspace(issueId: string, labels: string[] = []): string | null {\n const normalizedId = issueId.toLowerCase();\n\n // First, try to resolve from project registry\n const resolved = resolveProjectFromIssue(issueId, labels);\n if (resolved) {\n const workspaceName = `feature-${normalizedId}`;\n const workspacePath = join(resolved.projectPath, 'workspaces', workspaceName);\n if (existsSync(workspacePath)) {\n return workspacePath;\n }\n // Also try without \"feature-\" prefix\n const altPath = join(resolved.projectPath, 'workspaces', normalizedId);\n if (existsSync(altPath)) {\n return altPath;\n }\n }\n\n // Fall back to searching upward from cwd (backward compatible)\n let dir = process.cwd();\n for (let i = 0; i < 10; i++) {\n const workspacesDir = join(dir, 'workspaces');\n if (existsSync(workspacesDir)) {\n // Look for feature-{issue-id} workspace\n const workspaceName = `feature-${normalizedId}`;\n const workspacePath = join(workspacesDir, workspaceName);\n if (existsSync(workspacePath)) {\n return workspacePath;\n }\n\n // Also try without \"feature-\" prefix\n const altPath = join(workspacesDir, normalizedId);\n if (existsSync(altPath)) {\n return altPath;\n }\n }\n\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\n/**\n * Find the project root (contains workspaces/, .git, or CLAUDE.md)\n * First checks project registry, then falls back to searching upward.\n */\nfunction findProjectRoot(issueId?: string, labels: string[] = []): string {\n // If we have an issue ID, try to resolve from registry first\n if (issueId) {\n const resolved = resolveProjectFromIssue(issueId, labels);\n if (resolved) {\n return resolved.projectPath;\n }\n }\n\n // Fall back to searching upward from cwd\n let dir = process.cwd();\n for (let i = 0; i < 10; i++) {\n if (existsSync(join(dir, 'workspaces')) ||\n existsSync(join(dir, '.git')) ||\n existsSync(join(dir, 'CLAUDE.md'))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return process.cwd();\n}\n\n/**\n * Read planning artifacts for an issue (STATE.md, etc.)\n */\nfunction readPlanningContext(workspacePath: string): string | null {\n const statePath = join(workspacePath, '.planning', 'STATE.md');\n if (existsSync(statePath)) {\n return readFileSync(statePath, 'utf-8');\n }\n return null;\n}\n\n/**\n * Extract beads IDs from STATE.md content\n * Looks for patterns like `panopticon-1dg` in backticks or tables\n */\nfunction extractBeadsIdsFromState(stateContent: string): string[] {\n const ids: string[] = [];\n\n // Match beads IDs in backticks (e.g., `panopticon-1dg`)\n const backtickMatches = stateContent.match(/`([a-z]+-[a-z0-9]+)`/g) || [];\n for (const match of backtickMatches) {\n const id = match.replace(/`/g, '');\n // Filter for valid beads IDs (project-xxx format)\n if (id.match(/^[a-z]+-[a-z0-9]{2,4}$/)) {\n ids.push(id);\n }\n }\n\n return [...new Set(ids)]; // Deduplicate\n}\n\n/**\n * Read beads tasks for an issue from both workspace and project root.\n * Uses STATE.md to find the associated beads IDs.\n */\nfunction readBeadsTasks(workspacePath: string, projectRoot: string, issueId: string): string[] {\n const tasks: string[] = [];\n const normalizedId = issueId.toLowerCase();\n\n // First, extract beads IDs from STATE.md\n const stateContent = readPlanningContext(workspacePath);\n const beadsIds = stateContent ? extractBeadsIdsFromState(stateContent) : [];\n\n // Check both locations for beads database\n const beadsPaths = [\n join(workspacePath, '.beads', 'issues.jsonl'),\n join(projectRoot, '.beads', 'issues.jsonl'),\n ];\n\n const seenIds = new Set<string>();\n\n for (const beadsPath of beadsPaths) {\n if (!existsSync(beadsPath)) continue;\n\n try {\n const content = readFileSync(beadsPath, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n\n for (const line of lines) {\n try {\n const task = JSON.parse(line);\n if (seenIds.has(task.id)) continue;\n\n // Match by:\n // 1. Task ID is in the STATE.md beads list\n // 2. Task is tagged with the issue ID\n // 3. Task title contains the issue ID\n const tags = task.tags || [];\n const isMatch =\n beadsIds.includes(task.id) ||\n tags.some((t: string) => t.toLowerCase().includes(normalizedId)) ||\n task.title?.toLowerCase().includes(normalizedId);\n\n if (isMatch) {\n seenIds.add(task.id);\n tasks.push(`- [${task.status || 'open'}] ${task.title} (${task.id})`);\n }\n } catch {}\n }\n } catch {}\n }\n\n return tasks;\n}\n\n/**\n * Build a comprehensive prompt with planning context\n */\nfunction buildAgentPrompt(issueId: string, workspacePath: string, projectRoot: string): string {\n const lines: string[] = [\n `# Working on Issue: ${issueId}`,\n '',\n `**Workspace:** ${workspacePath}`,\n '',\n ];\n\n // Check what context files exist\n const hasStateFile = existsSync(join(workspacePath, '.planning', 'STATE.md'));\n const hasClaudeMd = existsSync(join(workspacePath, 'CLAUDE.md'));\n const hasProjectClaudeMd = existsSync(join(projectRoot, 'CLAUDE.md'));\n\n // CRITICAL: Instruct agent to read context files FIRST\n lines.push('## IMPORTANT: Read Context Files First');\n lines.push('');\n lines.push('Before starting any work, you MUST read these files to understand the full context:');\n lines.push('');\n\n if (hasStateFile) {\n lines.push(`1. **Read \\`.planning/STATE.md\\`** - Contains the full planning context, decisions made, and current status for this issue.`);\n }\n if (hasClaudeMd) {\n lines.push(`2. **Read \\`CLAUDE.md\\`** (in workspace) - Contains workspace-specific instructions and warnings.`);\n }\n if (hasProjectClaudeMd && projectRoot !== workspacePath) {\n lines.push(`3. **Read \\`${projectRoot}/CLAUDE.md\\`** - Contains project-wide development guidelines.`);\n }\n\n lines.push('');\n lines.push('These files contain critical context that may have been updated since the last session.');\n lines.push('');\n\n // Add beads tasks summary\n const beadsTasks = readBeadsTasks(workspacePath, projectRoot, issueId);\n if (beadsTasks.length > 0) {\n lines.push('## Beads Tasks');\n lines.push('');\n lines.push('Tasks created during planning (check STATE.md for which are complete):');\n lines.push('');\n lines.push(beadsTasks.join('\\n'));\n lines.push('');\n lines.push('Use `bd show <task-id>` to see task details, `bd update <task-id> --status in_progress` to start work.');\n lines.push('');\n }\n\n lines.push('## Your Task');\n lines.push('');\n lines.push('1. Read the context files listed above');\n lines.push('2. Check STATE.md for current status and what work remains');\n lines.push('3. Continue implementing the planned work');\n lines.push('4. Mark beads tasks as complete as you finish them: `bd update <task-id> --status closed`');\n lines.push('');\n\n // CRITICAL: Instructions for maintaining state for crash recovery\n lines.push('## CRITICAL: Keep STATE.md Updated');\n lines.push('');\n lines.push('**You may be interrupted, crash, or be stopped at any time.** To ensure the next agent can continue:');\n lines.push('');\n lines.push('1. **Update `.planning/STATE.md` frequently** as you complete work');\n lines.push('2. After completing each task or significant milestone, update the \"Current Status\" section');\n lines.push('3. Document any decisions made or blockers encountered');\n lines.push('4. Keep the \"Remaining Work\" section accurate');\n lines.push('');\n lines.push('The next agent will read STATE.md to know exactly where to pick up. Beads tasks track individual items,');\n lines.push('but STATE.md provides the narrative context and current state that beads alone cannot capture.');\n lines.push('');\n\n // CRITICAL: Work completion requirements\n lines.push('## CRITICAL: Work Completion Requirements');\n lines.push('');\n lines.push('**You are NOT done until ALL of these are true:**');\n lines.push('');\n lines.push('1. **Tests pass** - Run the full test suite (`npm test` or equivalent)');\n lines.push('2. **All changes committed** - `git status` shows \"nothing to commit, working tree clean\"');\n lines.push('3. **Pushed to remote** - `git push -u origin $(git branch --show-current)`');\n lines.push('');\n lines.push('**Before declaring work complete, run:**');\n lines.push('```');\n lines.push('npm test # Run tests');\n lines.push('git add -A && git commit -m \"feat: description\" # Commit ALL changes');\n lines.push('git push -u origin $(git branch --show-current) # Push');\n lines.push('git status # Must show \"nothing to commit\"');\n lines.push('```');\n lines.push('');\n lines.push('**Uncommitted changes = NOT COMPLETE. Do not say you are done if `git status` shows changes.**');\n lines.push('');\n\n return lines.join('\\n');\n}\n\nexport async function issueCommand(id: string, options: IssueOptions): Promise<void> {\n const spinner = ora(`Preparing workspace for ${id}...`).start();\n\n try {\n // Normalize issue ID (MIN-648 -> min-648 for tmux session name)\n const normalizedId = id.toLowerCase();\n\n // Find workspace for this issue (using project registry first, then cwd fallback)\n const projectRoot = findProjectRoot(id);\n let workspace = findWorkspace(id);\n\n // Log project resolution info\n const resolved = resolveProjectFromIssue(id);\n if (resolved) {\n spinner.text = `Resolved project: ${resolved.projectName} (${resolved.projectPath})`;\n }\n\n if (!workspace) {\n spinner.warn(`No workspace found for ${id}, using project root`);\n workspace = projectRoot;\n } else {\n spinner.text = `Found workspace: ${workspace}`;\n }\n\n if (options.dryRun) {\n spinner.info('Dry run mode');\n console.log('');\n console.log(chalk.bold('Would create:'));\n console.log(` Agent ID: agent-${normalizedId}`);\n console.log(` Workspace: ${workspace}`);\n console.log(` Runtime: ${options.runtime}`);\n console.log(` Model: ${options.model}`);\n\n // Show what context would be included\n const planningContext = readPlanningContext(workspace);\n const beadsTasks = readBeadsTasks(workspace, projectRoot, id);\n console.log('');\n console.log(chalk.bold('Context:'));\n console.log(` Planning: ${planningContext ? 'Found (.planning/STATE.md)' : 'None'}`);\n console.log(` Beads: ${beadsTasks.length} tasks`);\n return;\n }\n\n spinner.text = 'Building agent prompt with planning context...';\n const prompt = buildAgentPrompt(id, workspace, projectRoot);\n\n spinner.text = 'Spawning agent...';\n\n const agent = spawnAgent({\n issueId: id,\n workspace,\n runtime: options.runtime,\n model: options.model,\n prompt,\n });\n\n spinner.succeed(`Agent spawned: ${agent.id}`);\n\n console.log('');\n console.log(chalk.bold('Agent Details:'));\n console.log(` Session: ${chalk.cyan(agent.id)}`);\n console.log(` Workspace: ${workspace}`);\n console.log(` Runtime: ${agent.runtime} (${agent.model})`);\n\n // Show context info\n const planningContext = readPlanningContext(workspace);\n const beadsTasks = readBeadsTasks(workspace, projectRoot, id);\n if (planningContext || beadsTasks.length > 0) {\n console.log('');\n console.log(chalk.bold('Context Loaded:'));\n if (planningContext) console.log(` Planning: ${chalk.green('✓')} STATE.md`);\n if (beadsTasks.length > 0) console.log(` Beads: ${chalk.green('✓')} ${beadsTasks.length} tasks`);\n }\n\n console.log('');\n console.log(chalk.dim('Commands:'));\n console.log(` Attach: tmux attach -t ${agent.id}`);\n console.log(` Message: pan work tell ${id} \"your message\"`);\n console.log(` Kill: pan work kill ${id}`);\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { listRunningAgents } from '../../../lib/agents.js';\n\ninterface StatusOptions {\n json?: boolean;\n}\n\nexport async function statusCommand(options: StatusOptions): Promise<void> {\n const agents = listRunningAgents();\n\n if (options.json) {\n console.log(JSON.stringify(agents, null, 2));\n return;\n }\n\n if (agents.length === 0) {\n console.log(chalk.dim('No running agents.'));\n console.log(chalk.dim('Use \"pan work issue <id>\" to spawn one.'));\n return;\n }\n\n console.log(chalk.bold('\\nRunning Agents\\n'));\n\n for (const agent of agents) {\n const statusColor = agent.tmuxActive ? chalk.green : chalk.red;\n const status = agent.tmuxActive ? 'running' : 'stopped';\n\n const startedAt = new Date(agent.startedAt);\n const duration = Math.floor((Date.now() - startedAt.getTime()) / 1000 / 60);\n\n console.log(`${chalk.cyan(agent.id)}`);\n console.log(` Issue: ${agent.issueId}`);\n console.log(` Status: ${statusColor(status)}`);\n console.log(` Runtime: ${agent.runtime} (${agent.model})`);\n console.log(` Duration: ${duration} min`);\n console.log(` Workspace: ${chalk.dim(agent.workspace)}`);\n console.log('');\n }\n}\n","import chalk from 'chalk';\nimport { messageAgent } from '../../../lib/agents.js';\n\nexport async function tellCommand(id: string, message: string): Promise<void> {\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n\n try {\n messageAgent(agentId, message);\n console.log(chalk.green('Message sent to ' + agentId));\n console.log(chalk.dim(` \"${message}\"`));\n } catch (error: any) {\n console.error(chalk.red('Error: ' + error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { stopAgent, getAgentState } from '../../../lib/agents.js';\nimport { sessionExists } from '../../../lib/tmux.js';\n\ninterface KillOptions {\n force?: boolean;\n}\n\nexport async function killCommand(id: string, options: KillOptions): Promise<void> {\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n\n // Check if exists\n const state = getAgentState(agentId);\n const isRunning = sessionExists(agentId);\n\n if (!state && !isRunning) {\n console.log(chalk.yellow(`Agent ${agentId} not found.`));\n return;\n }\n\n if (!options.force && isRunning) {\n // In a real implementation, we'd prompt for confirmation\n // For now, just proceed\n }\n\n try {\n stopAgent(agentId);\n console.log(chalk.green(`Killed agent: ${agentId}`));\n } catch (error: any) {\n console.error(chalk.red('Error: ' + error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { listRunningAgents } from '../../../lib/agents.js';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from '../../../lib/paths.js';\n\nexport async function pendingCommand(): Promise<void> {\n // Find agents with completed work (status file or convention)\n // For now, show stopped agents that might have completed work\n\n const agents = listRunningAgents().filter(a => !a.tmuxActive && a.status !== 'error');\n\n if (agents.length === 0) {\n console.log(chalk.dim('No pending reviews.'));\n console.log(chalk.dim('Agents will appear here when they complete work.'));\n return;\n }\n\n console.log(chalk.bold('\\nPending Reviews\\n'));\n\n for (const agent of agents) {\n console.log(`${chalk.cyan(agent.issueId)}`);\n console.log(` Agent: ${agent.id}`);\n console.log(` Workspace: ${chalk.dim(agent.workspace)}`);\n\n // Check for completion notes\n const completionFile = join(AGENTS_DIR, agent.id, 'completion.md');\n if (existsSync(completionFile)) {\n const content = readFileSync(completionFile, 'utf8');\n const firstLine = content.split('\\n').find(l => l.trim() && !l.startsWith('#'));\n if (firstLine) {\n console.log(` Summary: ${chalk.dim(firstLine.trim())}`);\n }\n }\n\n console.log('');\n }\n\n console.log(chalk.dim('Run \"pan work approve <id>\" to approve and merge.'));\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAgentState, saveAgentState } from '../../../lib/agents.js';\nimport { existsSync, writeFileSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { execSync } from 'child_process';\nimport { AGENTS_DIR } from '../../../lib/paths.js';\n\ninterface ApproveOptions {\n merge?: boolean;\n noLinear?: boolean;\n}\n\nfunction getLinearApiKey(): string | null {\n const envFile = join(homedir(), '.panopticon.env');\n if (existsSync(envFile)) {\n const content = readFileSync(envFile, 'utf-8');\n const match = content.match(/LINEAR_API_KEY=(.+)/);\n if (match) return match[1].trim();\n }\n return process.env.LINEAR_API_KEY || null;\n}\n\nfunction checkGhCli(): boolean {\n try {\n execSync('which gh', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findPRForBranch(workspace: string): { number: number; url: string } | null {\n try {\n // Get current branch\n const branch = execSync('git rev-parse --abbrev-ref HEAD', {\n cwd: workspace,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n // Find PR for this branch\n const prJson = execSync(`gh pr list --head \"${branch}\" --json number,url --limit 1`, {\n cwd: workspace,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const prs = JSON.parse(prJson);\n if (prs.length > 0) {\n return { number: prs[0].number, url: prs[0].url };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction mergePR(workspace: string, prNumber: number): { success: boolean; error?: string } {\n try {\n execSync(`gh pr merge ${prNumber} --squash --delete-branch`, {\n cwd: workspace,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return { success: true };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nasync function updateLinearStatus(apiKey: string, issueIdentifier: string): Promise<boolean> {\n try {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey });\n\n // Get the team and find the Done state\n const me = await client.viewer;\n const teams = await me.teams();\n const team = teams.nodes[0];\n\n if (!team) return false;\n\n // Find the issue\n const issues = await team.issues({ first: 100 });\n const issue = issues.nodes.find(\n (i) => i.identifier.toUpperCase() === issueIdentifier.toUpperCase()\n );\n\n if (!issue) return false;\n\n // Find the Done state\n const states = await team.states();\n const doneState = states.nodes.find((s) => s.type === 'completed' && s.name === 'Done');\n\n if (!doneState) return false;\n\n // Update issue\n await issue.update({ stateId: doneState.id });\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function approveCommand(id: string, options: ApproveOptions = {}): Promise<void> {\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n const state = getAgentState(agentId);\n\n if (!state) {\n console.log(chalk.yellow(`Agent ${agentId} not found.`));\n console.log(chalk.dim('Run \"pan work status\" to see running agents.'));\n return;\n }\n\n const spinner = ora('Approving work...').start();\n\n try {\n const workspace = state.workspace;\n let prMerged = false;\n let linearUpdated = false;\n\n // Step 1: Find and merge PR if requested\n if (options.merge !== false) {\n if (!checkGhCli()) {\n spinner.warn('gh CLI not found - skipping PR merge');\n console.log(chalk.dim(' Install: https://cli.github.com/'));\n } else {\n spinner.text = 'Looking for PR...';\n const pr = findPRForBranch(workspace);\n\n if (pr) {\n spinner.text = `Merging PR #${pr.number}...`;\n const result = mergePR(workspace, pr.number);\n\n if (result.success) {\n prMerged = true;\n console.log(chalk.green(` ✓ Merged PR #${pr.number}`));\n } else {\n console.log(chalk.yellow(` ⚠ Failed to merge: ${result.error}`));\n console.log(chalk.dim(` Merge manually: gh pr merge ${pr.number} --squash`));\n }\n } else {\n console.log(chalk.dim(' No PR found for this branch'));\n }\n }\n }\n\n // Step 2: Update Linear status\n if (options.noLinear !== true) {\n const apiKey = getLinearApiKey();\n if (apiKey) {\n spinner.text = 'Updating Linear status...';\n linearUpdated = await updateLinearStatus(apiKey, state.issueId);\n if (linearUpdated) {\n console.log(chalk.green(` ✓ Updated ${state.issueId} to Done`));\n } else {\n console.log(chalk.yellow(` ⚠ Failed to update Linear status`));\n }\n } else {\n console.log(chalk.dim(' LINEAR_API_KEY not set - skipping status update'));\n }\n }\n\n // Step 3: Update agent state\n state.status = 'stopped';\n state.lastActivity = new Date().toISOString();\n saveAgentState(state);\n\n // Mark as approved\n const approvedFile = join(AGENTS_DIR, agentId, 'approved');\n writeFileSync(approvedFile, JSON.stringify({\n timestamp: new Date().toISOString(),\n prMerged,\n linearUpdated,\n }));\n\n spinner.succeed(`Approved: ${state.issueId}`);\n console.log('');\n\n // Summary\n console.log(chalk.bold('Summary:'));\n console.log(` Issue: ${chalk.cyan(state.issueId)}`);\n console.log(` PR: ${prMerged ? chalk.green('Merged') : chalk.dim('Not merged')}`);\n console.log(` Linear: ${linearUpdated ? chalk.green('Updated to Done') : chalk.dim('Not updated')}`);\n console.log('');\n\n console.log(chalk.dim('Workspace can be cleaned up with:'));\n console.log(chalk.dim(` pan workspace destroy ${state.issueId}`));\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport inquirer from 'inquirer';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { execSync } from 'child_process';\n\ninterface PlanOptions {\n output?: string;\n json?: boolean;\n skipDiscovery?: boolean;\n force?: boolean;\n}\n\ninterface LinearIssue {\n id: string;\n identifier: string;\n title: string;\n description?: string;\n state: { name: string };\n priority: number;\n url: string;\n labels?: { name: string }[];\n assignee?: { name: string };\n project?: { name: string };\n}\n\ninterface ComplexityAnalysis {\n isComplex: boolean;\n reasons: string[];\n subsystems: string[];\n estimatedTasks: number;\n}\n\ninterface PlanTask {\n name: string;\n description: string;\n dependsOn?: string;\n}\n\ninterface DiscoveryDecision {\n question: string;\n answer: string;\n}\n\nfunction getLinearApiKey(): string | null {\n const envFile = join(homedir(), '.panopticon.env');\n if (existsSync(envFile)) {\n const content = readFileSync(envFile, 'utf-8');\n const match = content.match(/LINEAR_API_KEY=(.+)/);\n if (match) return match[1].trim();\n }\n return process.env.LINEAR_API_KEY || null;\n}\n\nfunction findPRDFiles(issueId: string): string[] {\n const found: string[] = [];\n const cwd = process.cwd();\n\n const searchPaths = [\n 'docs/prds/active',\n 'docs/prds/planned',\n 'docs/prds',\n 'docs/prd',\n 'prds',\n 'docs',\n ];\n\n const issueIdLower = issueId.toLowerCase();\n\n for (const searchPath of searchPaths) {\n const fullPath = join(cwd, searchPath);\n if (!existsSync(fullPath)) continue;\n\n try {\n const result = execSync(\n `find \"${fullPath}\" -type f -name \"*.md\" 2>/dev/null | xargs grep -l -i \"${issueIdLower}\" 2>/dev/null || true`,\n { encoding: 'utf-8' }\n );\n\n const files = result.trim().split('\\n').filter(f => f);\n found.push(...files);\n } catch {\n // Ignore search errors\n }\n }\n\n return [...new Set(found)];\n}\n\n/**\n * Analyze issue complexity to determine if full planning is needed\n */\nfunction analyzeComplexity(issue: LinearIssue, prdFiles: string[]): ComplexityAnalysis {\n const reasons: string[] = [];\n const subsystems: string[] = [];\n let estimatedTasks = 1;\n\n const desc = (issue.description || '').toLowerCase();\n const title = issue.title.toLowerCase();\n const combined = `${title} ${desc}`;\n\n // Check for multiple subsystems\n if (combined.includes('frontend') || combined.includes('ui') || combined.includes('component')) {\n subsystems.push('frontend');\n }\n if (combined.includes('backend') || combined.includes('api') || combined.includes('endpoint')) {\n subsystems.push('backend');\n }\n if (combined.includes('database') || combined.includes('migration') || combined.includes('schema')) {\n subsystems.push('database');\n }\n if (combined.includes('test') || combined.includes('e2e') || combined.includes('playwright')) {\n subsystems.push('tests');\n }\n\n if (subsystems.length > 1) {\n reasons.push(`Multiple subsystems involved: ${subsystems.join(', ')}`);\n estimatedTasks += subsystems.length;\n }\n\n // Check for ambiguous requirements\n const ambiguousPatterns = [\n 'should we', 'maybe', 'or', 'consider', 'option', 'approach',\n 'tbd', 'to be determined', 'needs discussion', 'unclear'\n ];\n for (const pattern of ambiguousPatterns) {\n if (combined.includes(pattern)) {\n reasons.push('Requirements may be ambiguous');\n break;\n }\n }\n\n // Check for architecture keywords\n const architecturePatterns = [\n 'refactor', 'architecture', 'redesign', 'restructure', 'migrate',\n 'integration', 'authentication', 'authorization', 'security'\n ];\n for (const pattern of architecturePatterns) {\n if (combined.includes(pattern)) {\n reasons.push(`Architecture decision needed: ${pattern}`);\n estimatedTasks += 2;\n break;\n }\n }\n\n // Check description length (longer = more complex usually)\n if (desc.length > 500) {\n reasons.push('Detailed description suggests complexity');\n estimatedTasks += 1;\n }\n\n // Check for existing PRD (pre-done discovery)\n if (prdFiles.length > 0) {\n reasons.push(`PRD exists - complexity already documented`);\n }\n\n // Check labels for complexity hints\n const complexLabels = ['complex', 'large', 'epic', 'multi-phase', 'architecture'];\n for (const label of issue.labels || []) {\n if (complexLabels.some(cl => label.name.toLowerCase().includes(cl))) {\n reasons.push(`Label indicates complexity: ${label.name}`);\n estimatedTasks += 2;\n }\n }\n\n const isComplex = reasons.length >= 2 || subsystems.length > 1 || estimatedTasks >= 4;\n\n return {\n isComplex,\n reasons,\n subsystems,\n estimatedTasks: Math.max(estimatedTasks, subsystems.length + 1),\n };\n}\n\n/**\n * Run discovery phase - ask clarifying questions\n */\nasync function runDiscoveryPhase(\n issue: LinearIssue,\n complexity: ComplexityAnalysis,\n prdContent?: string\n): Promise<{ tasks: PlanTask[]; decisions: DiscoveryDecision[] }> {\n const decisions: DiscoveryDecision[] = [];\n const tasks: PlanTask[] = [];\n\n console.log('');\n console.log(chalk.bold.cyan('═══════════════════════════════════════════════════════════'));\n console.log(chalk.bold.cyan(' DISCOVERY PHASE'));\n console.log(chalk.bold.cyan('═══════════════════════════════════════════════════════════'));\n console.log('');\n console.log(chalk.dim('Answer questions to create a detailed execution plan.'));\n console.log(chalk.dim('Press Enter to skip optional questions.'));\n console.log('');\n\n // Show what we know\n console.log(chalk.bold('Issue:'), `${issue.identifier} - ${issue.title}`);\n if (complexity.subsystems.length > 0) {\n console.log(chalk.bold('Detected subsystems:'), complexity.subsystems.join(', '));\n }\n console.log('');\n\n // Q1: Scope clarification\n const scopeAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'scope',\n message: 'What specific changes are needed? (be specific about files/components):',\n default: issue.description?.slice(0, 100) || '',\n }]);\n if (scopeAnswer.scope) {\n decisions.push({ question: 'Scope', answer: scopeAnswer.scope });\n }\n\n // Q2: Technical approach\n const approachAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'approach',\n message: 'Any specific technical approach or patterns to follow?',\n }]);\n if (approachAnswer.approach) {\n decisions.push({ question: 'Technical approach', answer: approachAnswer.approach });\n }\n\n // Q3: Edge cases\n const edgeCasesAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'edgeCases',\n message: 'Any edge cases or error scenarios to handle?',\n }]);\n if (edgeCasesAnswer.edgeCases) {\n decisions.push({ question: 'Edge cases', answer: edgeCasesAnswer.edgeCases });\n }\n\n // Q4: Testing requirements\n const testingAnswer = await inquirer.prompt([{\n type: 'checkbox',\n name: 'testing',\n message: 'What testing is required?',\n choices: [\n { name: 'Unit tests', value: 'unit', checked: true },\n { name: 'Integration tests', value: 'integration' },\n { name: 'E2E tests (Playwright)', value: 'e2e' },\n { name: 'Manual testing only', value: 'manual' },\n ],\n }]);\n if (testingAnswer.testing.length > 0) {\n decisions.push({ question: 'Testing', answer: testingAnswer.testing.join(', ') });\n }\n\n // Q5: Out of scope\n const outOfScopeAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'outOfScope',\n message: 'Anything explicitly OUT of scope for this issue?',\n }]);\n if (outOfScopeAnswer.outOfScope) {\n decisions.push({ question: 'Out of scope', answer: outOfScopeAnswer.outOfScope });\n }\n\n // Q6: Define tasks\n console.log('');\n console.log(chalk.bold('Define execution tasks:'));\n console.log(chalk.dim('Enter tasks in order. Empty task name to finish.'));\n console.log('');\n\n // Start with standard tasks based on complexity\n const suggestedTasks: PlanTask[] = [\n { name: 'Understand requirements', description: 'Review issue, PRD, and existing code' },\n ];\n\n if (complexity.subsystems.length > 1) {\n suggestedTasks.push({ name: 'Design approach', description: 'Document architecture decisions', dependsOn: 'Understand requirements' });\n }\n\n for (const subsystem of complexity.subsystems) {\n suggestedTasks.push({\n name: `Implement ${subsystem}`,\n description: `Core ${subsystem} changes`,\n dependsOn: complexity.subsystems.length > 1 ? 'Design approach' : 'Understand requirements',\n });\n }\n\n if (suggestedTasks.length === 1) {\n suggestedTasks.push({ name: 'Implement changes', description: 'Core implementation', dependsOn: 'Understand requirements' });\n }\n\n if (testingAnswer.testing.includes('unit') || testingAnswer.testing.includes('integration')) {\n suggestedTasks.push({ name: 'Add tests', description: 'Unit and/or integration tests', dependsOn: suggestedTasks[suggestedTasks.length - 1].name });\n }\n\n if (testingAnswer.testing.includes('e2e')) {\n suggestedTasks.push({ name: 'Add E2E tests', description: 'Playwright E2E tests', dependsOn: 'Add tests' });\n }\n\n suggestedTasks.push({ name: 'Verify and cleanup', description: 'Lint, type check, final review', dependsOn: suggestedTasks[suggestedTasks.length - 1].name });\n\n // Show suggested tasks and let user modify\n console.log(chalk.bold('Suggested tasks:'));\n for (let i = 0; i < suggestedTasks.length; i++) {\n const task = suggestedTasks[i];\n console.log(` ${i + 1}. ${task.name}${task.dependsOn ? chalk.dim(` (after: ${task.dependsOn})`) : ''}`);\n }\n console.log('');\n\n const useDefaultAnswer = await inquirer.prompt([{\n type: 'confirm',\n name: 'useDefault',\n message: 'Use these suggested tasks?',\n default: true,\n }]);\n\n if (useDefaultAnswer.useDefault) {\n tasks.push(...suggestedTasks);\n } else {\n // Custom task entry\n let taskIndex = 1;\n let previousTask = '';\n\n while (true) {\n const taskAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'name',\n message: `Task ${taskIndex} name (empty to finish):`,\n }]);\n\n if (!taskAnswer.name) break;\n\n const descAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'description',\n message: `Task ${taskIndex} description:`,\n default: taskAnswer.name,\n }]);\n\n tasks.push({\n name: taskAnswer.name,\n description: descAnswer.description,\n dependsOn: previousTask || undefined,\n });\n\n previousTask = taskAnswer.name;\n taskIndex++;\n }\n }\n\n return { tasks, decisions };\n}\n\n/**\n * Generate STATE.md content\n */\nfunction generateStateFile(\n issue: LinearIssue,\n decisions: DiscoveryDecision[],\n tasks: PlanTask[]\n): string {\n const lines: string[] = [\n `# Agent State: ${issue.identifier}`,\n '',\n `**Last Updated:** ${new Date().toISOString()}`,\n '',\n '## Current Position',\n '',\n `- **Issue:** ${issue.identifier}`,\n `- **Title:** ${issue.title}`,\n `- **Status:** Planning complete, ready for execution`,\n `- **Linear:** ${issue.url}`,\n '',\n '## Decisions Made During Planning',\n '',\n ];\n\n if (decisions.length > 0) {\n for (const decision of decisions) {\n lines.push(`- **${decision.question}:** ${decision.answer}`);\n }\n } else {\n lines.push('- No specific decisions recorded');\n }\n\n lines.push('');\n lines.push('## Planned Tasks');\n lines.push('');\n\n for (const task of tasks) {\n lines.push(`- [ ] ${task.name}${task.dependsOn ? ` (after: ${task.dependsOn})` : ''}`);\n }\n\n lines.push('');\n lines.push('## Blockers/Concerns');\n lines.push('');\n lines.push('- None identified during planning');\n lines.push('');\n lines.push('## Notes');\n lines.push('');\n lines.push('<!-- Add notes as work progresses -->');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate WORKSPACE.md content\n */\nfunction generateWorkspaceFile(issue: LinearIssue, prdFiles: string[]): string {\n const lines: string[] = [\n `# Workspace: ${issue.identifier}`,\n '',\n `> ${issue.title}`,\n '',\n '## Quick Links',\n '',\n `- [Linear Issue](${issue.url})`,\n ];\n\n for (const prd of prdFiles) {\n const relativePath = prd.replace(process.cwd() + '/', '');\n lines.push(`- [PRD](${relativePath})`);\n }\n\n lines.push('');\n lines.push('## Context Files');\n lines.push('');\n lines.push('- `STATE.md` - Current progress and decisions');\n lines.push('- `WORKSPACE.md` - This file');\n lines.push('');\n lines.push('## Beads');\n lines.push('');\n lines.push('Check current task status:');\n lines.push('```bash');\n lines.push('bd ready # Next actionable task');\n lines.push(`bd list --tag ${issue.identifier} # All tasks for this issue`);\n lines.push('```');\n lines.push('');\n lines.push('## Agent Instructions');\n lines.push('');\n lines.push('1. Run `bd ready` to get next task');\n lines.push('2. Complete the task following relevant skills');\n lines.push('3. Run `bd close \"<task name>\" --reason \"...\"` when done');\n lines.push('4. Update STATE.md with progress');\n lines.push('5. Repeat until all tasks complete');\n lines.push('');\n lines.push('## CRITICAL: Work Completion Requirements');\n lines.push('');\n lines.push('**You are NOT done until ALL of these are true:**');\n lines.push('');\n lines.push('1. **Tests pass** - Run the full test suite');\n lines.push('2. **All changes committed** - `git status` shows \"nothing to commit\"');\n lines.push('3. **Pushed to remote** - `git push`');\n lines.push('');\n lines.push('**Uncommitted changes = NOT COMPLETE.**');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Create Beads tasks with dependencies\n */\nfunction createBeadsTasks(issue: LinearIssue, tasks: PlanTask[]): { success: boolean; created: string[]; errors: string[] } {\n const created: string[] = [];\n const errors: string[] = [];\n const taskIds: Map<string, string> = new Map();\n\n // Check if bd is available\n try {\n execSync('which bd', { encoding: 'utf-8' });\n } catch {\n return { success: false, created: [], errors: ['bd (beads) CLI not found in PATH'] };\n }\n\n for (const task of tasks) {\n const fullName = `${issue.identifier}: ${task.name}`;\n\n try {\n // Build bd create command with correct flags\n // bd create \"title\" --type task -l label1,label2 -d \"description\" --deps \"blocks:id\"\n const escapedName = fullName.replace(/\"/g, '\\\\\"');\n let cmd = `bd create \"${escapedName}\" --type task -l \"${issue.identifier},linear\"`;\n\n // Add dependency if specified (format: blocks:id)\n if (task.dependsOn) {\n const depName = `${issue.identifier}: ${task.dependsOn}`;\n const depId = taskIds.get(depName);\n if (depId) {\n cmd += ` --deps \"blocks:${depId}\"`;\n }\n }\n\n // Add description\n if (task.description) {\n const escapedDesc = task.description.replace(/\"/g, '\\\\\"');\n cmd += ` -d \"${escapedDesc}\"`;\n }\n\n const result = execSync(cmd, { encoding: 'utf-8', cwd: process.cwd() });\n\n // Extract ID from output - bd outputs \"Created: bd-XXXX\" or similar\n const idMatch = result.match(/bd-[a-f0-9]+/i) || result.match(/([a-f0-9-]{8,})/i);\n if (idMatch) {\n taskIds.set(fullName, idMatch[0]);\n }\n\n created.push(fullName);\n } catch (error: any) {\n // Extract meaningful error from stderr\n const errMsg = error.stderr?.toString() || error.message;\n errors.push(`Failed to create \"${task.name}\": ${errMsg.split('\\n')[0]}`);\n }\n }\n\n // Sync beads to git (bd uses 'bd flush' to export to JSONL)\n if (created.length > 0) {\n try {\n execSync('bd flush', { encoding: 'utf-8', cwd: process.cwd() });\n } catch {\n // Flush might fail if no changes, that's OK\n }\n }\n\n return { success: errors.length === 0, created, errors };\n}\n\n/**\n * Copy plan to PRD directory\n */\nfunction copyToPRDDirectory(issue: LinearIssue, stateContent: string): string | null {\n const cwd = process.cwd();\n const prdDir = join(cwd, 'docs', 'prds', 'active');\n\n try {\n mkdirSync(prdDir, { recursive: true });\n\n const filename = `${issue.identifier.toLowerCase()}-plan.md`;\n const prdPath = join(prdDir, filename);\n\n writeFileSync(prdPath, stateContent);\n\n return prdPath;\n } catch {\n return null;\n }\n}\n\nexport async function planCommand(id: string, options: PlanOptions = {}): Promise<void> {\n const spinner = ora(`Creating execution plan for ${id}...`).start();\n\n try {\n const apiKey = getLinearApiKey();\n if (!apiKey) {\n spinner.fail('LINEAR_API_KEY not found');\n console.log('');\n console.log(chalk.dim('Set it in ~/.panopticon.env:'));\n console.log(' LINEAR_API_KEY=lin_api_xxxxx');\n process.exit(1);\n }\n\n // Fetch issue from Linear\n spinner.text = 'Fetching issue from Linear...';\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey });\n\n const me = await client.viewer;\n const teams = await me.teams();\n const team = teams.nodes[0];\n\n if (!team) {\n spinner.fail('No Linear team found');\n process.exit(1);\n }\n\n const searchResult = await team.issues({ first: 100 });\n const issue = searchResult.nodes.find(\n (i) => i.identifier.toUpperCase() === id.toUpperCase()\n );\n\n if (!issue) {\n spinner.fail(`Issue not found: ${id}`);\n process.exit(1);\n }\n\n const state = await issue.state;\n const assignee = await issue.assignee;\n const project = await issue.project;\n const labels = await issue.labels();\n\n const issueData: LinearIssue = {\n id: issue.id,\n identifier: issue.identifier,\n title: issue.title,\n description: issue.description || undefined,\n state: { name: state?.name || 'Unknown' },\n priority: issue.priority,\n url: issue.url,\n labels: labels.nodes.map(l => ({ name: l.name })),\n assignee: assignee ? { name: assignee.name } : undefined,\n project: project ? { name: project.name } : undefined,\n };\n\n // Look for related PRD files\n spinner.text = 'Searching for related PRDs...';\n const prdFiles = findPRDFiles(id);\n\n // Analyze complexity\n spinner.text = 'Analyzing complexity...';\n const complexity = analyzeComplexity(issueData, prdFiles);\n\n spinner.stop();\n\n // Show complexity analysis\n console.log('');\n console.log(chalk.bold('═══════════════════════════════════════════════════════════'));\n console.log(chalk.bold(` ${issueData.identifier}: ${issueData.title}`));\n console.log(chalk.bold('═══════════════════════════════════════════════════════════'));\n console.log('');\n\n console.log(chalk.bold('Complexity Analysis:'));\n console.log(` Level: ${complexity.isComplex ? chalk.yellow('COMPLEX') : chalk.green('SIMPLE')}`);\n console.log(` Estimated tasks: ${complexity.estimatedTasks}`);\n if (complexity.subsystems.length > 0) {\n console.log(` Subsystems: ${complexity.subsystems.join(', ')}`);\n }\n if (complexity.reasons.length > 0) {\n console.log(` Reasons:`);\n for (const reason of complexity.reasons) {\n console.log(` - ${reason}`);\n }\n }\n console.log('');\n\n if (prdFiles.length > 0) {\n console.log(chalk.bold('Related PRDs found:'));\n for (const prd of prdFiles) {\n console.log(` - ${prd.replace(process.cwd() + '/', '')}`);\n }\n console.log('');\n }\n\n // For simple issues, offer to skip planning\n if (!complexity.isComplex && !options.force) {\n const skipAnswer = await inquirer.prompt([{\n type: 'confirm',\n name: 'skip',\n message: 'This looks simple. Skip planning and go straight to /work-issue?',\n default: true,\n }]);\n\n if (skipAnswer.skip) {\n console.log('');\n console.log(chalk.cyan(`Run: pan work issue ${id}`));\n console.log('');\n return;\n }\n }\n\n // Run discovery phase\n let tasks: PlanTask[];\n let decisions: DiscoveryDecision[];\n\n if (options.skipDiscovery) {\n // Use default tasks based on complexity\n tasks = [\n { name: 'Understand requirements', description: 'Review issue and existing code' },\n { name: 'Implement changes', description: 'Core implementation', dependsOn: 'Understand requirements' },\n { name: 'Add tests', description: 'Unit/integration tests', dependsOn: 'Implement changes' },\n { name: 'Verify and cleanup', description: 'Lint, type check, final review', dependsOn: 'Add tests' },\n ];\n decisions = [];\n } else {\n const discovery = await runDiscoveryPhase(issueData, complexity);\n tasks = discovery.tasks;\n decisions = discovery.decisions;\n }\n\n // Generate context files\n const spinnerCreate = ora('Creating context files...').start();\n\n const stateContent = generateStateFile(issueData, decisions, tasks);\n const workspaceContent = generateWorkspaceFile(issueData, prdFiles);\n\n // Determine output directory (workspace or current)\n const outputDir = options.output ? dirname(options.output) : process.cwd();\n const planningDir = join(outputDir, '.planning');\n mkdirSync(planningDir, { recursive: true });\n\n // Write STATE.md\n const statePath = join(planningDir, 'STATE.md');\n writeFileSync(statePath, stateContent);\n\n // Write WORKSPACE.md\n const workspacePath = join(planningDir, 'WORKSPACE.md');\n writeFileSync(workspacePath, workspaceContent);\n\n spinnerCreate.succeed('Context files created');\n\n // Create Beads tasks\n const spinnerBeads = ora('Creating Beads tasks...').start();\n const beadsResult = createBeadsTasks(issueData, tasks);\n\n if (beadsResult.success) {\n spinnerBeads.succeed(`Created ${beadsResult.created.length} Beads tasks`);\n } else {\n spinnerBeads.warn(`Created ${beadsResult.created.length} tasks with errors`);\n for (const error of beadsResult.errors) {\n console.log(chalk.red(` - ${error}`));\n }\n }\n\n // Copy to PRD directory\n const prdPath = copyToPRDDirectory(issueData, stateContent);\n if (prdPath) {\n console.log(chalk.dim(`Plan copied to: ${prdPath.replace(process.cwd() + '/', '')}`));\n }\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify({\n issue: issueData,\n complexity,\n tasks,\n decisions,\n files: {\n state: statePath,\n workspace: workspacePath,\n prd: prdPath,\n },\n beads: beadsResult,\n }, null, 2));\n return;\n }\n\n // Summary\n console.log('');\n console.log(chalk.bold.green('═══════════════════════════════════════════════════════════'));\n console.log(chalk.bold.green(' PLAN COMPLETE'));\n console.log(chalk.bold.green('═══════════════════════════════════════════════════════════'));\n console.log('');\n\n console.log(chalk.bold('Files created:'));\n console.log(` ${chalk.cyan(statePath.replace(process.cwd() + '/', ''))}`);\n console.log(` ${chalk.cyan(workspacePath.replace(process.cwd() + '/', ''))}`);\n console.log('');\n\n console.log(chalk.bold('Beads tasks:'));\n for (const task of tasks) {\n console.log(` ${chalk.dim('○')} ${issueData.identifier}: ${task.name}`);\n }\n console.log('');\n\n if (decisions.length > 0) {\n console.log(chalk.bold('Decisions recorded:'));\n for (const decision of decisions) {\n console.log(` - ${decision.question}: ${chalk.dim(decision.answer.slice(0, 50))}${decision.answer.length > 50 ? '...' : ''}`);\n }\n console.log('');\n }\n\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Review ${chalk.cyan('.planning/STATE.md')}`);\n console.log(` 2. Run ${chalk.cyan(`pan work issue ${id}`)} to spawn agent`);\n console.log(` 3. Agent will use ${chalk.cyan('bd ready')} to get tasks`);\n console.log('');\n\n } catch (error: any) {\n console.error(chalk.red(`Error: ${error.message}`));\n process.exit(1);\n }\n}\n","/**\n * work list - List issues from configured trackers\n *\n * Uses the tracker abstraction to support Linear, GitHub, and GitLab.\n */\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { loadConfig } from '../../../lib/config.js';\nimport type { Issue, IssueTracker, TrackerType } from '../../../lib/tracker/index.js';\nimport { createTracker, TrackerConfig } from '../../../lib/tracker/index.js';\n\ninterface ListOptions {\n all?: boolean;\n mine?: boolean;\n json?: boolean;\n tracker?: string;\n allTrackers?: boolean;\n}\n\nconst PRIORITY_LABELS: Record<number, string> = {\n 0: chalk.dim('None'),\n 1: chalk.red('Urgent'),\n 2: chalk.yellow('High'),\n 3: chalk.blue('Medium'),\n 4: chalk.dim('Low'),\n};\n\nconst STATE_COLORS: Record<string, (s: string) => string> = {\n 'open': chalk.white,\n 'in_progress': chalk.yellow,\n 'closed': chalk.green,\n};\n\n/**\n * Get tracker config by type from panopticon config\n */\nfunction getTrackerConfig(trackerType: TrackerType): TrackerConfig | null {\n const config = loadConfig();\n const trackerConfig = config.trackers[trackerType];\n\n if (!trackerConfig) {\n return null;\n }\n\n return {\n type: trackerType,\n apiKeyEnv: (trackerConfig as any).api_key_env,\n team: (trackerConfig as any).team,\n tokenEnv: (trackerConfig as any).token_env,\n owner: (trackerConfig as any).owner,\n repo: (trackerConfig as any).repo,\n projectId: (trackerConfig as any).project_id,\n server: (trackerConfig as any).server,\n workspace: (trackerConfig as any).workspace,\n project: (trackerConfig as any).project,\n };\n}\n\n/**\n * Get all configured trackers\n */\nfunction getConfiguredTrackers(): TrackerType[] {\n const config = loadConfig();\n const trackers: TrackerType[] = [];\n\n if (config.trackers.linear) trackers.push('linear');\n if (config.trackers.github) trackers.push('github');\n if (config.trackers.gitlab) trackers.push('gitlab');\n if (config.trackers.rally) trackers.push('rally');\n\n return trackers;\n}\n\n/**\n * Display issues in a formatted way\n */\nfunction displayIssues(issues: Issue[], trackerName: string): void {\n if (issues.length === 0) {\n console.log(chalk.dim(` No issues found in ${trackerName}`));\n return;\n }\n\n // Group by state\n const byState: Record<string, Issue[]> = {};\n for (const issue of issues) {\n if (!byState[issue.state]) byState[issue.state] = [];\n byState[issue.state].push(issue);\n }\n\n // Display order\n const stateOrder = ['in_progress', 'open', 'closed'];\n\n for (const state of stateOrder) {\n const stateIssues = byState[state];\n if (!stateIssues || stateIssues.length === 0) continue;\n\n const colorFn = STATE_COLORS[state] || chalk.white;\n const displayState = state.replace('_', ' ').replace(/\\b\\w/g, l => l.toUpperCase());\n console.log(colorFn(` ── ${displayState} (${stateIssues.length}) ──`));\n\n for (const issue of stateIssues) {\n const priorityLabel = issue.priority ? PRIORITY_LABELS[issue.priority] || '' : '';\n const assigneeStr = issue.assignee ? chalk.dim(` @${issue.assignee.split(' ')[0]}`) : '';\n const priorityStr = issue.priority && issue.priority < 3 ? ` ${priorityLabel}` : '';\n\n console.log(` ${chalk.cyan(issue.ref)} ${issue.title}${assigneeStr}${priorityStr}`);\n }\n console.log('');\n }\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n const spinner = ora('Fetching issues...').start();\n\n try {\n const config = loadConfig();\n const trackersToQuery: TrackerType[] = [];\n\n // Determine which trackers to query\n if (options.tracker) {\n // Specific tracker requested\n const trackerType = options.tracker as TrackerType;\n if (!['linear', 'github', 'gitlab', 'rally'].includes(trackerType)) {\n spinner.fail(`Unknown tracker: ${options.tracker}`);\n console.log(chalk.dim('Valid trackers: linear, github, gitlab, rally'));\n process.exit(1);\n }\n trackersToQuery.push(trackerType);\n } else if (options.allTrackers) {\n // All configured trackers\n trackersToQuery.push(...getConfiguredTrackers());\n } else {\n // Primary tracker only (default)\n trackersToQuery.push(config.trackers.primary);\n }\n\n if (trackersToQuery.length === 0) {\n spinner.fail('No trackers configured');\n console.log(chalk.dim('Configure trackers in ~/.panopticon/config.toml'));\n process.exit(1);\n }\n\n // Fetch issues from all requested trackers\n const allIssues: { tracker: TrackerType; issues: Issue[] }[] = [];\n\n for (const trackerType of trackersToQuery) {\n spinner.text = `Fetching from ${trackerType}...`;\n\n const trackerConfig = getTrackerConfig(trackerType);\n if (!trackerConfig) {\n console.log(chalk.yellow(`\\nWarning: ${trackerType} not configured, skipping`));\n continue;\n }\n\n try {\n const tracker = createTracker(trackerConfig);\n const issues = await tracker.listIssues({\n includeClosed: options.all,\n assignee: options.mine ? 'me' : undefined,\n });\n allIssues.push({ tracker: trackerType, issues });\n } catch (error: any) {\n console.log(chalk.yellow(`\\nWarning: Failed to fetch from ${trackerType}: ${error.message}`));\n }\n }\n\n spinner.stop();\n\n // JSON output\n if (options.json) {\n const output = allIssues.flatMap(({ tracker, issues }) =>\n issues.map(issue => ({ ...issue, source: tracker }))\n );\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Display results\n const totalIssues = allIssues.reduce((sum, { issues }) => sum + issues.length, 0);\n\n if (totalIssues === 0) {\n console.log(chalk.dim('\\nNo issues found.'));\n return;\n }\n\n for (const { tracker, issues } of allIssues) {\n console.log(chalk.bold(`\\n${tracker.toUpperCase()} (${issues.length} issues)\\n`));\n displayIssues(issues, tracker);\n }\n\n // Footer\n const trackerNames = trackersToQuery.join(', ');\n console.log(chalk.dim(`Showing ${totalIssues} issues from ${trackerNames}.`));\n if (!options.all) {\n console.log(chalk.dim('Use --all to include closed issues.'));\n }\n if (!options.allTrackers && trackersToQuery.length === 1) {\n console.log(chalk.dim('Use --all-trackers to query all configured trackers.'));\n }\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","/**\n * work triage - Triage issues from secondary tracker to primary tracker\n *\n * Uses the tracker abstraction to move issues between trackers.\n */\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { loadConfig } from '../../../lib/config.js';\nimport type { Issue, TrackerType } from '../../../lib/tracker/index.js';\nimport { createTracker, TrackerConfig } from '../../../lib/tracker/index.js';\n\ninterface TriageOptions {\n create?: boolean;\n dismiss?: string;\n}\n\ninterface TriageState {\n dismissed: string[]; // Issue refs that were dismissed\n created: { [sourceRef: string]: string }; // Source ref -> Primary ref\n}\n\n/**\n * Get tracker config by type from panopticon config\n */\nfunction getTrackerConfig(trackerType: TrackerType): TrackerConfig | null {\n const config = loadConfig();\n const trackerConfig = config.trackers[trackerType];\n\n if (!trackerConfig) {\n return null;\n }\n\n return {\n type: trackerType,\n apiKeyEnv: (trackerConfig as any).api_key_env,\n team: (trackerConfig as any).team,\n tokenEnv: (trackerConfig as any).token_env,\n owner: (trackerConfig as any).owner,\n repo: (trackerConfig as any).repo,\n projectId: (trackerConfig as any).project_id,\n };\n}\n\nfunction getTriageStatePath(): string {\n return join(homedir(), '.panopticon', 'triage-state.json');\n}\n\nfunction loadTriageState(): TriageState {\n const path = getTriageStatePath();\n if (existsSync(path)) {\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return { dismissed: [], created: {} };\n }\n }\n return { dismissed: [], created: {} };\n}\n\nfunction saveTriageState(state: TriageState): void {\n const dir = join(homedir(), '.panopticon');\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n const path = getTriageStatePath();\n writeFileSync(path, JSON.stringify(state, null, 2));\n}\n\nexport async function triageCommand(id?: string, options: TriageOptions = {}): Promise<void> {\n const spinner = ora('Loading triage queue...').start();\n\n try {\n const config = loadConfig();\n const primaryType = config.trackers.primary;\n const secondaryType = config.trackers.secondary;\n\n // Check for secondary tracker configuration\n if (!secondaryType) {\n spinner.info('No secondary tracker configured');\n console.log('');\n console.log(chalk.bold('Setup Instructions:'));\n console.log('');\n console.log('Add secondary tracker to ~/.panopticon/config.toml:');\n console.log(chalk.dim(`\n[trackers]\nprimary = \"linear\"\nsecondary = \"github\"\n\n[trackers.github]\ntype = \"github\"\ntoken_env = \"GITHUB_TOKEN\"\nowner = \"your-org\"\nrepo = \"your-repo\"\n`));\n return;\n }\n\n const primaryConfig = getTrackerConfig(primaryType);\n const secondaryConfig = getTrackerConfig(secondaryType);\n\n if (!primaryConfig) {\n spinner.fail(`Primary tracker (${primaryType}) not configured`);\n return;\n }\n\n if (!secondaryConfig) {\n spinner.fail(`Secondary tracker (${secondaryType}) not configured`);\n return;\n }\n\n const triageState = loadTriageState();\n\n // If specific ID provided, handle create/dismiss\n if (id) {\n // Normalize the ID (remove # prefix if present for GitHub)\n const issueRef = id.startsWith('#') ? id : `#${id}`;\n\n if (options.dismiss) {\n if (!triageState.dismissed.includes(issueRef)) {\n triageState.dismissed.push(issueRef);\n saveTriageState(triageState);\n }\n spinner.succeed(`Dismissed ${issueRef}: ${options.dismiss}`);\n return;\n }\n\n if (options.create) {\n spinner.text = `Fetching ${secondaryType} issue ${issueRef}...`;\n\n let secondaryTracker;\n try {\n secondaryTracker = createTracker(secondaryConfig);\n } catch (error: any) {\n spinner.fail(`Failed to connect to ${secondaryType}: ${error.message}`);\n return;\n }\n\n let sourceIssue: Issue;\n try {\n sourceIssue = await secondaryTracker.getIssue(id);\n } catch (error: any) {\n spinner.fail(`Issue ${issueRef} not found in ${secondaryType}`);\n return;\n }\n\n spinner.text = `Creating ${primaryType} issue...`;\n\n let primaryTracker;\n try {\n primaryTracker = createTracker(primaryConfig);\n } catch (error: any) {\n spinner.fail(`Failed to connect to ${primaryType}: ${error.message}`);\n return;\n }\n\n // Create issue in primary tracker with link to secondary\n const newIssue = await primaryTracker.createIssue({\n title: sourceIssue.title,\n description: `${sourceIssue.description}\\n\\n---\\n\\n**From ${secondaryType}:** ${sourceIssue.url}`,\n team: primaryConfig.team,\n });\n\n // Add comment to secondary issue linking to primary\n try {\n await secondaryTracker.addComment(\n id,\n `Internal tracking: ${newIssue.ref} (${primaryType})`\n );\n } catch {\n // Non-fatal - just log warning\n console.log(chalk.yellow('\\nNote: Could not add link comment to source issue'));\n }\n\n triageState.created[sourceIssue.ref] = newIssue.ref;\n saveTriageState(triageState);\n\n spinner.succeed(`Created ${newIssue.ref} from ${sourceIssue.ref}`);\n console.log('');\n console.log(` ${secondaryType}: ${chalk.dim(sourceIssue.url)}`);\n console.log(` ${primaryType}: ${chalk.cyan(newIssue.ref)}`);\n return;\n }\n }\n\n // List all secondary tracker issues needing triage\n spinner.text = `Fetching ${secondaryType} issues...`;\n\n let secondaryTracker;\n try {\n secondaryTracker = createTracker(secondaryConfig);\n } catch (error: any) {\n spinner.fail(`Failed to connect to ${secondaryType}: ${error.message}`);\n return;\n }\n\n const issues = await secondaryTracker.listIssues({ includeClosed: false });\n\n // Filter out dismissed and already created\n const pending = issues.filter(\n (i) => !triageState.dismissed.includes(i.ref) && !triageState.created[i.ref]\n );\n\n spinner.stop();\n\n if (pending.length === 0) {\n console.log(chalk.green('No issues pending triage.'));\n console.log(chalk.dim(`${issues.length} total open, ${triageState.dismissed.length} dismissed, ${Object.keys(triageState.created).length} created`));\n return;\n }\n\n console.log(chalk.bold(`\\n${secondaryType.toUpperCase()} Issues Pending Triage (${pending.length})\\n`));\n\n for (const issue of pending) {\n const labels = issue.labels.map((l) => chalk.dim(`[${l}]`)).join(' ');\n console.log(` ${chalk.cyan(issue.ref)} ${issue.title} ${labels}`);\n console.log(` ${chalk.dim(issue.url)}`);\n }\n\n console.log('');\n console.log(chalk.bold('Commands:'));\n console.log(` ${chalk.dim(`Create ${primaryType} issue:`)} pan work triage <id> --create`);\n console.log(` ${chalk.dim('Dismiss from queue:')} pan work triage <id> --dismiss \"reason\"`);\n console.log('');\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport {\n checkHook,\n pushToHook,\n popFromHook,\n clearHook,\n sendMail,\n generateGUPPPrompt,\n HookItem,\n} from '../../../lib/hooks.js';\n\ninterface HookOptions {\n json?: boolean;\n}\n\nexport async function hookCommand(\n action: string,\n idOrMessage?: string,\n options: HookOptions = {}\n): Promise<void> {\n // Normalize agent ID\n const agentId = process.env.PANOPTICON_AGENT_ID || 'default';\n\n switch (action) {\n case 'check': {\n const result = checkHook(idOrMessage || agentId);\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (!result.hasWork) {\n console.log(chalk.green('✓ No pending work on hook'));\n return;\n }\n\n console.log(chalk.yellow(`⚠ ${result.items.length} item(s) on hook`));\n if (result.urgentCount > 0) {\n console.log(chalk.red(` ${result.urgentCount} URGENT`));\n }\n console.log('');\n\n for (const item of result.items) {\n const priorityColor = {\n urgent: chalk.red,\n high: chalk.yellow,\n normal: chalk.white,\n low: chalk.dim,\n }[item.priority];\n\n console.log(`${priorityColor(`[${item.priority.toUpperCase()}]`)} ${item.id}`);\n console.log(` Type: ${item.type}`);\n console.log(` From: ${item.source}`);\n if (item.payload.message) {\n console.log(` Message: ${item.payload.message}`);\n }\n console.log('');\n }\n break;\n }\n\n case 'push': {\n if (!idOrMessage) {\n console.log(chalk.red('Usage: pan work hook push <agent-id> <message>'));\n process.exit(1);\n }\n\n const [targetAgent, ...messageParts] = idOrMessage.split(' ');\n const message = messageParts.join(' ');\n\n if (!message) {\n console.log(chalk.red('Message required'));\n process.exit(1);\n }\n\n const item = pushToHook(targetAgent.startsWith('agent-') ? targetAgent : `agent-${targetAgent}`, {\n type: 'task',\n priority: 'normal',\n source: 'cli',\n payload: { message },\n });\n\n console.log(chalk.green(`✓ Pushed to hook: ${item.id}`));\n break;\n }\n\n case 'pop': {\n if (!idOrMessage) {\n console.log(chalk.red('Usage: pan work hook pop <item-id>'));\n process.exit(1);\n }\n\n const success = popFromHook(agentId, idOrMessage);\n if (success) {\n console.log(chalk.green(`✓ Popped: ${idOrMessage}`));\n } else {\n console.log(chalk.yellow(`Item not found: ${idOrMessage}`));\n }\n break;\n }\n\n case 'clear': {\n clearHook(idOrMessage || agentId);\n console.log(chalk.green('✓ Hook cleared'));\n break;\n }\n\n case 'mail': {\n if (!idOrMessage) {\n console.log(chalk.red('Usage: pan work hook mail <agent-id> <message>'));\n process.exit(1);\n }\n\n const [targetAgent, ...messageParts] = idOrMessage.split(' ');\n const message = messageParts.join(' ');\n\n if (!message) {\n console.log(chalk.red('Message required'));\n process.exit(1);\n }\n\n sendMail(\n targetAgent.startsWith('agent-') ? targetAgent : `agent-${targetAgent}`,\n 'cli',\n message\n );\n\n console.log(chalk.green(`✓ Mail sent to ${targetAgent}`));\n break;\n }\n\n case 'gupp': {\n const prompt = generateGUPPPrompt(idOrMessage || agentId);\n\n if (!prompt) {\n console.log(chalk.green('No GUPP work found'));\n return;\n }\n\n console.log(prompt);\n break;\n }\n\n default:\n console.log(chalk.bold('Hook Commands:'));\n console.log('');\n console.log(` ${chalk.cyan('pan work hook check [agent-id]')} - Check for pending work`);\n console.log(` ${chalk.cyan('pan work hook push <agent-id> <msg>')} - Push task to hook`);\n console.log(` ${chalk.cyan('pan work hook pop <item-id>')} - Remove completed item`);\n console.log(` ${chalk.cyan('pan work hook clear [agent-id]')} - Clear all hook items`);\n console.log(` ${chalk.cyan('pan work hook mail <agent-id> <msg>')} - Send mail to agent`);\n console.log(` ${chalk.cyan('pan work hook gupp [agent-id]')} - Generate GUPP prompt`);\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport {\n detectCrashedAgents,\n recoverAgent,\n autoRecoverAgents,\n} from '../../../lib/agents.js';\n\ninterface RecoverOptions {\n all?: boolean;\n json?: boolean;\n}\n\nexport async function recoverCommand(id?: string, options: RecoverOptions = {}): Promise<void> {\n const spinner = ora('Checking for crashed agents...').start();\n\n try {\n // Auto-recover all crashed agents\n if (options.all || !id) {\n const crashed = detectCrashedAgents();\n\n if (crashed.length === 0) {\n spinner.succeed('No crashed agents found');\n return;\n }\n\n if (options.json) {\n spinner.stop();\n console.log(JSON.stringify({ crashed: crashed.map((a) => a.id) }, null, 2));\n\n if (!options.all) {\n console.log(chalk.dim('\\nUse --all to auto-recover all crashed agents'));\n return;\n }\n }\n\n if (!options.all) {\n spinner.info(`Found ${crashed.length} crashed agent(s)`);\n console.log('');\n\n for (const agent of crashed) {\n console.log(` ${chalk.red('●')} ${chalk.cyan(agent.id)}`);\n console.log(` Issue: ${agent.issueId}`);\n console.log(` Started: ${agent.startedAt}`);\n console.log('');\n }\n\n console.log(chalk.dim('Use --all to auto-recover, or specify an agent ID'));\n return;\n }\n\n spinner.text = 'Auto-recovering agents...';\n const result = autoRecoverAgents();\n\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (result.recovered.length > 0) {\n console.log(chalk.green(`✓ Recovered ${result.recovered.length} agent(s):`));\n for (const agentId of result.recovered) {\n console.log(` ${chalk.cyan(agentId)}`);\n }\n }\n\n if (result.failed.length > 0) {\n console.log(chalk.red(`✗ Failed to recover ${result.failed.length} agent(s):`));\n for (const agentId of result.failed) {\n console.log(` ${chalk.dim(agentId)}`);\n }\n }\n\n return;\n }\n\n // Recover specific agent\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n spinner.text = `Recovering ${agentId}...`;\n\n const state = recoverAgent(agentId);\n\n if (!state) {\n spinner.fail(`Agent not found: ${agentId}`);\n process.exit(1);\n }\n\n spinner.succeed(`Recovered: ${agentId}`);\n console.log('');\n console.log(chalk.bold('Agent Details:'));\n console.log(` Issue: ${chalk.cyan(state.issueId)}`);\n console.log(` Workspace: ${chalk.dim(state.workspace)}`);\n console.log(` Model: ${state.model}`);\n console.log('');\n console.log(chalk.dim('Commands:'));\n console.log(` Attach: tmux attach -t ${state.id}`);\n console.log(` Message: pan work tell ${state.issueId} \"your message\"`);\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport {\n getAgentCV,\n getAgentRankings,\n formatCV,\n startWork,\n completeWork,\n} from '../../../lib/cv.js';\n\ninterface CVOptions {\n json?: boolean;\n rankings?: boolean;\n}\n\nexport async function cvCommand(agentId?: string, options: CVOptions = {}): Promise<void> {\n // Show rankings\n if (options.rankings || !agentId) {\n const rankings = getAgentRankings();\n\n if (options.json) {\n console.log(JSON.stringify(rankings, null, 2));\n return;\n }\n\n if (rankings.length === 0) {\n console.log(chalk.dim('No agent work history yet.'));\n console.log(chalk.dim('CVs are created as agents complete work.'));\n return;\n }\n\n console.log(chalk.bold('\\nAgent Rankings\\n'));\n\n // Header\n console.log(\n `${'Agent'.padEnd(25)} ${'Success'.padStart(8)} ${'Total'.padStart(6)} ${'Avg Time'.padStart(10)}`\n );\n console.log(chalk.dim('─'.repeat(52)));\n\n for (let i = 0; i < rankings.length; i++) {\n const r = rankings[i];\n const medal = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : ' ';\n const successPct = `${(r.successRate * 100).toFixed(0)}%`;\n const avgTime = r.avgDuration > 0 ? `${r.avgDuration}m` : '-';\n\n console.log(\n `${medal} ${r.agentId.padEnd(22)} ${successPct.padStart(8)} ${r.totalIssues\n .toString()\n .padStart(6)} ${avgTime.padStart(10)}`\n );\n }\n\n console.log('');\n console.log(chalk.dim(`Use: pan work cv <agent-id> for details`));\n return;\n }\n\n // Show specific agent CV\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n const cv = getAgentCV(normalizedId);\n\n if (options.json) {\n console.log(JSON.stringify(cv, null, 2));\n return;\n }\n\n console.log('');\n console.log(formatCV(cv));\n}\n\n// Export helper functions for integration\nexport { startWork, completeWork };\n","import chalk from 'chalk';\nimport {\n readAgentState,\n writeAgentState,\n updateCheckpoint,\n appendSummary,\n logHistory,\n searchHistory,\n getRecentHistory,\n materializeOutput,\n listMaterialized,\n readMaterialized,\n estimateTokens,\n AgentStateContext,\n} from '../../../lib/context.js';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from '../../../lib/paths.js';\n\ninterface ContextOptions {\n json?: boolean;\n}\n\nexport async function contextCommand(\n action: string,\n arg1?: string,\n arg2?: string,\n options: ContextOptions = {}\n): Promise<void> {\n // Get agent ID from environment or argument\n const agentId = process.env.PANOPTICON_AGENT_ID || arg1 || 'default';\n\n switch (action) {\n case 'state': {\n // Show or update STATE.md\n const state = readAgentState(agentId);\n\n if (options.json) {\n console.log(JSON.stringify(state, null, 2));\n return;\n }\n\n if (!state) {\n console.log(chalk.dim('No state found for agent.'));\n console.log(chalk.dim('Initialize with: pan work context init <agent-id> <issue-id>'));\n return;\n }\n\n console.log(chalk.bold(`\\nAgent State: ${state.issueId}\\n`));\n console.log(`Status: ${chalk.cyan(state.status)}`);\n console.log(`Last Activity: ${chalk.dim(state.lastActivity)}`);\n\n if (state.lastCheckpoint) {\n console.log('');\n console.log(chalk.bold('Session Continuity:'));\n console.log(` Checkpoint: ${chalk.yellow(state.lastCheckpoint)}`);\n if (state.resumePoint) {\n console.log(` Resume: ${chalk.green(state.resumePoint)}`);\n }\n }\n\n if (state.contextRefs.workspace || state.contextRefs.prd) {\n console.log('');\n console.log(chalk.bold('Context References:'));\n if (state.contextRefs.workspace) {\n console.log(` Workspace: ${chalk.dim(state.contextRefs.workspace)}`);\n }\n if (state.contextRefs.prd) {\n console.log(` PRD: ${chalk.dim(state.contextRefs.prd)}`);\n }\n if (state.contextRefs.beads) {\n console.log(` Beads: ${chalk.dim(state.contextRefs.beads)}`);\n }\n }\n console.log('');\n break;\n }\n\n case 'init': {\n // Initialize STATE.md for an agent\n const issueId = arg2 || arg1 || 'UNKNOWN';\n const targetAgent = arg2 ? arg1 : agentId;\n\n const state: AgentStateContext = {\n issueId: issueId.toUpperCase(),\n status: 'In Progress',\n lastActivity: new Date().toISOString(),\n contextRefs: {},\n };\n\n writeAgentState(targetAgent!, state);\n logHistory(targetAgent!, 'context:init', { issueId });\n\n console.log(chalk.green(`✓ Initialized state for ${targetAgent}`));\n break;\n }\n\n case 'checkpoint': {\n // Update checkpoint\n const checkpoint = arg1;\n const resume = arg2;\n\n if (!checkpoint) {\n console.log(chalk.red('Checkpoint message required'));\n console.log(chalk.dim('Usage: pan work context checkpoint \"message\" [\"resume point\"]'));\n return;\n }\n\n updateCheckpoint(agentId, checkpoint, resume);\n logHistory(agentId, 'context:checkpoint', { checkpoint, resume });\n\n console.log(chalk.green(`✓ Checkpoint saved: \"${checkpoint}\"`));\n if (resume) {\n console.log(chalk.dim(` Resume point: \"${resume}\"`));\n }\n break;\n }\n\n case 'summary': {\n // Add a work summary\n const title = arg1 || 'Work Session';\n\n // Read summary from stdin or prompt\n const summary = {\n title,\n completedAt: new Date().toISOString(),\n whatWasDone: ['Completed assigned work'],\n };\n\n appendSummary(agentId, summary);\n logHistory(agentId, 'context:summary', { title });\n\n console.log(chalk.green(`✓ Summary added: \"${title}\"`));\n break;\n }\n\n case 'history': {\n // Search or show history\n const pattern = arg1;\n\n if (pattern) {\n const results = searchHistory(agentId, pattern);\n if (results.length === 0) {\n console.log(chalk.dim('No matches found.'));\n return;\n }\n\n console.log(chalk.bold(`\\nHistory matches for \"${pattern}\":\\n`));\n for (const line of results.slice(0, 50)) {\n console.log(line);\n }\n } else {\n const recent = getRecentHistory(agentId, 20);\n if (recent.length === 0) {\n console.log(chalk.dim('No history yet.'));\n return;\n }\n\n console.log(chalk.bold('\\nRecent History:\\n'));\n for (const line of recent) {\n console.log(line);\n }\n }\n console.log('');\n break;\n }\n\n case 'materialize': {\n // List or read materialized outputs\n const filepath = arg1;\n\n if (filepath && existsSync(filepath)) {\n const content = readMaterialized(filepath);\n if (content) {\n console.log(content);\n }\n return;\n }\n\n const outputs = listMaterialized(agentId);\n if (outputs.length === 0) {\n console.log(chalk.dim('No materialized outputs.'));\n return;\n }\n\n console.log(chalk.bold('\\nMaterialized Outputs:\\n'));\n for (const out of outputs) {\n const date = new Date(out.timestamp).toLocaleString();\n console.log(` ${chalk.cyan(out.tool)} ${chalk.dim(date)}`);\n console.log(` ${chalk.dim(out.file)}`);\n }\n console.log('');\n break;\n }\n\n case 'tokens': {\n // Estimate tokens for a file or text\n const target = arg1;\n\n if (!target) {\n console.log(chalk.dim('Usage: pan work context tokens <file-or-text>'));\n return;\n }\n\n let text = target;\n if (existsSync(target)) {\n text = readFileSync(target, 'utf-8');\n }\n\n const tokens = estimateTokens(text);\n console.log(`Estimated tokens: ${chalk.cyan(tokens.toLocaleString())}`);\n break;\n }\n\n default:\n console.log(chalk.bold('Context Commands:'));\n console.log('');\n console.log(` ${chalk.cyan('pan work context state [agent-id]')} - Show current state`);\n console.log(` ${chalk.cyan('pan work context init <agent> <issue>')} - Initialize state`);\n console.log(` ${chalk.cyan('pan work context checkpoint \"msg\"')} - Save checkpoint`);\n console.log(` ${chalk.cyan('pan work context summary [title]')} - Add work summary`);\n console.log(` ${chalk.cyan('pan work context history [pattern]')} - Search history`);\n console.log(` ${chalk.cyan('pan work context materialize [file]')} - List/read outputs`);\n console.log(` ${chalk.cyan('pan work context tokens <file>')} - Estimate token count`);\n console.log('');\n }\n}\n","/**\n * Context Engineering System\n *\n * Implements GSD-Plus patterns for structured context management:\n * - STATE.md: Agent state that survives compaction\n * - WORKSPACE.md: Project context\n * - SUMMARY.md: Work artifacts\n * - Queryable history files\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from 'fs';\nimport { join, basename } from 'path';\nimport { AGENTS_DIR } from './paths.js';\n\nexport interface AgentStateContext {\n issueId: string;\n status: string;\n lastActivity: string;\n lastCheckpoint?: string;\n resumePoint?: string;\n contextRefs: {\n workspace?: string;\n prd?: string;\n beads?: string;\n };\n}\n\nexport interface WorkspaceMdContext {\n projectName: string;\n branch: string;\n issueId: string;\n description: string;\n constraints: string[];\n activeWork: string[];\n}\n\nexport interface SummaryEntry {\n title: string;\n completedAt: string;\n duration?: number;\n whatWasDone: string[];\n keyInsights?: string[];\n filesModified?: string[];\n}\n\n// ============== STATE.md ==============\n\nfunction getStateFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'STATE.md');\n}\n\n/**\n * Read current STATE.md for an agent\n */\nexport function readAgentState(agentId: string): AgentStateContext | null {\n const stateFile = getStateFile(agentId);\n if (!existsSync(stateFile)) return null;\n\n try {\n const content = readFileSync(stateFile, 'utf-8');\n return parseStateMd(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Write STATE.md for an agent\n */\nexport function writeAgentState(agentId: string, state: AgentStateContext): void {\n const dir = join(AGENTS_DIR, agentId);\n mkdirSync(dir, { recursive: true });\n\n const content = generateStateMd(state);\n writeFileSync(getStateFile(agentId), content);\n}\n\n/**\n * Update checkpoint in STATE.md\n */\nexport function updateCheckpoint(agentId: string, checkpoint: string, resumePoint?: string): void {\n const state = readAgentState(agentId);\n if (!state) return;\n\n state.lastActivity = new Date().toISOString();\n state.lastCheckpoint = checkpoint;\n if (resumePoint) {\n state.resumePoint = resumePoint;\n }\n\n writeAgentState(agentId, state);\n}\n\nfunction generateStateMd(state: AgentStateContext): string {\n const lines: string[] = [\n `# Agent State: ${state.issueId}`,\n '',\n '## Current Position',\n '',\n `Issue: ${state.issueId}`,\n `Status: ${state.status}`,\n `Last activity: ${state.lastActivity}`,\n '',\n ];\n\n if (state.lastCheckpoint) {\n lines.push('## Session Continuity');\n lines.push('');\n lines.push(`Last checkpoint: \"${state.lastCheckpoint}\"`);\n if (state.resumePoint) {\n lines.push(`Resume point: \"${state.resumePoint}\"`);\n }\n lines.push('');\n }\n\n if (state.contextRefs.workspace || state.contextRefs.prd || state.contextRefs.beads) {\n lines.push('## Context References');\n lines.push('');\n if (state.contextRefs.workspace) {\n lines.push(`- Workspace: ${state.contextRefs.workspace}`);\n }\n if (state.contextRefs.prd) {\n lines.push(`- PRD: ${state.contextRefs.prd}`);\n }\n if (state.contextRefs.beads) {\n lines.push(`- Beads: ${state.contextRefs.beads}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction parseStateMd(content: string): AgentStateContext {\n const state: AgentStateContext = {\n issueId: '',\n status: '',\n lastActivity: '',\n contextRefs: {},\n };\n\n // Parse issue ID from title\n const titleMatch = content.match(/# Agent State: (.+)/);\n if (titleMatch) state.issueId = titleMatch[1].trim();\n\n // Parse status\n const statusMatch = content.match(/Status: (.+)/);\n if (statusMatch) state.status = statusMatch[1].trim();\n\n // Parse last activity\n const activityMatch = content.match(/Last activity: (.+)/);\n if (activityMatch) state.lastActivity = activityMatch[1].trim();\n\n // Parse checkpoint\n const checkpointMatch = content.match(/Last checkpoint: \"(.+)\"/);\n if (checkpointMatch) state.lastCheckpoint = checkpointMatch[1];\n\n // Parse resume point\n const resumeMatch = content.match(/Resume point: \"(.+)\"/);\n if (resumeMatch) state.resumePoint = resumeMatch[1];\n\n // Parse context refs\n const workspaceMatch = content.match(/- Workspace: (.+)/);\n if (workspaceMatch) state.contextRefs.workspace = workspaceMatch[1].trim();\n\n const prdMatch = content.match(/- PRD: (.+)/);\n if (prdMatch) state.contextRefs.prd = prdMatch[1].trim();\n\n const beadsMatch = content.match(/- Beads: (.+)/);\n if (beadsMatch) state.contextRefs.beads = beadsMatch[1].trim();\n\n return state;\n}\n\n// ============== WORKSPACE.md ==============\n\n/**\n * Generate WORKSPACE.md for a workspace\n */\nexport function generateWorkspaceMd(ctx: WorkspaceMdContext): string {\n const lines: string[] = [\n `# ${ctx.projectName}`,\n '',\n ctx.description,\n '',\n '## Core Value',\n '',\n `Working on ${ctx.issueId} to deliver requested functionality.`,\n '',\n '## Active Work',\n '',\n ];\n\n for (const work of ctx.activeWork) {\n lines.push(`- [ ] ${work}`);\n }\n\n lines.push('');\n lines.push('## Constraints');\n lines.push('');\n\n for (const constraint of ctx.constraints) {\n lines.push(`- ${constraint}`);\n }\n\n lines.push('');\n lines.push('## Context');\n lines.push('');\n lines.push(`- Branch: \\`${ctx.branch}\\``);\n lines.push(`- Issue: ${ctx.issueId}`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n// ============== SUMMARY.md ==============\n\nfunction getSummaryFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'SUMMARY.md');\n}\n\n/**\n * Append a work summary to SUMMARY.md\n */\nexport function appendSummary(agentId: string, summary: SummaryEntry): void {\n const dir = join(AGENTS_DIR, agentId);\n mkdirSync(dir, { recursive: true });\n\n const summaryFile = getSummaryFile(agentId);\n const content = generateSummaryEntry(summary);\n\n if (existsSync(summaryFile)) {\n appendFileSync(summaryFile, '\\n---\\n\\n' + content);\n } else {\n writeFileSync(summaryFile, '# Work Summaries\\n\\n' + content);\n }\n}\n\nfunction generateSummaryEntry(summary: SummaryEntry): string {\n const lines: string[] = [\n `## ${summary.title}`,\n '',\n `**Completed:** ${summary.completedAt}`,\n ];\n\n if (summary.duration) {\n lines.push(`**Duration:** ${summary.duration} minutes`);\n }\n\n lines.push('');\n lines.push('### What Was Done');\n lines.push('');\n\n for (let i = 0; i < summary.whatWasDone.length; i++) {\n lines.push(`${i + 1}. ${summary.whatWasDone[i]}`);\n }\n\n if (summary.keyInsights && summary.keyInsights.length > 0) {\n lines.push('');\n lines.push('### Key Insights');\n lines.push('');\n for (let i = 0; i < summary.keyInsights.length; i++) {\n lines.push(`${i + 1}. ${summary.keyInsights[i]}`);\n }\n }\n\n if (summary.filesModified && summary.filesModified.length > 0) {\n lines.push('');\n lines.push('### Files Modified');\n lines.push('');\n for (const file of summary.filesModified) {\n lines.push(`- ${file}`);\n }\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\n// ============== History Files ==============\n\nfunction getHistoryDir(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'history');\n}\n\n/**\n * Log an action to queryable history\n */\nexport function logHistory(\n agentId: string,\n action: string,\n details?: Record<string, any>\n): void {\n const historyDir = getHistoryDir(agentId);\n mkdirSync(historyDir, { recursive: true });\n\n const date = new Date();\n const dateStr = date.toISOString().split('T')[0];\n const historyFile = join(historyDir, `${dateStr}.log`);\n\n const timestamp = date.toISOString();\n const detailsStr = details ? ` ${JSON.stringify(details)}` : '';\n const logLine = `[${timestamp}] ${action}${detailsStr}\\n`;\n\n appendFileSync(historyFile, logLine);\n}\n\n/**\n * Search history files for a pattern\n */\nexport function searchHistory(agentId: string, pattern: string): string[] {\n const historyDir = getHistoryDir(agentId);\n if (!existsSync(historyDir)) return [];\n\n const results: string[] = [];\n const regex = new RegExp(pattern, 'i');\n\n const files = readdirSync(historyDir).filter((f) => f.endsWith('.log'));\n files.sort().reverse(); // Most recent first\n\n for (const file of files) {\n const content = readFileSync(join(historyDir, file), 'utf-8');\n const lines = content.split('\\n');\n\n for (const line of lines) {\n if (regex.test(line)) {\n results.push(line);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get recent history entries\n */\nexport function getRecentHistory(agentId: string, limit: number = 20): string[] {\n const historyDir = getHistoryDir(agentId);\n if (!existsSync(historyDir)) return [];\n\n const results: string[] = [];\n\n const files = readdirSync(historyDir).filter((f) => f.endsWith('.log'));\n files.sort().reverse(); // Most recent first\n\n for (const file of files) {\n if (results.length >= limit) break;\n\n const content = readFileSync(join(historyDir, file), 'utf-8');\n const lines = content.split('\\n').filter((l) => l.trim());\n\n for (const line of lines.reverse()) {\n if (results.length >= limit) break;\n results.push(line);\n }\n }\n\n return results;\n}\n\n// ============== Context Budget ==============\n\nexport interface ContextBudget {\n maxTokens: number;\n usedTokens: number;\n warningThreshold: number; // e.g., 0.8 = warn at 80%\n}\n\n/**\n * Estimate token count (rough approximation: ~4 chars per token)\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Check if context budget allows adding more content\n */\nexport function checkContextBudget(\n budget: ContextBudget,\n newContent: string\n): { allowed: boolean; warning: boolean; remaining: number } {\n const newTokens = estimateTokens(newContent);\n const totalUsed = budget.usedTokens + newTokens;\n const remaining = budget.maxTokens - totalUsed;\n const usageRatio = totalUsed / budget.maxTokens;\n\n return {\n allowed: totalUsed <= budget.maxTokens,\n warning: usageRatio >= budget.warningThreshold,\n remaining,\n };\n}\n\n/**\n * Create a context budget for a session\n */\nexport function createContextBudget(maxTokens: number = 100000): ContextBudget {\n return {\n maxTokens,\n usedTokens: 0,\n warningThreshold: 0.8,\n };\n}\n\n// ============== Context Materialization ==============\n\nfunction getMaterializedDir(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'materialized');\n}\n\n/**\n * Materialize tool output for later retrieval\n */\nexport function materializeOutput(\n agentId: string,\n toolName: string,\n output: string,\n metadata?: Record<string, any>\n): string {\n const dir = getMaterializedDir(agentId);\n mkdirSync(dir, { recursive: true });\n\n const timestamp = Date.now();\n const filename = `${toolName}-${timestamp}.md`;\n const filepath = join(dir, filename);\n\n const lines: string[] = [\n `# Tool Output: ${toolName}`,\n '',\n `**Timestamp:** ${new Date(timestamp).toISOString()}`,\n ];\n\n if (metadata) {\n for (const [key, value] of Object.entries(metadata)) {\n lines.push(`**${key}:** ${value}`);\n }\n }\n\n lines.push('');\n lines.push('## Output');\n lines.push('');\n lines.push('```');\n lines.push(output);\n lines.push('```');\n lines.push('');\n\n writeFileSync(filepath, lines.join('\\n'));\n\n // Log to history\n logHistory(agentId, `materialized:${toolName}`, { file: filename });\n\n return filepath;\n}\n\n/**\n * List materialized outputs for an agent\n */\nexport function listMaterialized(agentId: string): Array<{\n tool: string;\n timestamp: number;\n file: string;\n}> {\n const dir = getMaterializedDir(agentId);\n if (!existsSync(dir)) return [];\n\n return readdirSync(dir)\n .filter((f) => f.endsWith('.md'))\n .map((f) => {\n const match = f.match(/^(.+)-(\\d+)\\.md$/);\n if (!match) return null;\n return {\n tool: match[1],\n timestamp: parseInt(match[2], 10),\n file: join(dir, f),\n };\n })\n .filter(Boolean) as Array<{ tool: string; timestamp: number; file: string }>;\n}\n\n/**\n * Read materialized output\n */\nexport function readMaterialized(filepath: string): string | null {\n if (!existsSync(filepath)) return null;\n return readFileSync(filepath, 'utf-8');\n}\n","import chalk from 'chalk';\nimport {\n getAgentHealth,\n pingAgent,\n handleStuckAgent,\n runHealthCheck,\n startHealthDaemon,\n formatHealthStatus,\n DEFAULT_PING_TIMEOUT_MS,\n DEFAULT_CONSECUTIVE_FAILURES,\n DEFAULT_COOLDOWN_MS,\n DEFAULT_CHECK_INTERVAL_MS,\n type HealthConfig,\n} from '../../../lib/health.js';\nimport { listRunningAgents } from '../../../lib/agents.js';\n\ninterface HealthOptions {\n json?: boolean;\n daemon?: boolean;\n interval?: number;\n}\n\nexport async function healthCommand(\n action?: string,\n arg?: string,\n options: HealthOptions = {}\n): Promise<void> {\n const config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: options.interval ? options.interval * 1000 : DEFAULT_CHECK_INTERVAL_MS,\n };\n\n switch (action) {\n case 'check': {\n // Run a single health check\n console.log(chalk.bold('Running health check...\\n'));\n\n const results = await runHealthCheck(config);\n\n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n\n console.log(`Checked: ${results.checked} agents`);\n console.log(` ${chalk.green('\\u2705 Healthy:')} ${results.healthy}`);\n console.log(` ${chalk.yellow('\\u26a0\\ufe0f Warning:')} ${results.warning}`);\n console.log(` ${chalk.hex('#FFA500')('\\u{1f7e0} Stuck:')} ${results.stuck}`);\n console.log(` ${chalk.red('\\u274c Dead:')} ${results.dead}`);\n\n if (results.recovered.length > 0) {\n console.log('');\n console.log(chalk.green('Recovered agents:'));\n for (const agentId of results.recovered) {\n console.log(` - ${agentId}`);\n }\n }\n break;\n }\n\n case 'status': {\n // Show health status of all agents\n const agents = listRunningAgents();\n\n if (agents.length === 0) {\n console.log(chalk.dim('No agents found.'));\n return;\n }\n\n const healthData = agents.map((agent) => {\n const health = getAgentHealth(agent.id);\n return { agent, health };\n });\n\n if (options.json) {\n console.log(JSON.stringify(healthData.map((d) => d.health), null, 2));\n return;\n }\n\n console.log(chalk.bold('Agent Health Status:\\n'));\n\n for (const { health } of healthData) {\n console.log(formatHealthStatus(health));\n console.log('');\n }\n break;\n }\n\n case 'ping': {\n // Ping a specific agent\n if (!arg) {\n console.log(chalk.red('Agent ID required'));\n console.log(chalk.dim('Usage: pan work health ping <agent-id>'));\n return;\n }\n\n const agentId = arg.startsWith('agent-') ? arg : `agent-${arg.toLowerCase()}`;\n console.log(chalk.dim(`Pinging ${agentId}...`));\n\n const health = pingAgent(agentId, config);\n\n if (options.json) {\n console.log(JSON.stringify(health, null, 2));\n return;\n }\n\n console.log('');\n console.log(formatHealthStatus(health));\n break;\n }\n\n case 'recover': {\n // Force recovery of a specific agent\n if (!arg) {\n console.log(chalk.red('Agent ID required'));\n console.log(chalk.dim('Usage: pan work health recover <agent-id>'));\n return;\n }\n\n const agentId = arg.startsWith('agent-') ? arg : `agent-${arg.toLowerCase()}`;\n console.log(chalk.dim(`Attempting recovery of ${agentId}...`));\n\n // Override config to allow immediate recovery\n const forceConfig = { ...config, consecutiveFailures: 0 };\n const result = await handleStuckAgent(agentId, forceConfig);\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (result.action === 'recovered') {\n console.log(chalk.green(`\\u2705 ${result.reason}`));\n } else if (result.action === 'cooldown') {\n console.log(chalk.yellow(`\\u26a0\\ufe0f ${result.reason}`));\n } else {\n console.log(chalk.dim(result.reason));\n }\n break;\n }\n\n case 'daemon': {\n // Start the health monitoring daemon\n console.log(chalk.bold('Starting Panopticon Health Daemon'));\n console.log(chalk.dim(`Check interval: ${config.checkIntervalMs / 1000}s`));\n console.log(chalk.dim(`Failure threshold: ${config.consecutiveFailures}`));\n console.log(chalk.dim(`Cooldown: ${config.cooldownMs / (1000 * 60)}m`));\n console.log('');\n console.log(chalk.dim('Press Ctrl+C to stop...\\n'));\n\n const stop = startHealthDaemon(config, (results) => {\n const timestamp = new Date().toLocaleTimeString();\n const statusParts = [\n `[${timestamp}]`,\n `\\u2705${results.healthy}`,\n `\\u26a0\\ufe0f${results.warning}`,\n `\\u{1f7e0}${results.stuck}`,\n `\\u274c${results.dead}`,\n ];\n\n if (results.recovered.length > 0) {\n statusParts.push(chalk.green(`+${results.recovered.length} recovered`));\n }\n\n console.log(statusParts.join(' '));\n });\n\n // Handle graceful shutdown\n process.on('SIGINT', () => {\n console.log('\\n' + chalk.dim('Stopping health daemon...'));\n stop();\n process.exit(0);\n });\n\n // Keep process running\n await new Promise(() => {});\n break;\n }\n\n default:\n console.log(chalk.bold('Health Monitoring Commands:'));\n console.log('');\n console.log(` ${chalk.cyan('pan work health check')} - Run single health check`);\n console.log(` ${chalk.cyan('pan work health status')} - Show all agent health`);\n console.log(` ${chalk.cyan('pan work health ping <id>')} - Ping specific agent`);\n console.log(` ${chalk.cyan('pan work health recover <id>')} - Force recover agent`);\n console.log(` ${chalk.cyan('pan work health daemon')} - Start health daemon`);\n console.log('');\n console.log(chalk.bold('Options:'));\n console.log(` ${chalk.dim('--json')} Output as JSON`);\n console.log(` ${chalk.dim('--interval <sec>')} Check interval for daemon (default: 30)`);\n console.log('');\n console.log(chalk.bold('Deacon Pattern Defaults:'));\n console.log(` Ping timeout: ${DEFAULT_PING_TIMEOUT_MS / 1000}s`);\n console.log(` Consecutive failures: ${DEFAULT_CONSECUTIVE_FAILURES}`);\n console.log(` Cooldown after kill: ${DEFAULT_COOLDOWN_MS / (1000 * 60)}m`);\n console.log('');\n }\n}\n","/**\n * Health Monitoring System (Deacon Pattern)\n *\n * Implements stuck detection and auto-recovery with cooldown:\n * - Default ping timeout: 30 seconds\n * - Default consecutive failures: 3\n * - Default cooldown: 5 minutes\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { AGENTS_DIR } from './paths.js';\nimport { recoverAgent, stopAgent, getAgentState } from './agents.js';\n\n// Deacon pattern defaults\nexport const DEFAULT_PING_TIMEOUT_MS = 30 * 1000; // 30 seconds\nexport const DEFAULT_CONSECUTIVE_FAILURES = 3;\nexport const DEFAULT_COOLDOWN_MS = 5 * 60 * 1000; // 5 minutes\nexport const DEFAULT_CHECK_INTERVAL_MS = 30 * 1000; // 30 seconds\n\nexport interface AgentHealth {\n agentId: string;\n status: 'healthy' | 'warning' | 'stuck' | 'dead';\n lastActivity?: string;\n lastPing?: string;\n lastPingResponse?: string;\n consecutiveFailures: number;\n lastForceKill?: string;\n forceKillCount: number;\n recoveryCount: number;\n inCooldown: boolean;\n}\n\nexport interface HealthConfig {\n pingTimeoutMs: number;\n consecutiveFailures: number;\n cooldownMs: number;\n checkIntervalMs: number;\n}\n\nfunction getHealthFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'health.json');\n}\n\n/**\n * Get or create health record for an agent\n */\nexport function getAgentHealth(agentId: string): AgentHealth {\n const healthFile = getHealthFile(agentId);\n\n const defaultHealth: AgentHealth = {\n agentId,\n status: 'healthy',\n consecutiveFailures: 0,\n forceKillCount: 0,\n recoveryCount: 0,\n inCooldown: false,\n };\n\n if (existsSync(healthFile)) {\n try {\n const stored = JSON.parse(readFileSync(healthFile, 'utf-8'));\n return { ...defaultHealth, ...stored };\n } catch {}\n }\n\n return defaultHealth;\n}\n\n/**\n * Save health record for an agent\n */\nexport function saveAgentHealth(health: AgentHealth): void {\n const dir = join(AGENTS_DIR, health.agentId);\n mkdirSync(dir, { recursive: true });\n writeFileSync(getHealthFile(health.agentId), JSON.stringify(health, null, 2));\n}\n\n/**\n * Check if agent's tmux session is alive\n */\nexport function isAgentAlive(agentId: string): boolean {\n try {\n execSync(`tmux has-session -t \"${agentId}\" 2>/dev/null`, { encoding: 'utf-8' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get recent output from agent's terminal\n */\nexport function getAgentOutput(agentId: string, lines: number = 20): string | null {\n try {\n const output = execSync(\n `tmux capture-pane -t \"${agentId}\" -p -S -${lines} 2>/dev/null`,\n { encoding: 'utf-8', maxBuffer: 1024 * 1024 }\n );\n return output.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Send a health check nudge to the agent\n * Returns true if we detect activity, false otherwise\n */\nexport function sendHealthNudge(agentId: string): boolean {\n if (!isAgentAlive(agentId)) {\n return false;\n }\n\n // Capture output before nudge\n const outputBefore = getAgentOutput(agentId, 5);\n\n // Send a gentle nudge - just check if the session is responsive\n // We don't want to interrupt actual work, just verify the session exists\n try {\n // Check if there's been any recent output change\n // For now, we consider alive = responsive\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Ping an agent and update health status\n */\nexport function pingAgent(\n agentId: string,\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n }\n): AgentHealth {\n const health = getAgentHealth(agentId);\n health.lastPing = new Date().toISOString();\n\n // Check if session is alive\n const alive = isAgentAlive(agentId);\n\n if (!alive) {\n // Session is dead\n health.status = 'dead';\n health.consecutiveFailures++;\n } else {\n // Session is alive - check for activity\n const state = getAgentState(agentId);\n const lastActivity = state?.lastActivity ? new Date(state.lastActivity) : null;\n\n if (lastActivity) {\n const ageMs = Date.now() - lastActivity.getTime();\n const ageMinutes = ageMs / (1000 * 60);\n\n if (ageMinutes > 30) {\n health.status = 'stuck';\n health.consecutiveFailures++;\n } else if (ageMinutes > 15) {\n health.status = 'warning';\n // Don't increment failures for warning, just monitor\n } else {\n health.status = 'healthy';\n health.consecutiveFailures = 0;\n }\n } else {\n // No activity tracking, assume healthy if alive\n health.status = 'healthy';\n health.consecutiveFailures = 0;\n }\n\n health.lastPingResponse = new Date().toISOString();\n }\n\n // Check cooldown status\n if (health.lastForceKill) {\n const timeSinceKill = Date.now() - new Date(health.lastForceKill).getTime();\n health.inCooldown = timeSinceKill < config.cooldownMs;\n } else {\n health.inCooldown = false;\n }\n\n saveAgentHealth(health);\n return health;\n}\n\n/**\n * Handle a stuck agent - force kill and respawn with context\n */\nexport async function handleStuckAgent(\n agentId: string,\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n }\n): Promise<{ action: 'recovered' | 'cooldown' | 'skipped'; reason: string }> {\n const health = getAgentHealth(agentId);\n\n // Check if failures meet threshold\n if (health.consecutiveFailures < config.consecutiveFailures) {\n return {\n action: 'skipped',\n reason: `Only ${health.consecutiveFailures} failures (need ${config.consecutiveFailures})`,\n };\n }\n\n // Check cooldown\n if (health.lastForceKill) {\n const timeSinceKill = Date.now() - new Date(health.lastForceKill).getTime();\n if (timeSinceKill < config.cooldownMs) {\n const remainingMs = config.cooldownMs - timeSinceKill;\n const remainingMin = Math.ceil(remainingMs / (1000 * 60));\n return {\n action: 'cooldown',\n reason: `In cooldown (${remainingMin}m remaining)`,\n };\n }\n }\n\n // Force kill the agent\n try {\n stopAgent(agentId);\n } catch {}\n\n // Record the force kill\n health.lastForceKill = new Date().toISOString();\n health.forceKillCount++;\n health.consecutiveFailures = 0;\n health.status = 'dead';\n health.inCooldown = true;\n saveAgentHealth(health);\n\n // Attempt recovery\n try {\n const recovered = recoverAgent(agentId);\n if (recovered) {\n health.status = 'healthy';\n health.recoveryCount++;\n saveAgentHealth(health);\n return { action: 'recovered', reason: 'Force killed and respawned' };\n }\n } catch {}\n\n return { action: 'recovered', reason: 'Force killed (respawn failed)' };\n}\n\n/**\n * Run a single health check cycle for all agents\n */\nexport async function runHealthCheck(\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n }\n): Promise<{\n checked: number;\n healthy: number;\n warning: number;\n stuck: number;\n dead: number;\n recovered: string[];\n}> {\n const results = {\n checked: 0,\n healthy: 0,\n warning: 0,\n stuck: 0,\n dead: 0,\n recovered: [] as string[],\n };\n\n // Get all agent sessions\n let sessions: string[] = [];\n try {\n const output = execSync(\n 'tmux list-sessions -F \"#{session_name}\" 2>/dev/null || true',\n { encoding: 'utf-8' }\n );\n sessions = output\n .trim()\n .split('\\n')\n .filter((s) => s.startsWith('agent-'));\n } catch {}\n\n // Also check agents dir for crashed agents\n if (existsSync(AGENTS_DIR)) {\n const { readdirSync } = await import('fs');\n const dirs = readdirSync(AGENTS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory() && d.name.startsWith('agent-'))\n .map((d) => d.name);\n\n for (const dir of dirs) {\n if (!sessions.includes(dir)) {\n sessions.push(dir);\n }\n }\n }\n\n // Check each agent\n for (const agentId of sessions) {\n results.checked++;\n\n const health = pingAgent(agentId, config);\n\n switch (health.status) {\n case 'healthy':\n results.healthy++;\n break;\n case 'warning':\n results.warning++;\n break;\n case 'stuck':\n results.stuck++;\n // Handle stuck agent\n const result = await handleStuckAgent(agentId, config);\n if (result.action === 'recovered') {\n results.recovered.push(agentId);\n }\n break;\n case 'dead':\n results.dead++;\n // Handle dead agent\n const deadResult = await handleStuckAgent(agentId, config);\n if (deadResult.action === 'recovered') {\n results.recovered.push(agentId);\n }\n break;\n }\n }\n\n return results;\n}\n\n/**\n * Start the health monitoring daemon\n * Returns a stop function\n */\nexport function startHealthDaemon(\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n },\n onCheck?: (results: Awaited<ReturnType<typeof runHealthCheck>>) => void\n): () => void {\n let running = true;\n\n const runLoop = async () => {\n while (running) {\n try {\n const results = await runHealthCheck(config);\n if (onCheck) {\n onCheck(results);\n }\n } catch (error) {\n console.error('Health check error:', error);\n }\n\n // Wait for next interval\n await new Promise((resolve) => setTimeout(resolve, config.checkIntervalMs));\n }\n };\n\n // Start the loop\n runLoop();\n\n // Return stop function\n return () => {\n running = false;\n };\n}\n\n/**\n * Format health status for display\n */\nexport function formatHealthStatus(health: AgentHealth): string {\n const statusIcons = {\n healthy: '\\u2705',\n warning: '\\u26a0\\ufe0f',\n stuck: '\\u{1f7e0}',\n dead: '\\u274c',\n };\n\n const lines: string[] = [\n `${statusIcons[health.status]} ${health.agentId}: ${health.status.toUpperCase()}`,\n ];\n\n if (health.lastPing) {\n lines.push(` Last ping: ${health.lastPing}`);\n }\n\n if (health.consecutiveFailures > 0) {\n lines.push(` Consecutive failures: ${health.consecutiveFailures}`);\n }\n\n if (health.forceKillCount > 0) {\n lines.push(` Force kills: ${health.forceKillCount}`);\n }\n\n if (health.recoveryCount > 0) {\n lines.push(` Recoveries: ${health.recoveryCount}`);\n }\n\n if (health.inCooldown) {\n lines.push(` Status: IN COOLDOWN`);\n }\n\n return lines.join('\\n');\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { join, basename } from 'path';\nimport { createWorktree, removeWorktree, listWorktrees } from '../../lib/worktree.js';\nimport { generateClaudeMd, TemplateVariables } from '../../lib/template.js';\nimport { mergeSkillsIntoWorkspace } from '../../lib/skills-merge.js';\nimport {\n resolveProjectFromIssue,\n hasProjects,\n PROJECTS_CONFIG_FILE,\n} from '../../lib/projects.js';\n\nexport function registerWorkspaceCommands(program: Command): void {\n const workspace = program.command('workspace').description('Workspace management');\n\n workspace\n .command('create <issueId>')\n .description('Create workspace for issue')\n .option('--dry-run', 'Show what would be created')\n .option('--no-skills', 'Skip skills symlink setup')\n .option('--labels <labels>', 'Comma-separated labels for routing (e.g., docs,marketing)')\n .option('--project <path>', 'Explicit project path (overrides registry)')\n .action(createCommand);\n\n workspace\n .command('list')\n .description('List all workspaces')\n .option('--json', 'Output as JSON')\n .option('--all', 'List workspaces across all registered projects')\n .action(listCommand);\n\n workspace\n .command('destroy <issueId>')\n .description('Destroy workspace')\n .option('--force', 'Force removal even with uncommitted changes')\n .option('--project <path>', 'Explicit project path (overrides registry)')\n .action(destroyCommand);\n}\n\ninterface CreateOptions {\n dryRun?: boolean;\n skills?: boolean;\n labels?: string;\n project?: string;\n}\n\nasync function createCommand(issueId: string, options: CreateOptions): Promise<void> {\n const spinner = ora('Creating workspace...').start();\n\n try {\n // Normalize issue ID (e.g., MIN-123 -> min-123)\n const normalizedId = issueId.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n const branchName = `feature/${normalizedId}`;\n const folderName = `feature-${normalizedId}`;\n\n // Parse labels if provided\n const labels = options.labels\n ? options.labels.split(',').map((l) => l.trim())\n : [];\n\n // Resolve project root - try registry first, fall back to cwd\n let projectRoot: string;\n let projectName: string | undefined;\n\n if (options.project) {\n // Explicit project path provided\n projectRoot = options.project;\n } else {\n // Try to resolve from project registry\n const resolved = resolveProjectFromIssue(issueId, labels);\n if (resolved) {\n projectRoot = resolved.projectPath;\n projectName = resolved.projectName;\n spinner.text = `Resolved project: ${projectName} (${projectRoot})`;\n } else if (hasProjects()) {\n // Registry exists but no match found - warn user\n spinner.warn(`No project found for ${issueId} in registry. Using current directory.`);\n spinner.start('Creating workspace...');\n projectRoot = process.cwd();\n } else {\n // No registry - use cwd (backward compatible)\n projectRoot = process.cwd();\n }\n }\n\n const workspacesDir = join(projectRoot, 'workspaces');\n const workspacePath = join(workspacesDir, folderName);\n\n if (options.dryRun) {\n spinner.info('Dry run mode');\n console.log('');\n console.log(chalk.bold('Would create:'));\n if (projectName) {\n console.log(` Project: ${chalk.green(projectName)}`);\n }\n console.log(` Root: ${chalk.dim(projectRoot)}`);\n console.log(` Workspace: ${chalk.cyan(workspacePath)}`);\n console.log(` Branch: ${chalk.cyan(branchName)}`);\n console.log(` CLAUDE.md: ${chalk.dim(join(workspacePath, 'CLAUDE.md'))}`);\n if (options.skills !== false) {\n console.log(` Skills: ${chalk.dim(join(workspacePath, '.claude', 'skills'))}`);\n }\n return;\n }\n\n // Check if already exists\n if (existsSync(workspacePath)) {\n spinner.fail(`Workspace already exists: ${workspacePath}`);\n process.exit(1);\n }\n\n // Check if we're in a git repo\n if (!existsSync(join(projectRoot, '.git'))) {\n spinner.fail('Not a git repository. Run this from the project root.');\n process.exit(1);\n }\n\n // Create worktree\n spinner.text = 'Creating git worktree...';\n createWorktree(projectRoot, workspacePath, branchName);\n\n // Generate CLAUDE.md\n spinner.text = 'Generating CLAUDE.md...';\n const variables: TemplateVariables = {\n FEATURE_FOLDER: folderName,\n BRANCH_NAME: branchName,\n ISSUE_ID: issueId.toUpperCase(),\n WORKSPACE_PATH: workspacePath,\n FRONTEND_URL: `https://${folderName}.localhost:3000`,\n API_URL: `https://api-${folderName}.localhost:8080`,\n PROJECT_NAME: projectName,\n };\n\n const claudeMd = generateClaudeMd(projectRoot, variables);\n writeFileSync(join(workspacePath, 'CLAUDE.md'), claudeMd);\n\n // Merge skills (unless disabled)\n let skillsResult = { added: [] as string[], skipped: [] as string[] };\n if (options.skills !== false) {\n spinner.text = 'Merging skills...';\n mkdirSync(join(workspacePath, '.claude', 'skills'), { recursive: true });\n skillsResult = mergeSkillsIntoWorkspace(workspacePath);\n }\n\n spinner.succeed('Workspace created!');\n\n console.log('');\n console.log(chalk.bold('Workspace Details:'));\n if (projectName) {\n console.log(` Project: ${chalk.green(projectName)}`);\n }\n console.log(` Path: ${chalk.cyan(workspacePath)}`);\n console.log(` Branch: ${chalk.dim(branchName)}`);\n console.log('');\n\n if (options.skills !== false) {\n console.log(chalk.bold('Skills:'));\n console.log(` Added: ${skillsResult.added.length} Panopticon skills`);\n if (skillsResult.skipped.length > 0) {\n console.log(` Skipped: ${chalk.dim(skillsResult.skipped.join(', '))}`);\n }\n console.log('');\n }\n\n console.log(chalk.dim(`Next: cd ${workspacePath}`));\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n\ninterface ListOptions {\n json?: boolean;\n all?: boolean;\n}\n\nasync function listCommand(options: ListOptions): Promise<void> {\n const { listProjects } = await import('../../lib/projects.js');\n const projects = listProjects();\n\n // If we have registered projects and --all is specified, list across all projects\n if (projects.length > 0 && options.all) {\n const allWorkspaces: Array<{\n projectName: string;\n projectPath: string;\n workspaces: ReturnType<typeof listWorktrees>;\n }> = [];\n\n for (const { key, config } of projects) {\n if (!existsSync(join(config.path, '.git'))) {\n continue;\n }\n\n const worktrees = listWorktrees(config.path);\n const workspaces = worktrees.filter(\n (w) => w.path.includes('/workspaces/') || w.path.includes('\\\\workspaces\\\\')\n );\n\n if (workspaces.length > 0) {\n allWorkspaces.push({\n projectName: config.name,\n projectPath: config.path,\n workspaces,\n });\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(allWorkspaces, null, 2));\n return;\n }\n\n if (allWorkspaces.length === 0) {\n console.log(chalk.dim('No workspaces found in any registered project.'));\n console.log(chalk.dim('Create one with: pan workspace create <issue-id>'));\n return;\n }\n\n for (const proj of allWorkspaces) {\n console.log(chalk.bold(`\\n${proj.projectName}\\n`));\n for (const ws of proj.workspaces) {\n const name = basename(ws.path);\n const status = ws.prunable ? chalk.yellow(' (prunable)') : '';\n console.log(` ${chalk.cyan(name)}${status}`);\n console.log(` Branch: ${ws.branch || chalk.dim('(detached)')}`);\n console.log(` Path: ${chalk.dim(ws.path)}`);\n }\n }\n return;\n }\n\n // Default behavior: list from current directory\n const projectRoot = process.cwd();\n\n // Check if we're in a git repo\n if (!existsSync(join(projectRoot, '.git'))) {\n console.error(chalk.red('Not a git repository.'));\n if (projects.length > 0) {\n console.log(chalk.dim('Tip: Use --all to list workspaces across all registered projects.'));\n }\n process.exit(1);\n }\n\n const worktrees = listWorktrees(projectRoot);\n\n // Filter to workspaces directory only\n const workspaces = worktrees.filter((w) =>\n w.path.includes('/workspaces/') || w.path.includes('\\\\workspaces\\\\')\n );\n\n if (options.json) {\n console.log(JSON.stringify(workspaces, null, 2));\n return;\n }\n\n if (workspaces.length === 0) {\n console.log(chalk.dim('No workspaces found.'));\n console.log(chalk.dim('Create one with: pan workspace create <issue-id>'));\n if (projects.length > 0) {\n console.log(chalk.dim('Tip: Use --all to list workspaces across all registered projects.'));\n }\n return;\n }\n\n console.log(chalk.bold('\\nWorkspaces\\n'));\n\n for (const ws of workspaces) {\n const name = basename(ws.path);\n const status = ws.prunable ? chalk.yellow(' (prunable)') : '';\n console.log(`${chalk.cyan(name)}${status}`);\n console.log(` Branch: ${ws.branch || chalk.dim('(detached)')}`);\n console.log(` Path: ${chalk.dim(ws.path)}`);\n console.log('');\n }\n}\n\ninterface DestroyOptions {\n force?: boolean;\n project?: string;\n}\n\nasync function destroyCommand(issueId: string, options: DestroyOptions): Promise<void> {\n const spinner = ora('Destroying workspace...').start();\n\n try {\n const normalizedId = issueId.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n const folderName = `feature-${normalizedId}`;\n\n // Resolve project root - try registry first, then explicit option, then cwd\n let projectRoot: string;\n\n if (options.project) {\n projectRoot = options.project;\n } else {\n // Try to resolve from project registry\n const resolved = resolveProjectFromIssue(issueId);\n if (resolved) {\n projectRoot = resolved.projectPath;\n } else {\n projectRoot = process.cwd();\n }\n }\n\n const workspacePath = join(projectRoot, 'workspaces', folderName);\n\n if (!existsSync(workspacePath)) {\n // If not found and we resolved from registry, also check cwd\n const cwdPath = join(process.cwd(), 'workspaces', folderName);\n if (projectRoot !== process.cwd() && existsSync(cwdPath)) {\n projectRoot = process.cwd();\n } else {\n spinner.fail(`Workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n }\n\n const finalWorkspacePath = join(projectRoot, 'workspaces', folderName);\n\n spinner.text = 'Removing git worktree...';\n removeWorktree(projectRoot, finalWorkspacePath);\n\n spinner.succeed(`Workspace destroyed: ${folderName}`);\n } catch (error: any) {\n spinner.fail(error.message);\n if (!options.force) {\n console.log(chalk.dim('Tip: Use --force to remove even with uncommitted changes'));\n }\n process.exit(1);\n }\n}\n","import { execSync } from 'child_process';\nimport { mkdirSync } from 'fs';\nimport { dirname } from 'path';\n\nexport interface WorktreeInfo {\n path: string;\n branch: string;\n head: string;\n prunable: boolean;\n}\n\nexport function listWorktrees(repoPath: string): WorktreeInfo[] {\n const output = execSync('git worktree list --porcelain', {\n cwd: repoPath,\n encoding: 'utf8',\n });\n\n const worktrees: WorktreeInfo[] = [];\n let current: Partial<WorktreeInfo> = {};\n\n for (const line of output.split('\\n')) {\n if (line.startsWith('worktree ')) {\n if (current.path) worktrees.push(current as WorktreeInfo);\n current = { path: line.slice(9), prunable: false };\n } else if (line.startsWith('HEAD ')) {\n current.head = line.slice(5);\n } else if (line.startsWith('branch ')) {\n current.branch = line.slice(7).replace('refs/heads/', '');\n } else if (line === 'prunable') {\n current.prunable = true;\n }\n }\n if (current.path) worktrees.push(current as WorktreeInfo);\n\n return worktrees;\n}\n\nexport function createWorktree(\n repoPath: string,\n targetPath: string,\n branchName: string\n): void {\n // Ensure parent directory exists\n mkdirSync(dirname(targetPath), { recursive: true });\n\n // Check if branch exists\n try {\n execSync(`git show-ref --verify --quiet refs/heads/${branchName}`, {\n cwd: repoPath,\n });\n // Branch exists, just add worktree\n execSync(`git worktree add \"${targetPath}\" \"${branchName}\"`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n } catch {\n // Branch doesn't exist, create it\n execSync(`git worktree add -b \"${branchName}\" \"${targetPath}\"`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n }\n}\n\nexport function removeWorktree(repoPath: string, worktreePath: string): void {\n execSync(`git worktree remove \"${worktreePath}\" --force`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n}\n\nexport function pruneWorktrees(repoPath: string): void {\n execSync('git worktree prune', { cwd: repoPath, stdio: 'pipe' });\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { CLAUDE_MD_TEMPLATES } from './paths.js';\n\nexport interface TemplateVariables {\n FEATURE_FOLDER: string;\n BRANCH_NAME: string;\n ISSUE_ID: string;\n WORKSPACE_PATH: string;\n FRONTEND_URL?: string;\n API_URL?: string;\n PROJECT_NAME?: string;\n PROJECT_DOMAIN?: string;\n [key: string]: string | undefined;\n}\n\nexport function loadTemplate(templatePath: string): string {\n if (!existsSync(templatePath)) {\n throw new Error(`Template not found: ${templatePath}`);\n }\n return readFileSync(templatePath, 'utf8');\n}\n\nexport function substituteVariables(\n template: string,\n variables: TemplateVariables\n): string {\n let result = template;\n\n for (const [key, value] of Object.entries(variables)) {\n if (value !== undefined) {\n // Replace {{KEY}} and ${KEY} patterns\n result = result.replace(new RegExp(`\\\\{\\\\{${key}\\\\}\\\\}`, 'g'), value);\n result = result.replace(new RegExp(`\\\\$\\\\{${key}\\\\}`, 'g'), value);\n }\n }\n\n return result;\n}\n\nexport function generateClaudeMd(\n projectPath: string,\n variables: TemplateVariables\n): string {\n const sections: string[] = [];\n\n // Layer 1: Panopticon default sections\n const defaultOrder = [\n 'workspace-info.md',\n 'beads.md',\n 'commands-skills.md',\n 'warnings.md',\n ];\n\n for (const section of defaultOrder) {\n const sectionPath = join(CLAUDE_MD_TEMPLATES, section);\n if (existsSync(sectionPath)) {\n const content = loadTemplate(sectionPath);\n sections.push(substituteVariables(content, variables));\n }\n }\n\n // Layer 2: Project-specific sections\n const projectSections = join(projectPath, '.panopticon', 'claude-md', 'sections');\n if (existsSync(projectSections)) {\n const projectFiles = readdirSync(projectSections)\n .filter((f) => f.endsWith('.md'))\n .sort();\n\n for (const file of projectFiles) {\n const content = loadTemplate(join(projectSections, file));\n sections.push(substituteVariables(content, variables));\n }\n }\n\n // If no sections found, return minimal CLAUDE.md\n if (sections.length === 0) {\n return `# Workspace: ${variables.FEATURE_FOLDER}\n\n**Issue:** ${variables.ISSUE_ID}\n**Branch:** ${variables.BRANCH_NAME}\n**Path:** ${variables.WORKSPACE_PATH}\n\n## Getting Started\n\nThis workspace was created by Panopticon. Use \\`bd\\` commands to track your work.\n`;\n }\n\n return sections.join('\\n\\n---\\n\\n');\n}\n","import {\n existsSync,\n readdirSync,\n lstatSync,\n readlinkSync,\n symlinkSync,\n mkdirSync,\n appendFileSync,\n} from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { SKILLS_DIR } from './paths.js';\n\ntype ContentOrigin = 'git-tracked' | 'panopticon' | 'user-untracked';\n\nfunction detectContentOrigin(path: string, repoPath: string): ContentOrigin {\n try {\n const stat = lstatSync(path);\n\n // Check if symlink pointing to panopticon\n if (stat.isSymbolicLink()) {\n const target = readlinkSync(path);\n if (target.includes('.panopticon')) {\n return 'panopticon';\n }\n }\n\n // Check if git-tracked\n try {\n execSync(`git ls-files --error-unmatch \"${path}\" 2>/dev/null`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n return 'git-tracked';\n } catch {\n return 'user-untracked';\n }\n } catch {\n return 'user-untracked';\n }\n}\n\nexport function mergeSkillsIntoWorkspace(workspacePath: string): {\n added: string[];\n skipped: string[];\n} {\n const skillsTarget = join(workspacePath, '.claude', 'skills');\n const added: string[] = [];\n const skipped: string[] = [];\n\n // Ensure target directory exists\n mkdirSync(skillsTarget, { recursive: true });\n\n // Get existing skills in workspace\n const existingSkills = new Set<string>();\n if (existsSync(skillsTarget)) {\n for (const item of readdirSync(skillsTarget)) {\n existingSkills.add(item);\n }\n }\n\n // Get panopticon skills\n if (!existsSync(SKILLS_DIR)) return { added, skipped };\n\n const panopticonSkills = readdirSync(SKILLS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n for (const skill of panopticonSkills) {\n const targetPath = join(skillsTarget, skill);\n const sourcePath = join(SKILLS_DIR, skill);\n\n // Skip if exists and is git-tracked\n if (existingSkills.has(skill)) {\n const origin = detectContentOrigin(targetPath, workspacePath);\n if (origin === 'git-tracked') {\n skipped.push(`${skill} (git-tracked)`);\n continue;\n }\n if (origin === 'panopticon') {\n // Already ours, skip silently\n continue;\n }\n }\n\n // Create symlink\n try {\n symlinkSync(sourcePath, targetPath);\n added.push(skill);\n } catch (error: any) {\n if (error.code !== 'EEXIST') {\n // If exists but not symlink, skip\n skipped.push(`${skill} (exists)`);\n }\n }\n }\n\n // Update .gitignore if we added anything\n if (added.length > 0) {\n updateGitignore(skillsTarget, added);\n }\n\n return { added, skipped };\n}\n\nfunction updateGitignore(skillsDir: string, skills: string[]): void {\n const gitignorePath = join(skillsDir, '.gitignore');\n\n const content = `# Panopticon-managed symlinks (not committed)\n${skills.join('\\n')}\n`;\n\n try {\n appendFileSync(gitignorePath, content);\n } catch {\n // Ignore errors writing .gitignore\n }\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { execSync } from 'child_process';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { homedir, platform } from 'os';\nimport {\n PANOPTICON_HOME,\n INIT_DIRS,\n CERTS_DIR,\n TRAEFIK_DIR,\n TRAEFIK_DYNAMIC_DIR,\n TRAEFIK_CERTS_DIR,\n SOURCE_TRAEFIK_TEMPLATES\n} from '../../lib/paths.js';\nimport { getDefaultConfig, saveConfig } from '../../lib/config.js';\n\nexport function registerInstallCommand(program: Command): void {\n program\n .command('install')\n .description('Install Panopticon prerequisites')\n .option('--check', 'Check prerequisites only')\n .option('--minimal', 'Skip Traefik and mkcert (use port-based routing)')\n .option('--skip-mkcert', 'Skip mkcert/HTTPS setup')\n .option('--skip-docker', 'Skip Docker network setup')\n .action(installCommand);\n}\n\ninterface InstallOptions {\n check?: boolean;\n minimal?: boolean;\n skipMkcert?: boolean;\n skipDocker?: boolean;\n}\n\ninterface PrereqResult {\n name: string;\n passed: boolean;\n message: string;\n fix?: string;\n}\n\nfunction detectPlatform(): 'linux' | 'darwin' | 'win32' | 'wsl' {\n const os = platform();\n if (os === 'linux') {\n // Check for WSL\n try {\n const release = readFileSync('/proc/version', 'utf8').toLowerCase();\n if (release.includes('microsoft') || release.includes('wsl')) {\n return 'wsl';\n }\n } catch {}\n return 'linux';\n }\n return os as 'darwin' | 'win32';\n}\n\n/**\n * Recursively copy directory contents\n */\nfunction copyDirectoryRecursive(source: string, dest: string): void {\n if (!existsSync(source)) {\n throw new Error(`Source directory not found: ${source}`);\n }\n\n mkdirSync(dest, { recursive: true });\n\n const entries = readdirSync(source);\n for (const entry of entries) {\n const sourcePath = join(source, entry);\n const destPath = join(dest, entry);\n const stat = statSync(sourcePath);\n\n if (stat.isDirectory()) {\n copyDirectoryRecursive(sourcePath, destPath);\n } else {\n copyFileSync(sourcePath, destPath);\n }\n }\n}\n\nfunction checkCommand(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction checkPrerequisites(): { results: PrereqResult[]; allPassed: boolean } {\n const results: PrereqResult[] = [];\n\n // Node.js\n const nodeVersion = process.version;\n const nodeMajor = parseInt(nodeVersion.slice(1).split('.')[0]);\n results.push({\n name: 'Node.js',\n passed: nodeMajor >= 18,\n message: nodeMajor >= 18 ? `v${nodeVersion}` : `v${nodeVersion} (need v18+)`,\n fix: 'Install Node.js 18+ from https://nodejs.org',\n });\n\n // Git\n const hasGit = checkCommand('git');\n results.push({\n name: 'Git',\n passed: hasGit,\n message: hasGit ? 'installed' : 'not found',\n fix: 'Install git from your package manager',\n });\n\n // Docker\n const hasDocker = checkCommand('docker');\n let dockerRunning = false;\n if (hasDocker) {\n try {\n execSync('docker info', { stdio: 'pipe' });\n dockerRunning = true;\n } catch {}\n }\n results.push({\n name: 'Docker',\n passed: dockerRunning,\n message: dockerRunning ? 'running' : hasDocker ? 'not running' : 'not found',\n fix: hasDocker ? 'Start Docker Desktop or docker service' : 'Install Docker',\n });\n\n // tmux\n const hasTmux = checkCommand('tmux');\n results.push({\n name: 'tmux',\n passed: hasTmux,\n message: hasTmux ? 'installed' : 'not found',\n fix: 'apt install tmux / brew install tmux',\n });\n\n // mkcert (optional but recommended)\n const hasMkcert = checkCommand('mkcert');\n results.push({\n name: 'mkcert',\n passed: hasMkcert,\n message: hasMkcert ? 'installed' : 'not found (optional)',\n fix: 'brew install mkcert / apt install mkcert',\n });\n\n // Beads CLI\n const hasBeads = checkCommand('bd');\n results.push({\n name: 'Beads CLI (bd)',\n passed: hasBeads,\n message: hasBeads ? 'installed' : 'not found',\n fix: 'cargo install beads-cli',\n });\n\n // ttyd (web terminal for planning sessions)\n const hasTtyd = checkCommand('ttyd') || existsSync(join(homedir(), 'bin', 'ttyd'));\n results.push({\n name: 'ttyd',\n passed: hasTtyd,\n message: hasTtyd ? 'installed' : 'not found',\n fix: 'brew install ttyd / Download from https://github.com/tsl0922/ttyd/releases',\n });\n\n return {\n results,\n allPassed: results.filter((r) => r.name !== 'mkcert' && r.name !== 'ttyd').every((r) => r.passed),\n };\n}\n\nfunction printPrereqStatus(prereqs: { results: PrereqResult[]; allPassed: boolean }): void {\n console.log(chalk.bold('Prerequisites:\\n'));\n\n for (const result of prereqs.results) {\n const icon = result.passed ? chalk.green('✓') : chalk.red('✗');\n const msg = result.passed ? chalk.dim(result.message) : chalk.yellow(result.message);\n console.log(` ${icon} ${result.name}: ${msg}`);\n if (!result.passed && result.fix) {\n console.log(` ${chalk.dim('→ ' + result.fix)}`);\n }\n }\n console.log('');\n}\n\nasync function installCommand(options: InstallOptions): Promise<void> {\n console.log(chalk.bold('\\nPanopticon Installation\\n'));\n\n const plat = detectPlatform();\n console.log(`Platform: ${chalk.cyan(plat)}\\n`);\n\n // Step 1: Check prerequisites\n const prereqs = checkPrerequisites();\n\n if (options.check) {\n printPrereqStatus(prereqs);\n process.exit(prereqs.allPassed ? 0 : 1);\n }\n\n printPrereqStatus(prereqs);\n\n if (!prereqs.allPassed) {\n console.log(chalk.red('Fix prerequisites above before continuing.'));\n console.log(chalk.dim('Tip: Run with --minimal to skip optional components'));\n process.exit(1);\n }\n\n // Step 2: Initialize directories\n const spinner = ora('Initializing Panopticon directories...').start();\n for (const dir of INIT_DIRS) {\n mkdirSync(dir, { recursive: true });\n }\n spinner.succeed('Directories initialized');\n\n // Step 3: Docker network\n if (!options.skipDocker) {\n spinner.start('Creating Docker network...');\n try {\n execSync('docker network create panopticon 2>/dev/null || true', { stdio: 'pipe' });\n spinner.succeed('Docker network ready');\n } catch (error) {\n spinner.warn('Docker network setup failed (may already exist)');\n }\n }\n\n // Step 4: mkcert setup\n if (!options.skipMkcert && !options.minimal) {\n const hasMkcert = checkCommand('mkcert');\n if (hasMkcert) {\n spinner.start('Setting up mkcert CA...');\n try {\n execSync('mkcert -install', { stdio: 'pipe' });\n spinner.succeed('mkcert CA installed');\n\n // Generate wildcard certificates\n spinner.start('Generating wildcard certificates...');\n const traefikCertFile = join(TRAEFIK_CERTS_DIR, '_wildcard.pan.localhost.pem');\n const traefikKeyFile = join(TRAEFIK_CERTS_DIR, '_wildcard.pan.localhost-key.pem');\n\n execSync(\n `mkcert -cert-file \"${traefikCertFile}\" -key-file \"${traefikKeyFile}\" \"*.pan.localhost\" \"*.localhost\" localhost 127.0.0.1 ::1`,\n { stdio: 'pipe' }\n );\n\n // Also copy to legacy certs directory for backwards compatibility\n const legacyCertFile = join(CERTS_DIR, 'localhost.pem');\n const legacyKeyFile = join(CERTS_DIR, 'localhost-key.pem');\n copyFileSync(traefikCertFile, legacyCertFile);\n copyFileSync(traefikKeyFile, legacyKeyFile);\n\n spinner.succeed('Wildcard certificates generated (*.pan.localhost, *.localhost)');\n } catch (error) {\n spinner.warn('mkcert setup failed (HTTPS may not work)');\n }\n } else {\n spinner.info('Skipping mkcert (not installed)');\n }\n }\n\n // Step 5: Install ttyd (web terminal for planning sessions)\n const hasTtyd = checkCommand('ttyd') || existsSync(join(homedir(), 'bin', 'ttyd'));\n if (!hasTtyd) {\n spinner.start('Installing ttyd (web terminal)...');\n try {\n const binDir = join(homedir(), 'bin');\n mkdirSync(binDir, { recursive: true });\n const ttydPath = join(binDir, 'ttyd');\n\n // Determine platform and download appropriate binary\n const plat = detectPlatform();\n let downloadUrl = '';\n if (plat === 'darwin') {\n // macOS - try homebrew first\n try {\n execSync('brew install ttyd', { stdio: 'pipe' });\n spinner.succeed('ttyd installed via Homebrew');\n } catch {\n spinner.warn('ttyd installation failed - install manually: brew install ttyd');\n }\n } else {\n // Linux/WSL - download binary\n downloadUrl = 'https://github.com/tsl0922/ttyd/releases/latest/download/ttyd.x86_64';\n try {\n execSync(`curl -sL \"${downloadUrl}\" -o \"${ttydPath}\" && chmod +x \"${ttydPath}\"`, {\n stdio: 'pipe',\n timeout: 60000,\n });\n spinner.succeed(`ttyd installed to ${ttydPath}`);\n } catch (error) {\n spinner.warn('ttyd download failed - install manually from https://github.com/tsl0922/ttyd/releases');\n }\n }\n } catch (error) {\n spinner.warn('ttyd installation failed (planning sessions will not work)');\n }\n } else {\n spinner.info('ttyd already installed');\n }\n\n // Step 6: Setup Traefik configuration\n if (!options.minimal) {\n spinner.start('Setting up Traefik configuration...');\n\n try {\n // Copy Traefik templates from package to ~/.panopticon/traefik/\n // Only copy if files don't already exist\n if (!existsSync(join(TRAEFIK_DIR, 'docker-compose.yml'))) {\n copyDirectoryRecursive(SOURCE_TRAEFIK_TEMPLATES, TRAEFIK_DIR);\n spinner.succeed('Traefik configuration created from templates');\n } else {\n spinner.info('Traefik configuration already exists (skipping)');\n }\n } catch (error) {\n spinner.fail(`Failed to set up Traefik configuration: ${error}`);\n console.log(chalk.yellow('You can set up Traefik manually later'));\n }\n }\n\n // Step 6: Create config file if doesn't exist\n const configFile = join(PANOPTICON_HOME, 'config.toml');\n if (!existsSync(configFile)) {\n spinner.start('Creating default config...');\n\n // Get default config and customize based on install options\n const config = getDefaultConfig();\n\n // Configure Traefik based on minimal flag\n if (options.minimal) {\n config.traefik = {\n enabled: false,\n };\n } else {\n config.traefik = {\n enabled: true,\n dashboard_port: 8080,\n domain: 'pan.localhost',\n };\n }\n\n saveConfig(config);\n spinner.succeed('Config created');\n }\n\n // Done!\n console.log('');\n console.log(chalk.green.bold('Installation complete!'));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Run ${chalk.cyan('pan sync')} to sync skills to ~/.claude/`);\n\n if (!options.minimal) {\n console.log(` 2. Add to ${chalk.yellow('/etc/hosts')}: ${chalk.cyan('127.0.0.1 pan.localhost')}`);\n console.log(` 3. Run ${chalk.cyan('pan up')} to start Traefik and dashboard`);\n console.log(` 4. Access dashboard at ${chalk.cyan('https://pan.localhost')}`);\n } else {\n console.log(` 2. Run ${chalk.cyan('pan up')} to start the dashboard`);\n console.log(` 3. Access dashboard at ${chalk.cyan('http://localhost:3001')}`);\n }\n\n console.log(` ${!options.minimal ? '5' : '4'}. Create a workspace with ${chalk.cyan('pan workspace create <issue-id>')}`);\n console.log('');\n}\n","/**\n * Cloister CLI Commands\n *\n * pan cloister <command>\n */\n\nimport { Command } from 'commander';\nimport { statusCommand } from './status.js';\nimport { startCommand } from './start.js';\nimport { stopCommand } from './stop.js';\n\nexport function registerCloisterCommands(program: Command): void {\n const cloister = program\n .command('cloister')\n .description('Cloister agent watchdog commands');\n\n // pan cloister status\n cloister\n .command('status')\n .description('Show Cloister service status and agent health')\n .option('--json', 'Output in JSON format')\n .action(statusCommand);\n\n // pan cloister start\n cloister\n .command('start')\n .description('Start Cloister monitoring service')\n .action(startCommand);\n\n // pan cloister stop\n cloister\n .command('stop')\n .description('Stop Cloister monitoring (agents continue running)')\n .action(stopCommand);\n\n // pan cloister emergency-stop\n cloister\n .command('emergency-stop')\n .description('Emergency stop - kill ALL agents immediately')\n .action(() => stopCommand({ emergency: true }));\n}\n","/**\n * pan cloister status command\n *\n * Display Cloister service status and agent health summary.\n */\n\nimport chalk from 'chalk';\nimport { getCloisterService } from '../../../lib/cloister/service.js';\nimport { getHealthEmoji, getHealthLabel } from '../../../lib/cloister/health.js';\n\ninterface StatusOptions {\n json?: boolean;\n}\n\nexport async function statusCommand(options: StatusOptions): Promise<void> {\n const service = getCloisterService();\n const status = service.getStatus();\n\n if (options.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n\n console.log(chalk.bold('\\n🔔 Cloister Agent Watchdog\\n'));\n\n // Service status\n const runningStatus = status.running ? chalk.green('Running') : chalk.red('Stopped');\n console.log(`Status: ${runningStatus}`);\n\n if (status.lastCheck) {\n const lastCheck = new Date(status.lastCheck);\n const timeSince = Math.floor((Date.now() - lastCheck.getTime()) / 1000);\n console.log(`Last check: ${timeSince}s ago`);\n }\n\n console.log('');\n\n // Agent summary\n console.log(chalk.bold('Agent Health Summary:'));\n console.log(` 🟢 Active: ${chalk.green(status.summary.active)}`);\n console.log(` 🟡 Stale: ${chalk.yellow(status.summary.stale)}`);\n console.log(` 🟠 Warning: ${chalk.hex('#FFA500')(status.summary.warning)}`);\n console.log(` 🔴 Stuck: ${chalk.red(status.summary.stuck)}`);\n console.log(` Total: ${status.summary.total}`);\n\n console.log('');\n\n // Agents needing attention\n if (status.agentsNeedingAttention.length > 0) {\n console.log(chalk.bold('⚠️ Agents Needing Attention:'));\n for (const agentId of status.agentsNeedingAttention) {\n const health = service.getAgentHealth(agentId);\n if (health) {\n const emoji = getHealthEmoji(health.state);\n const label = getHealthLabel(health.state);\n const color = health.state === 'warning' ? chalk.hex('#FFA500') : chalk.red;\n console.log(` ${emoji} ${color(agentId)} - ${label}`);\n }\n }\n console.log('');\n }\n\n // Configuration\n console.log(chalk.bold('Configuration:'));\n console.log(` Auto-start: ${status.config.startup.auto_start ? 'enabled' : 'disabled'}`);\n console.log(` Thresholds: stale=${status.config.thresholds.stale}m, warning=${status.config.thresholds.warning}m, stuck=${status.config.thresholds.stuck}m`);\n console.log(` Auto-actions:`);\n console.log(` - Poke on warning: ${status.config.auto_actions.poke_on_warning ? 'enabled' : 'disabled'}`);\n console.log(` - Kill on stuck: ${status.config.auto_actions.kill_on_stuck ? chalk.red('enabled') : 'disabled'}`);\n\n console.log('');\n}\n","/**\n * Cloister Service\n *\n * Core monitoring service that watches over all running agents.\n * Named after the TARDIS's Cloister Bell - an alarm for catastrophic events.\n */\n\nimport type { AgentRuntime, HealthState } from '../runtimes/types.js';\nimport type { CloisterConfig } from './config.js';\nimport type { AgentHealth, HealthSummary } from './health.js';\nimport { loadCloisterConfig } from './config.js';\nimport {\n getAgentHealth,\n getMultipleAgentHealth,\n generateHealthSummary,\n getAgentsToPoke,\n getAgentsToKill,\n getAgentsNeedingAttention,\n} from './health.js';\nimport {\n initHealthDatabase,\n writeHealthEvent,\n getLatestHealthEvent,\n closeHealthDatabase,\n} from './database.js';\nimport { initializeEnabledSpecialists } from './specialists.js';\nimport { getGlobalRegistry, getRuntimeForAgent } from '../runtimes/index.js';\nimport { listRunningAgents, getAgentState } from '../agents.js';\nimport { checkAllTriggers, type TriggerDetection } from './triggers.js';\nimport { performHandoff, type HandoffResult } from './handoff.js';\nimport { logHandoffEvent, createHandoffEvent } from './handoff-logger.js';\n\n/**\n * Cloister service status\n */\nexport interface CloisterStatus {\n running: boolean;\n lastCheck: Date | null;\n config: CloisterConfig;\n summary: HealthSummary;\n agentsNeedingAttention: string[];\n}\n\n/**\n * Cloister service event\n */\nexport type CloisterEvent =\n | { type: 'started' }\n | { type: 'stopped' }\n | { type: 'health_check'; agentHealths: AgentHealth[] }\n | { type: 'agent_warning'; agentId: string; health: AgentHealth }\n | { type: 'agent_stuck'; agentId: string; health: AgentHealth }\n | { type: 'poked_agent'; agentId: string }\n | { type: 'killed_agent'; agentId: string }\n | { type: 'handoff_triggered'; agentId: string; trigger: TriggerDetection }\n | { type: 'handoff_completed'; agentId: string; result: HandoffResult }\n | { type: 'emergency_stop'; killedAgents: string[] }\n | { type: 'error'; error: Error };\n\n/**\n * Cloister service event listener\n */\nexport type CloisterEventListener = (event: CloisterEvent) => void;\n\n/**\n * Cloister Service\n *\n * Monitors agent health and performs auto-actions.\n */\nexport class CloisterService {\n private running: boolean = false;\n private checkInterval: NodeJS.Timeout | null = null;\n private lastCheck: Date | null = null;\n private config: CloisterConfig;\n private listeners: CloisterEventListener[] = [];\n private previousStates: Map<string, HealthState> = new Map();\n\n constructor(config?: CloisterConfig) {\n this.config = config || loadCloisterConfig();\n }\n\n /**\n * Start the Cloister service\n */\n async start(): Promise<void> {\n if (this.running) {\n console.warn('Cloister is already running');\n return;\n }\n\n console.log('🔔 Starting Cloister agent watchdog...');\n\n // Initialize health history database\n try {\n initHealthDatabase();\n console.log(' ✓ Health history database initialized');\n } catch (error) {\n console.error(' ✗ Failed to initialize health database:', error);\n }\n\n // Auto-initialize enabled specialists\n try {\n console.log(' → Checking specialists...');\n const results = await initializeEnabledSpecialists();\n for (const result of results) {\n if (result.success) {\n console.log(` ✓ ${result.name}: ${result.message}`);\n } else {\n console.log(` ✗ ${result.name}: ${result.message}`);\n }\n }\n } catch (error) {\n console.error(' ✗ Failed to initialize specialists:', error);\n }\n\n this.running = true;\n this.emit({ type: 'started' });\n\n // Start monitoring loop\n this.startMonitoringLoop();\n }\n\n /**\n * Stop the Cloister service\n *\n * Note: This stops monitoring but does NOT kill agents.\n * Use emergencyStop() to kill all agents.\n */\n stop(): void {\n if (!this.running) {\n console.warn('Cloister is not running');\n return;\n }\n\n console.log('🔔 Stopping Cloister agent watchdog...');\n this.running = false;\n\n if (this.checkInterval) {\n clearInterval(this.checkInterval);\n this.checkInterval = null;\n }\n\n // Close database connection\n try {\n closeHealthDatabase();\n } catch (error) {\n console.error('Failed to close health database:', error);\n }\n\n this.emit({ type: 'stopped' });\n }\n\n /**\n * Emergency stop - kill ALL agents immediately\n *\n * This is the nuclear option. Use with caution.\n */\n emergencyStop(): string[] {\n console.log('🚨 EMERGENCY STOP - Killing all agents');\n\n const runningAgents = listRunningAgents();\n const killedAgents: string[] = [];\n\n for (const agent of runningAgents) {\n if (agent.tmuxActive) {\n try {\n const runtime = getRuntimeForAgent(agent.id);\n if (runtime) {\n runtime.killAgent(agent.id);\n killedAgents.push(agent.id);\n console.log(` ✓ Killed ${agent.id}`);\n }\n } catch (error) {\n console.error(` ✗ Failed to kill ${agent.id}:`, error);\n }\n }\n }\n\n this.emit({ type: 'emergency_stop', killedAgents });\n\n // Stop monitoring after emergency stop\n this.stop();\n\n return killedAgents;\n }\n\n /**\n * Start the monitoring loop\n */\n private startMonitoringLoop(): void {\n // Run initial check immediately\n this.performHealthCheck();\n\n // Schedule periodic checks\n const intervalMs = this.config.monitoring.check_interval * 1000;\n this.checkInterval = setInterval(() => {\n this.performHealthCheck();\n }, intervalMs);\n }\n\n /**\n * Perform a health check on all running agents\n */\n private async performHealthCheck(): Promise<void> {\n try {\n const runningAgents = listRunningAgents().filter((a) => a.tmuxActive);\n const agentIds = runningAgents.map((a) => a.id);\n\n if (agentIds.length === 0) {\n this.lastCheck = new Date();\n return;\n }\n\n // Get health for all agents\n const agentHealths: AgentHealth[] = [];\n\n for (const agentId of agentIds) {\n const runtime = getRuntimeForAgent(agentId);\n if (runtime) {\n const health = getAgentHealth(agentId, runtime);\n agentHealths.push(health);\n\n // Write health event to database\n this.recordHealthEvent(health);\n }\n }\n\n this.lastCheck = new Date();\n this.emit({ type: 'health_check', agentHealths });\n\n // Check for agents needing attention\n const needsAttention = getAgentsNeedingAttention(agentHealths);\n\n for (const health of needsAttention) {\n if (health.state === 'warning') {\n this.emit({ type: 'agent_warning', agentId: health.agentId, health });\n\n // Auto-poke if configured\n if (this.config.auto_actions.poke_on_warning) {\n this.pokeAgent(health.agentId);\n }\n } else if (health.state === 'stuck') {\n this.emit({ type: 'agent_stuck', agentId: health.agentId, health });\n\n // Auto-kill if configured (dangerous!)\n if (this.config.auto_actions.kill_on_stuck) {\n this.killAgent(health.agentId);\n }\n }\n }\n\n // Check for handoff triggers (Phase 4)\n await this.checkHandoffTriggers(agentHealths);\n } catch (error) {\n console.error('Cloister health check failed:', error);\n this.emit({ type: 'error', error: error as Error });\n }\n }\n\n /**\n * Poke an agent (send \"are you stuck?\" message)\n */\n private pokeAgent(agentId: string): void {\n try {\n const runtime = getRuntimeForAgent(agentId);\n if (!runtime) {\n throw new Error(`No runtime found for agent ${agentId}`);\n }\n\n const pokeMessage =\n 'Hey, I noticed you haven\\'t made progress in a while. Are you stuck? ' +\n 'If you need help or clarification, please ask. Otherwise, please continue with your work.';\n\n runtime.sendMessage(agentId, pokeMessage);\n this.emit({ type: 'poked_agent', agentId });\n\n console.log(`🔔 Poked ${agentId}`);\n } catch (error) {\n console.error(`Failed to poke ${agentId}:`, error);\n }\n }\n\n /**\n * Kill an agent\n */\n private killAgent(agentId: string): void {\n try {\n const runtime = getRuntimeForAgent(agentId);\n if (!runtime) {\n throw new Error(`No runtime found for agent ${agentId}`);\n }\n\n runtime.killAgent(agentId);\n this.emit({ type: 'killed_agent', agentId });\n\n console.log(`🔔 Killed ${agentId}`);\n } catch (error) {\n console.error(`Failed to kill ${agentId}:`, error);\n }\n }\n\n /**\n * Record health event to database\n *\n * Only writes events when state changes or on first check.\n */\n private recordHealthEvent(health: AgentHealth): void {\n try {\n const currentState = health.state;\n const previousState = this.previousStates.get(health.agentId);\n\n // Only write event if state changed or this is first check\n if (previousState === undefined || previousState !== currentState) {\n // Determine source from heartbeat\n const source = health.heartbeat?.source\n ? this.mapActivitySource(health.heartbeat.source)\n : 'unknown';\n\n writeHealthEvent({\n agentId: health.agentId,\n timestamp: new Date().toISOString(),\n state: currentState,\n previousState: previousState,\n source,\n metadata: health.heartbeat\n ? JSON.stringify({\n confidence: health.heartbeat.confidence,\n lastAction: health.heartbeat.lastAction,\n toolName: health.heartbeat.toolName,\n timeSinceActivity: health.timeSinceActivity,\n })\n : undefined,\n });\n\n // Update tracked state\n this.previousStates.set(health.agentId, currentState);\n }\n } catch (error) {\n console.error(`Failed to record health event for ${health.agentId}:`, error);\n }\n }\n\n /**\n * Check for handoff triggers and execute handoffs (Phase 4)\n *\n * Checks all triggers for each agent and performs handoffs when triggered.\n */\n private async checkHandoffTriggers(agentHealths: AgentHealth[]): Promise<void> {\n for (const health of agentHealths) {\n try {\n // Get agent state\n const agentState = getAgentState(health.agentId);\n if (!agentState) continue;\n\n // Skip if no workspace (can't determine context)\n if (!agentState.workspace) continue;\n\n // Check all triggers\n const triggers = checkAllTriggers(\n health.agentId,\n agentState.workspace,\n agentState.issueId,\n agentState.model,\n health,\n this.config\n );\n\n // Execute handoff for first triggered condition\n // (Priority: stuck > planning > test > completion)\n if (triggers.length > 0) {\n const trigger = triggers[0];\n this.emit({ type: 'handoff_triggered', agentId: health.agentId, trigger });\n\n console.log(`🔔 Handoff triggered for ${health.agentId}: ${trigger.reason}`);\n\n // Perform handoff\n const result = await performHandoff(health.agentId, {\n targetModel: trigger.suggestedModel || 'sonnet',\n reason: trigger.reason,\n });\n\n this.emit({ type: 'handoff_completed', agentId: health.agentId, result });\n\n // Log handoff event\n if (result.context) {\n const event = createHandoffEvent(\n health.agentId,\n agentState.issueId,\n result.context,\n trigger.type,\n result.success,\n result.error\n );\n logHandoffEvent(event);\n }\n\n if (result.success) {\n console.log(`✓ Handoff completed: ${health.agentId} → ${result.newAgentId} (${trigger.suggestedModel})`);\n } else {\n console.error(`✗ Handoff failed: ${result.error}`);\n }\n }\n } catch (error) {\n console.error(`Failed to check handoff triggers for ${health.agentId}:`, error);\n }\n }\n }\n\n /**\n * Map ActivitySource to database source string\n */\n private mapActivitySource(source: string): string {\n switch (source) {\n case 'jsonl':\n return 'jsonl_mtime';\n case 'tmux':\n return 'tmux_activity';\n case 'git':\n return 'git_activity';\n case 'active-heartbeat':\n return 'active_heartbeat';\n default:\n return source;\n }\n }\n\n /**\n * Get current status\n */\n getStatus(): CloisterStatus {\n const runningAgents = listRunningAgents().filter((a) => a.tmuxActive);\n const agentIds = runningAgents.map((a) => a.id);\n\n const agentHealths: AgentHealth[] = [];\n\n for (const agentId of agentIds) {\n const runtime = getRuntimeForAgent(agentId);\n if (runtime) {\n const health = getAgentHealth(agentId, runtime);\n agentHealths.push(health);\n }\n }\n\n const summary = generateHealthSummary(agentHealths);\n const needsAttention = getAgentsNeedingAttention(agentHealths).map((h) => h.agentId);\n\n return {\n running: this.running,\n lastCheck: this.lastCheck,\n config: this.config,\n summary,\n agentsNeedingAttention: needsAttention,\n };\n }\n\n /**\n * Get health for a specific agent\n */\n getAgentHealth(agentId: string): AgentHealth | null {\n const runtime = getRuntimeForAgent(agentId);\n if (!runtime) {\n return null;\n }\n\n return getAgentHealth(agentId, runtime);\n }\n\n /**\n * Get health for all running agents\n */\n getAllAgentHealth(): AgentHealth[] {\n const runningAgents = listRunningAgents().filter((a) => a.tmuxActive);\n const agentHealths: AgentHealth[] = [];\n\n for (const agent of runningAgents) {\n const runtime = getRuntimeForAgent(agent.id);\n if (runtime) {\n const health = getAgentHealth(agent.id, runtime);\n agentHealths.push(health);\n }\n }\n\n return agentHealths;\n }\n\n /**\n * Reload configuration\n */\n reloadConfig(): void {\n this.config = loadCloisterConfig();\n\n // Restart monitoring loop with new interval if running\n if (this.running && this.checkInterval) {\n clearInterval(this.checkInterval);\n this.startMonitoringLoop();\n }\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: CloisterConfig): void {\n this.config = config;\n\n // Restart monitoring loop with new interval if running\n if (this.running && this.checkInterval) {\n clearInterval(this.checkInterval);\n this.startMonitoringLoop();\n }\n }\n\n /**\n * Register an event listener\n */\n on(listener: CloisterEventListener): void {\n this.listeners.push(listener);\n }\n\n /**\n * Unregister an event listener\n */\n off(listener: CloisterEventListener): void {\n this.listeners = this.listeners.filter((l) => l !== listener);\n }\n\n /**\n * Emit an event to all listeners\n */\n private emit(event: CloisterEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('Cloister event listener error:', error);\n }\n }\n }\n\n /**\n * Check if service is running\n */\n isRunning(): boolean {\n return this.running;\n }\n}\n\n/**\n * Global Cloister service instance\n */\nlet globalService: CloisterService | null = null;\n\n/**\n * Get the global Cloister service instance\n *\n * Creates a new instance if one doesn't exist.\n */\nexport function getCloisterService(): CloisterService {\n if (!globalService) {\n globalService = new CloisterService();\n }\n return globalService;\n}\n\n/**\n * Set the global Cloister service instance\n *\n * Useful for testing or custom configurations.\n */\nexport function setCloisterService(service: CloisterService): void {\n globalService = service;\n}\n","/**\n * Cloister Configuration\n *\n * Loads and manages Cloister configuration from ~/.panopticon/cloister.toml\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { parse, stringify } from '@iarna/toml';\nimport { join } from 'path';\nimport { PANOPTICON_HOME } from '../paths.js';\n\nconst CLOISTER_CONFIG_FILE = join(PANOPTICON_HOME, 'cloister.toml');\n\n/**\n * Health threshold configuration (in minutes)\n */\nexport interface HealthThresholds {\n stale: number;\n warning: number;\n stuck: number;\n}\n\n/**\n * Automatic action configuration\n */\nexport interface AutoActions {\n poke_on_warning: boolean;\n kill_on_stuck: boolean;\n restart_on_kill: boolean;\n}\n\n/**\n * Monitoring configuration\n */\nexport interface MonitoringConfig {\n check_interval: number; // seconds between health checks\n heartbeat_sources: ('jsonl_mtime' | 'tmux_activity' | 'git_activity' | 'active_heartbeat')[];\n}\n\n/**\n * Startup configuration\n */\nexport interface StartupConfig {\n auto_start: boolean; // Start Cloister when dashboard starts\n}\n\n/**\n * Notification configuration (future feature)\n */\nexport interface NotificationConfig {\n slack_webhook?: string;\n email?: string;\n}\n\n/**\n * Specialist agent configuration\n */\nexport interface SpecialistConfig {\n enabled: boolean;\n auto_wake: boolean;\n}\n\n/**\n * All specialist agents configuration\n */\nexport interface SpecialistsConfig {\n merge_agent?: SpecialistConfig;\n review_agent?: SpecialistConfig;\n test_agent?: SpecialistConfig;\n}\n\n/**\n * Model selection configuration\n */\nexport interface ModelSelectionConfig {\n default_model: 'opus' | 'sonnet' | 'haiku';\n complexity_routing: {\n trivial: 'opus' | 'sonnet' | 'haiku';\n simple: 'opus' | 'sonnet' | 'haiku';\n medium: 'opus' | 'sonnet' | 'haiku';\n complex: 'opus' | 'sonnet' | 'haiku';\n expert: 'opus' | 'sonnet' | 'haiku';\n };\n specialist_models: {\n merge_agent: 'opus' | 'sonnet' | 'haiku';\n review_agent: 'opus' | 'sonnet' | 'haiku';\n test_agent: 'opus' | 'sonnet' | 'haiku';\n planning_agent: 'opus' | 'sonnet' | 'haiku';\n };\n}\n\n/**\n * Handoff trigger configuration\n */\nexport interface HandoffTriggersConfig {\n planning_complete?: {\n enabled: boolean;\n from_model: 'opus' | 'sonnet' | 'haiku';\n to_model: 'opus' | 'sonnet' | 'haiku';\n };\n stuck_escalation?: {\n enabled: boolean;\n haiku_to_sonnet_minutes: number;\n sonnet_to_opus_minutes: number;\n };\n test_failure?: {\n enabled: boolean;\n from_model: 'opus' | 'sonnet' | 'haiku';\n to_model: 'opus' | 'sonnet' | 'haiku';\n trigger_on: 'any_failure' | '2_consecutive';\n };\n implementation_complete?: {\n enabled: boolean;\n to_specialist: string; // e.g., 'test-agent'\n };\n}\n\n/**\n * Handoff configuration\n */\nexport interface HandoffConfig {\n auto_triggers: HandoffTriggersConfig;\n}\n\n/**\n * Cost tracking configuration\n */\nexport interface CostTrackingConfig {\n display_enabled: boolean;\n log_to_jsonl: boolean;\n}\n\n/**\n * Complete Cloister configuration\n */\nexport interface CloisterConfig {\n startup: StartupConfig;\n thresholds: HealthThresholds;\n auto_actions: AutoActions;\n monitoring: MonitoringConfig;\n notifications?: NotificationConfig;\n specialists?: SpecialistsConfig;\n model_selection?: ModelSelectionConfig;\n handoffs?: HandoffConfig;\n cost_tracking?: CostTrackingConfig;\n}\n\n/**\n * Default Cloister configuration\n */\nexport const DEFAULT_CLOISTER_CONFIG: CloisterConfig = {\n startup: {\n auto_start: true,\n },\n thresholds: {\n stale: 5,\n warning: 15,\n stuck: 30,\n },\n auto_actions: {\n poke_on_warning: true,\n kill_on_stuck: false, // Manual by default for safety\n restart_on_kill: false,\n },\n monitoring: {\n check_interval: 60, // 1 minute\n heartbeat_sources: ['jsonl_mtime', 'tmux_activity', 'git_activity'],\n },\n notifications: {\n slack_webhook: undefined,\n email: undefined,\n },\n specialists: {\n merge_agent: {\n enabled: true,\n auto_wake: false, // Only wake on explicit \"Approve & Merge\" click\n },\n review_agent: {\n enabled: true,\n auto_wake: false, // Only wake on explicit request\n },\n test_agent: {\n enabled: false, // Not yet implemented\n auto_wake: false,\n },\n },\n model_selection: {\n default_model: 'sonnet',\n complexity_routing: {\n trivial: 'haiku',\n simple: 'haiku',\n medium: 'sonnet',\n complex: 'sonnet',\n expert: 'opus',\n },\n specialist_models: {\n merge_agent: 'sonnet',\n review_agent: 'sonnet',\n test_agent: 'haiku',\n planning_agent: 'opus',\n },\n },\n handoffs: {\n auto_triggers: {\n planning_complete: {\n enabled: true,\n from_model: 'opus',\n to_model: 'sonnet',\n },\n stuck_escalation: {\n enabled: true,\n haiku_to_sonnet_minutes: 10,\n sonnet_to_opus_minutes: 20,\n },\n test_failure: {\n enabled: true,\n from_model: 'haiku',\n to_model: 'sonnet',\n trigger_on: 'any_failure',\n },\n implementation_complete: {\n enabled: true, // Auto-handoff to test-agent when implementation done\n to_specialist: 'test-agent',\n },\n },\n },\n cost_tracking: {\n display_enabled: true,\n log_to_jsonl: true,\n },\n};\n\n/**\n * Deep merge utility that recursively merges objects.\n * - Recursively merges nested objects\n * - Arrays in overrides replace defaults (not concatenated)\n * - User values take precedence over defaults\n */\nfunction deepMerge<T extends object>(defaults: T, overrides: Partial<T>): T {\n const result = { ...defaults };\n\n for (const key of Object.keys(overrides) as (keyof T)[]) {\n const defaultVal = defaults[key];\n const overrideVal = overrides[key];\n\n // Skip undefined values in overrides\n if (overrideVal === undefined) continue;\n\n // Deep merge if both values are non-array objects\n if (\n typeof defaultVal === 'object' &&\n defaultVal !== null &&\n !Array.isArray(defaultVal) &&\n typeof overrideVal === 'object' &&\n overrideVal !== null &&\n !Array.isArray(overrideVal)\n ) {\n result[key] = deepMerge(defaultVal as any, overrideVal as any);\n } else {\n // Direct override for primitives and arrays\n result[key] = overrideVal as T[keyof T];\n }\n }\n\n return result;\n}\n\n/**\n * Load Cloister configuration\n *\n * Reads from ~/.panopticon/cloister.toml and merges with defaults.\n * Creates default config file if it doesn't exist.\n */\nexport function loadCloisterConfig(): CloisterConfig {\n // Ensure panopticon home exists\n if (!existsSync(PANOPTICON_HOME)) {\n mkdirSync(PANOPTICON_HOME, { recursive: true });\n }\n\n // If config file doesn't exist, create it with defaults\n if (!existsSync(CLOISTER_CONFIG_FILE)) {\n saveCloisterConfig(DEFAULT_CLOISTER_CONFIG);\n return DEFAULT_CLOISTER_CONFIG;\n }\n\n try {\n const content = readFileSync(CLOISTER_CONFIG_FILE, 'utf-8');\n const parsed = parse(content) as unknown as Partial<CloisterConfig>;\n\n // Deep merge with defaults\n return deepMerge(DEFAULT_CLOISTER_CONFIG, parsed);\n } catch (error) {\n console.error('Failed to load Cloister config:', error);\n console.error('Using default configuration');\n return DEFAULT_CLOISTER_CONFIG;\n }\n}\n\n/**\n * Save Cloister configuration\n *\n * Writes configuration to ~/.panopticon/cloister.toml\n */\nexport function saveCloisterConfig(config: CloisterConfig): void {\n // Ensure panopticon home exists\n if (!existsSync(PANOPTICON_HOME)) {\n mkdirSync(PANOPTICON_HOME, { recursive: true });\n }\n\n try {\n const content = stringify(config as any);\n writeFileSync(CLOISTER_CONFIG_FILE, content, 'utf-8');\n } catch (error) {\n console.error('Failed to save Cloister config:', error);\n throw error;\n }\n}\n\n/**\n * Update Cloister configuration\n *\n * Merges partial config updates with existing config.\n */\nexport function updateCloisterConfig(updates: Partial<CloisterConfig>): CloisterConfig {\n const current = loadCloisterConfig();\n const updated = deepMerge(current, updates);\n saveCloisterConfig(updated);\n return updated;\n}\n\n/**\n * Get the path to the Cloister config file\n */\nexport function getCloisterConfigPath(): string {\n return CLOISTER_CONFIG_FILE;\n}\n\n/**\n * Check if Cloister should auto-start\n */\nexport function shouldAutoStart(): boolean {\n const config = loadCloisterConfig();\n return config.startup.auto_start;\n}\n\n/**\n * Get health thresholds in milliseconds\n */\nexport function getHealthThresholdsMs(): {\n stale: number;\n warning: number;\n stuck: number;\n} {\n const config = loadCloisterConfig();\n return {\n stale: config.thresholds.stale * 60 * 1000,\n warning: config.thresholds.warning * 60 * 1000,\n stuck: config.thresholds.stuck * 60 * 1000,\n };\n}\n","/**\n * Cloister Health Evaluator\n *\n * Evaluates agent health based on heartbeats and activity timestamps.\n */\n\nimport type { HealthState, Heartbeat, AgentRuntime } from '../runtimes/types.js';\nimport type { HealthThresholds } from './config.js';\nimport { getHealthThresholdsMs } from './config.js';\n\n/**\n * Agent health status\n */\nexport interface AgentHealth {\n agentId: string;\n state: HealthState;\n lastActivity: Date | null;\n timeSinceActivity: number | null; // milliseconds\n heartbeat: Heartbeat | null;\n isRunning: boolean;\n}\n\n/**\n * Health summary for all agents\n */\nexport interface HealthSummary {\n active: number;\n stale: number;\n warning: number;\n stuck: number;\n total: number;\n}\n\n/**\n * Evaluate health state based on time since last activity\n *\n * @param timeSinceActivityMs - Milliseconds since last activity\n * @param thresholds - Health thresholds in milliseconds\n * @returns Health state\n */\nexport function evaluateHealthState(\n timeSinceActivityMs: number,\n thresholds: { stale: number; warning: number; stuck: number }\n): HealthState {\n if (timeSinceActivityMs < thresholds.stale) {\n return 'active';\n } else if (timeSinceActivityMs < thresholds.warning) {\n return 'stale';\n } else if (timeSinceActivityMs < thresholds.stuck) {\n return 'warning';\n } else {\n return 'stuck';\n }\n}\n\n/**\n * Get health status for a single agent\n *\n * @param agentId - Agent identifier\n * @param runtime - Runtime to query for heartbeat\n * @param thresholds - Health thresholds (optional, uses config if not provided)\n * @returns Agent health status\n */\nexport function getAgentHealth(\n agentId: string,\n runtime: AgentRuntime,\n thresholds?: { stale: number; warning: number; stuck: number }\n): AgentHealth {\n const thresholdsMs = thresholds || getHealthThresholdsMs();\n\n // Check if agent is running\n const isRunning = runtime.isRunning(agentId);\n\n if (!isRunning) {\n return {\n agentId,\n state: 'stuck',\n lastActivity: null,\n timeSinceActivity: null,\n heartbeat: null,\n isRunning: false,\n };\n }\n\n // Get heartbeat\n const heartbeat = runtime.getHeartbeat(agentId);\n\n if (!heartbeat) {\n // No heartbeat available - agent might be starting up\n return {\n agentId,\n state: 'active', // Assume active if no heartbeat yet\n lastActivity: null,\n timeSinceActivity: null,\n heartbeat: null,\n isRunning: true,\n };\n }\n\n // Calculate time since last activity\n const now = new Date();\n const timeSinceActivity = now.getTime() - heartbeat.timestamp.getTime();\n\n // Evaluate health state\n const state = evaluateHealthState(timeSinceActivity, thresholdsMs);\n\n return {\n agentId,\n state,\n lastActivity: heartbeat.timestamp,\n timeSinceActivity,\n heartbeat,\n isRunning: true,\n };\n}\n\n/**\n * Get health status for multiple agents\n *\n * @param agentIds - Array of agent identifiers\n * @param runtime - Runtime to query for heartbeats\n * @param thresholds - Health thresholds (optional, uses config if not provided)\n * @returns Array of agent health statuses\n */\nexport function getMultipleAgentHealth(\n agentIds: string[],\n runtime: AgentRuntime,\n thresholds?: { stale: number; warning: number; stuck: number }\n): AgentHealth[] {\n return agentIds.map((agentId) => getAgentHealth(agentId, runtime, thresholds));\n}\n\n/**\n * Generate health summary from agent health statuses\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Health summary with counts by state\n */\nexport function generateHealthSummary(agentHealths: AgentHealth[]): HealthSummary {\n const summary: HealthSummary = {\n active: 0,\n stale: 0,\n warning: 0,\n stuck: 0,\n total: agentHealths.length,\n };\n\n for (const health of agentHealths) {\n summary[health.state]++;\n }\n\n return summary;\n}\n\n/**\n * Check if an agent needs attention (warning or stuck)\n *\n * @param health - Agent health status\n * @returns True if agent needs attention\n */\nexport function needsAttention(health: AgentHealth): boolean {\n return health.state === 'warning' || health.state === 'stuck';\n}\n\n/**\n * Check if an agent should be poked (warning state)\n *\n * @param health - Agent health status\n * @returns True if agent should be poked\n */\nexport function shouldPoke(health: AgentHealth): boolean {\n return health.state === 'warning';\n}\n\n/**\n * Check if an agent should be killed (stuck state)\n *\n * @param health - Agent health status\n * @returns True if agent should be killed\n */\nexport function shouldKill(health: AgentHealth): boolean {\n return health.state === 'stuck';\n}\n\n/**\n * Get agents that need attention\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Array of agents needing attention\n */\nexport function getAgentsNeedingAttention(agentHealths: AgentHealth[]): AgentHealth[] {\n return agentHealths.filter(needsAttention);\n}\n\n/**\n * Get agents that should be poked\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Array of agents to poke\n */\nexport function getAgentsToPoke(agentHealths: AgentHealth[]): AgentHealth[] {\n return agentHealths.filter(shouldPoke);\n}\n\n/**\n * Get agents that should be killed\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Array of agents to kill\n */\nexport function getAgentsToKill(agentHealths: AgentHealth[]): AgentHealth[] {\n return agentHealths.filter(shouldKill);\n}\n\n/**\n * Format time duration in human-readable format\n *\n * @param ms - Milliseconds\n * @returns Human-readable duration (e.g., \"5m\", \"2h\", \"1d\")\n */\nexport function formatDuration(ms: number | null): string {\n if (ms === null) {\n return 'unknown';\n }\n\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}d`;\n } else if (hours > 0) {\n return `${hours}h`;\n } else if (minutes > 0) {\n return `${minutes}m`;\n } else {\n return `${seconds}s`;\n }\n}\n\n/**\n * Get health emoji for a health state\n *\n * @param state - Health state\n * @returns Emoji representing the state\n */\nexport function getHealthEmoji(state: HealthState): string {\n switch (state) {\n case 'active':\n return '🟢';\n case 'stale':\n return '🟡';\n case 'warning':\n return '🟠';\n case 'stuck':\n return '🔴';\n }\n}\n\n/**\n * Get health label for a health state\n *\n * @param state - Health state\n * @returns Human-readable label\n */\nexport function getHealthLabel(state: HealthState): string {\n switch (state) {\n case 'active':\n return 'Active';\n case 'stale':\n return 'Stale';\n case 'warning':\n return 'Warning';\n case 'stuck':\n return 'Stuck';\n }\n}\n","/**\n * Cloister Health History Database\n *\n * SQLite storage for agent health events and history.\n * Stores health state transitions for visualization and analysis.\n */\n\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync, mkdirSync } from 'fs';\nimport { PANOPTICON_HOME } from '../paths.js';\nimport type { HealthState } from '../runtimes/types.js';\n\nconst CLOISTER_DB_PATH = join(PANOPTICON_HOME, 'cloister.db');\nconst RETENTION_DAYS = 7;\n\n/**\n * Health event stored in database\n */\nexport interface HealthEvent {\n id?: number;\n agentId: string;\n timestamp: string; // ISO 8601\n state: HealthState;\n previousState?: string;\n source?: string; // jsonl_mtime, tmux_activity, git_activity, active_heartbeat\n metadata?: string; // JSON string\n}\n\n/**\n * Health event with parsed metadata\n */\nexport interface HealthEventWithMetadata extends Omit<HealthEvent, 'metadata'> {\n metadata?: Record<string, any>;\n}\n\nlet db: Database.Database | null = null;\n\n/**\n * Initialize the health history database\n *\n * Creates the database file and schema if they don't exist.\n * Safe to call multiple times - idempotent.\n */\nexport function initHealthDatabase(): Database.Database {\n // Ensure panopticon home exists\n if (!existsSync(PANOPTICON_HOME)) {\n mkdirSync(PANOPTICON_HOME, { recursive: true });\n }\n\n // Open or create database\n db = new Database(CLOISTER_DB_PATH);\n\n // Enable WAL mode for better concurrency\n db.pragma('journal_mode = WAL');\n\n // Create schema\n db.exec(`\n CREATE TABLE IF NOT EXISTS health_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n agent_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n state TEXT NOT NULL,\n previous_state TEXT,\n source TEXT,\n metadata TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_agent_timestamp\n ON health_events(agent_id, timestamp);\n\n CREATE INDEX IF NOT EXISTS idx_timestamp\n ON health_events(timestamp);\n `);\n\n // Run cleanup on initialization\n cleanupOldEvents(db);\n\n return db;\n}\n\n/**\n * Get the database instance, initializing if necessary\n */\nexport function getHealthDatabase(): Database.Database {\n if (!db) {\n return initHealthDatabase();\n }\n return db;\n}\n\n/**\n * Close the database connection\n */\nexport function closeHealthDatabase(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n\n/**\n * Write a health event to the database\n *\n * @param event - Health event to store\n * @returns The ID of the inserted event\n */\nexport function writeHealthEvent(event: Omit<HealthEvent, 'id'>): number {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n INSERT INTO health_events (agent_id, timestamp, state, previous_state, source, metadata)\n VALUES (?, ?, ?, ?, ?, ?)\n `);\n\n const result = stmt.run(\n event.agentId,\n event.timestamp,\n event.state,\n event.previousState || null,\n event.source || null,\n event.metadata || null\n );\n\n return result.lastInsertRowid as number;\n}\n\n/**\n * Write multiple health events in a transaction\n *\n * @param events - Array of health events to store\n * @returns Number of events inserted\n */\nexport function writeHealthEvents(events: Omit<HealthEvent, 'id'>[]): number {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n INSERT INTO health_events (agent_id, timestamp, state, previous_state, source, metadata)\n VALUES (?, ?, ?, ?, ?, ?)\n `);\n\n const insertMany = database.transaction((eventsToInsert: Omit<HealthEvent, 'id'>[]) => {\n for (const event of eventsToInsert) {\n stmt.run(\n event.agentId,\n event.timestamp,\n event.state,\n event.previousState || null,\n event.source || null,\n event.metadata || null\n );\n }\n return eventsToInsert.length;\n });\n\n return insertMany(events);\n}\n\n/**\n * Get health events for an agent within a time range\n *\n * @param agentId - Agent identifier\n * @param startTime - Start of time range (ISO 8601)\n * @param endTime - End of time range (ISO 8601)\n * @returns Array of health events, ordered by timestamp\n */\nexport function getHealthHistory(\n agentId: string,\n startTime: string,\n endTime: string\n): HealthEventWithMetadata[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE agent_id = ? AND timestamp >= ? AND timestamp <= ?\n ORDER BY timestamp ASC\n `);\n\n const events = stmt.all(agentId, startTime, endTime) as HealthEvent[];\n\n // Parse metadata JSON\n return events.map((event) => ({\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n }));\n}\n\n/**\n * Get recent health events for an agent\n *\n * @param agentId - Agent identifier\n * @param limit - Maximum number of events to return (default: 100)\n * @returns Array of health events, ordered by timestamp descending\n */\nexport function getRecentHealthHistory(\n agentId: string,\n limit: number = 100\n): HealthEventWithMetadata[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE agent_id = ?\n ORDER BY timestamp DESC\n LIMIT ?\n `);\n\n const events = stmt.all(agentId, limit) as HealthEvent[];\n\n // Parse metadata JSON and reverse to get chronological order\n return events\n .map((event) => ({\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n }))\n .reverse();\n}\n\n/**\n * Get health events for all agents within a time range\n *\n * @param startTime - Start of time range (ISO 8601)\n * @param endTime - End of time range (ISO 8601)\n * @returns Array of health events, ordered by timestamp\n */\nexport function getAllHealthHistory(\n startTime: string,\n endTime: string\n): HealthEventWithMetadata[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE timestamp >= ? AND timestamp <= ?\n ORDER BY timestamp ASC\n `);\n\n const events = stmt.all(startTime, endTime) as HealthEvent[];\n\n // Parse metadata JSON\n return events.map((event) => ({\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n }));\n}\n\n/**\n * Get the latest health event for an agent\n *\n * @param agentId - Agent identifier\n * @returns Latest health event or null if none exist\n */\nexport function getLatestHealthEvent(agentId: string): HealthEventWithMetadata | null {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE agent_id = ?\n ORDER BY timestamp DESC\n LIMIT 1\n `);\n\n const event = stmt.get(agentId) as HealthEvent | undefined;\n\n if (!event) {\n return null;\n }\n\n return {\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n };\n}\n\n/**\n * Get list of all agents with health history\n *\n * @returns Array of unique agent IDs\n */\nexport function getAgentsWithHistory(): string[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT DISTINCT agent_id as agentId\n FROM health_events\n ORDER BY agent_id ASC\n `);\n\n const results = stmt.all() as { agentId: string }[];\n return results.map((r) => r.agentId);\n}\n\n/**\n * Delete health events older than the retention period\n *\n * @param database - Database instance\n * @param retentionDays - Number of days to retain (default: 7)\n * @returns Number of events deleted\n */\nexport function cleanupOldEvents(\n database: Database.Database = getHealthDatabase(),\n retentionDays: number = RETENTION_DAYS\n): number {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n const cutoffTimestamp = cutoffDate.toISOString();\n\n const stmt = database.prepare(`\n DELETE FROM health_events\n WHERE timestamp < ?\n `);\n\n const result = stmt.run(cutoffTimestamp);\n return result.changes;\n}\n\n/**\n * Delete all health events for a specific agent\n *\n * @param agentId - Agent identifier\n * @returns Number of events deleted\n */\nexport function deleteAgentHistory(agentId: string): number {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n DELETE FROM health_events\n WHERE agent_id = ?\n `);\n\n const result = stmt.run(agentId);\n return result.changes;\n}\n\n/**\n * Get database statistics\n *\n * @returns Statistics about the health history database\n */\nexport function getDatabaseStats(): {\n totalEvents: number;\n uniqueAgents: number;\n oldestEvent: string | null;\n newestEvent: string | null;\n} {\n const database = getHealthDatabase();\n\n const countStmt = database.prepare('SELECT COUNT(*) as count FROM health_events');\n const agentStmt = database.prepare('SELECT COUNT(DISTINCT agent_id) as count FROM health_events');\n const oldestStmt = database.prepare('SELECT MIN(timestamp) as oldest FROM health_events');\n const newestStmt = database.prepare('SELECT MAX(timestamp) as newest FROM health_events');\n\n const totalEvents = (countStmt.get() as { count: number }).count;\n const uniqueAgents = (agentStmt.get() as { count: number }).count;\n const oldestEvent = (oldestStmt.get() as { oldest: string | null }).oldest;\n const newestEvent = (newestStmt.get() as { newest: string | null }).newest;\n\n return {\n totalEvents,\n uniqueAgents,\n oldestEvent,\n newestEvent,\n };\n}\n","/**\n * Cloister Specialist Agents\n *\n * Manages long-running specialist agents that can be woken up on demand.\n * Specialists maintain context across invocations via session files.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'fs';\nimport { join, basename } from 'path';\nimport { execSync } from 'child_process';\nimport { PANOPTICON_HOME } from '../paths.js';\nimport { getAllSessionFiles, parseClaudeSession } from '../cost-parsers/jsonl-parser.js';\n\nconst SPECIALISTS_DIR = join(PANOPTICON_HOME, 'specialists');\nconst REGISTRY_FILE = join(SPECIALISTS_DIR, 'registry.json');\n\n/**\n * Supported specialist types\n */\nexport type SpecialistType = 'merge-agent' | 'review-agent' | 'test-agent';\n\n/**\n * Specialist state\n */\nexport type SpecialistState = 'sleeping' | 'active' | 'uninitialized';\n\n/**\n * Specialist metadata\n */\nexport interface SpecialistMetadata {\n name: SpecialistType;\n displayName: string;\n description: string;\n enabled: boolean;\n autoWake: boolean;\n sessionId?: string;\n lastWake?: string; // ISO 8601 timestamp\n contextTokens?: number;\n}\n\n/**\n * Specialist status including runtime state\n */\nexport interface SpecialistStatus extends SpecialistMetadata {\n state: SpecialistState;\n isRunning: boolean;\n tmuxSession?: string;\n}\n\n/**\n * Registry of all specialist agents\n */\nexport interface SpecialistRegistry {\n version: string;\n specialists: SpecialistMetadata[];\n lastUpdated: string; // ISO 8601 timestamp\n}\n\n/**\n * Default specialist definitions\n */\nconst DEFAULT_SPECIALISTS: SpecialistMetadata[] = [\n {\n name: 'merge-agent',\n displayName: 'Merge Agent',\n description: 'PR merging and conflict resolution',\n enabled: true,\n autoWake: true,\n },\n {\n name: 'review-agent',\n displayName: 'Review Agent',\n description: 'Code review and quality checks',\n enabled: true,\n autoWake: true,\n },\n {\n name: 'test-agent',\n displayName: 'Test Agent',\n description: 'Test execution and analysis',\n enabled: false,\n autoWake: false,\n },\n];\n\n/**\n * Initialize specialists directory and registry\n *\n * Creates directory structure and default registry.json if needed.\n * Safe to call multiple times - idempotent.\n */\nexport function initSpecialistsDirectory(): void {\n // Ensure specialists directory exists\n if (!existsSync(SPECIALISTS_DIR)) {\n mkdirSync(SPECIALISTS_DIR, { recursive: true });\n }\n\n // Create default registry if it doesn't exist\n if (!existsSync(REGISTRY_FILE)) {\n const registry: SpecialistRegistry = {\n version: '1.0',\n specialists: DEFAULT_SPECIALISTS,\n lastUpdated: new Date().toISOString(),\n };\n saveRegistry(registry);\n }\n}\n\n/**\n * Load the specialist registry\n *\n * @returns Specialist registry\n */\nexport function loadRegistry(): SpecialistRegistry {\n initSpecialistsDirectory();\n\n try {\n const content = readFileSync(REGISTRY_FILE, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n console.error('Failed to load specialist registry:', error);\n // Return default registry\n return {\n version: '1.0',\n specialists: DEFAULT_SPECIALISTS,\n lastUpdated: new Date().toISOString(),\n };\n }\n}\n\n/**\n * Save the specialist registry\n *\n * @param registry - Registry to save\n */\nexport function saveRegistry(registry: SpecialistRegistry): void {\n // Only ensure directory exists, don't call initSpecialistsDirectory to avoid recursion\n if (!existsSync(SPECIALISTS_DIR)) {\n mkdirSync(SPECIALISTS_DIR, { recursive: true });\n }\n\n registry.lastUpdated = new Date().toISOString();\n\n try {\n const content = JSON.stringify(registry, null, 2);\n writeFileSync(REGISTRY_FILE, content, 'utf-8');\n } catch (error) {\n console.error('Failed to save specialist registry:', error);\n throw error;\n }\n}\n\n/**\n * Get session file path for a specialist\n *\n * @param name - Specialist name\n * @returns Path to session file\n */\nexport function getSessionFilePath(name: SpecialistType): string {\n return join(SPECIALISTS_DIR, `${name}.session`);\n}\n\n/**\n * Read session ID from file\n *\n * @param name - Specialist name\n * @returns Session ID or null if not found\n */\nexport function getSessionId(name: SpecialistType): string | null {\n const sessionFile = getSessionFilePath(name);\n\n if (!existsSync(sessionFile)) {\n return null;\n }\n\n try {\n return readFileSync(sessionFile, 'utf-8').trim();\n } catch (error) {\n console.error(`Failed to read session file for ${name}:`, error);\n return null;\n }\n}\n\n/**\n * Write session ID to file\n *\n * @param name - Specialist name\n * @param sessionId - Session ID to store\n */\nexport function setSessionId(name: SpecialistType, sessionId: string): void {\n initSpecialistsDirectory();\n\n const sessionFile = getSessionFilePath(name);\n\n try {\n writeFileSync(sessionFile, sessionId.trim(), 'utf-8');\n } catch (error) {\n console.error(`Failed to write session file for ${name}:`, error);\n throw error;\n }\n}\n\n/**\n * Delete session file\n *\n * @param name - Specialist name\n * @returns True if file was deleted, false if it didn't exist\n */\nexport function clearSessionId(name: SpecialistType): boolean {\n const sessionFile = getSessionFilePath(name);\n\n if (!existsSync(sessionFile)) {\n return false;\n }\n\n try {\n unlinkSync(sessionFile);\n return true;\n } catch (error) {\n console.error(`Failed to delete session file for ${name}:`, error);\n throw error;\n }\n}\n\n/**\n * Get metadata for a specific specialist\n *\n * @param name - Specialist name\n * @returns Specialist metadata or null if not found\n */\nexport function getSpecialistMetadata(name: SpecialistType): SpecialistMetadata | null {\n const registry = loadRegistry();\n return registry.specialists.find((s) => s.name === name) || null;\n}\n\n/**\n * Update specialist metadata\n *\n * @param name - Specialist name\n * @param updates - Partial metadata to update\n */\nexport function updateSpecialistMetadata(\n name: SpecialistType,\n updates: Partial<SpecialistMetadata>\n): void {\n const registry = loadRegistry();\n\n const index = registry.specialists.findIndex((s) => s.name === name);\n\n if (index === -1) {\n throw new Error(`Specialist ${name} not found in registry`);\n }\n\n registry.specialists[index] = {\n ...registry.specialists[index],\n ...updates,\n name, // Ensure name doesn't change\n };\n\n saveRegistry(registry);\n}\n\n/**\n * Get all specialist metadata\n *\n * @returns Array of all specialists\n */\nexport function getAllSpecialists(): SpecialistMetadata[] {\n const registry = loadRegistry();\n return registry.specialists;\n}\n\n/**\n * Check if a specialist is initialized (has session file)\n *\n * @param name - Specialist name\n * @returns True if specialist has a session file\n */\nexport function isInitialized(name: SpecialistType): boolean {\n return getSessionId(name) !== null;\n}\n\n/**\n * Get the state of a specialist based on session file\n *\n * Note: This only checks if session exists, not if it's actually running.\n * Use getSpecialistStatus() for runtime state.\n *\n * @param name - Specialist name\n * @returns Specialist state\n */\nexport function getSpecialistState(name: SpecialistType): Exclude<SpecialistState, 'active'> {\n return isInitialized(name) ? 'sleeping' : 'uninitialized';\n}\n\n/**\n * Get tmux session name for a specialist\n *\n * @param name - Specialist name\n * @returns Expected tmux session name\n */\nexport function getTmuxSessionName(name: SpecialistType): string {\n return `specialist-${name}`;\n}\n\n/**\n * Record wake event in metadata\n *\n * @param name - Specialist name\n * @param sessionId - New session ID (if changed)\n */\nexport function recordWake(name: SpecialistType, sessionId?: string): void {\n const updates: Partial<SpecialistMetadata> = {\n lastWake: new Date().toISOString(),\n };\n\n if (sessionId) {\n updates.sessionId = sessionId;\n }\n\n updateSpecialistMetadata(name, updates);\n}\n\n/**\n * Update context token count for a specialist\n *\n * @param name - Specialist name\n * @param tokens - Total context tokens\n */\nexport function updateContextTokens(name: SpecialistType, tokens: number): void {\n updateSpecialistMetadata(name, { contextTokens: tokens });\n}\n\n/**\n * List all session files in the specialists directory\n *\n * @returns Array of specialist names that have session files\n */\nexport function listSessionFiles(): SpecialistType[] {\n initSpecialistsDirectory();\n\n try {\n const files = readdirSync(SPECIALISTS_DIR);\n const sessionFiles = files.filter((f) => f.endsWith('.session'));\n\n return sessionFiles.map((f) => f.replace('.session', '') as SpecialistType);\n } catch (error) {\n console.error('Failed to list session files:', error);\n return [];\n }\n}\n\n/**\n * Enable a specialist\n *\n * @param name - Specialist name\n */\nexport function enableSpecialist(name: SpecialistType): void {\n updateSpecialistMetadata(name, { enabled: true });\n}\n\n/**\n * Disable a specialist\n *\n * @param name - Specialist name\n */\nexport function disableSpecialist(name: SpecialistType): void {\n updateSpecialistMetadata(name, { enabled: false });\n}\n\n/**\n * Check if a specialist is enabled\n *\n * @param name - Specialist name\n * @returns True if specialist is enabled\n */\nexport function isEnabled(name: SpecialistType): boolean {\n const metadata = getSpecialistMetadata(name);\n return metadata?.enabled ?? false;\n}\n\n/**\n * Get all enabled specialists\n *\n * @returns Array of enabled specialists\n */\nexport function getEnabledSpecialists(): SpecialistMetadata[] {\n return getAllSpecialists().filter((s) => s.enabled);\n}\n\n/**\n * Find JSONL file for a session ID\n *\n * Searches through Claude Code project directories to find the JSONL file.\n *\n * @param sessionId - Session ID to find\n * @returns Path to JSONL file or null if not found\n */\nexport function findSessionFile(sessionId: string): string | null {\n try {\n const allFiles = getAllSessionFiles();\n\n for (const file of allFiles) {\n const fileSessionId = basename(file, '.jsonl');\n if (fileSessionId === sessionId) {\n return file;\n }\n }\n } catch {\n // Session files not available\n }\n\n return null;\n}\n\n/**\n * Count context tokens for a specialist session\n *\n * Reads the JSONL file for the specialist's session and sums all token usage.\n * This gives an approximate count of context size.\n *\n * @param name - Specialist name\n * @returns Total token count or null if session not found\n */\nexport function countContextTokens(name: SpecialistType): number | null {\n const sessionId = getSessionId(name);\n\n if (!sessionId) {\n return null;\n }\n\n const sessionFile = findSessionFile(sessionId);\n\n if (!sessionFile) {\n return null;\n }\n\n const sessionUsage = parseClaudeSession(sessionFile);\n\n if (!sessionUsage) {\n return null;\n }\n\n // Sum all token types for total context\n return (\n sessionUsage.usage.inputTokens +\n sessionUsage.usage.outputTokens +\n (sessionUsage.usage.cacheReadTokens || 0) +\n (sessionUsage.usage.cacheWriteTokens || 0)\n );\n}\n\n/**\n * Check if a specialist is currently running in tmux\n *\n * @param name - Specialist name\n * @returns True if specialist has an active tmux session\n */\nexport function isRunning(name: SpecialistType): boolean {\n const tmuxSession = getTmuxSessionName(name);\n\n try {\n execSync(`tmux has-session -t ${tmuxSession}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get complete status for a specialist\n *\n * Combines metadata, session info, and runtime state.\n *\n * @param name - Specialist name\n * @returns Complete specialist status\n */\nexport function getSpecialistStatus(name: SpecialistType): SpecialistStatus {\n const metadata = getSpecialistMetadata(name) || {\n name,\n displayName: name,\n description: '',\n enabled: false,\n autoWake: false,\n };\n\n const sessionId = getSessionId(name);\n const running = isRunning(name);\n const contextTokens = countContextTokens(name);\n\n // Determine state\n let state: SpecialistState;\n if (running) {\n state = 'active';\n } else if (sessionId) {\n state = 'sleeping';\n } else {\n state = 'uninitialized';\n }\n\n return {\n ...metadata,\n sessionId: sessionId || undefined,\n contextTokens: contextTokens || undefined,\n state,\n isRunning: running,\n tmuxSession: getTmuxSessionName(name),\n };\n}\n\n/**\n * Get status for all specialists\n *\n * @returns Array of specialist statuses\n */\nexport function getAllSpecialistStatus(): SpecialistStatus[] {\n return getAllSpecialists().map((metadata) => getSpecialistStatus(metadata.name));\n}\n\n/**\n * Initialize a specialist agent\n *\n * Creates a tmux session and starts Claude Code with an identity prompt.\n * This is for first-time initialization of specialists that don't have session files.\n *\n * @param name - Specialist name\n * @returns Promise with initialization result\n */\nexport async function initializeSpecialist(name: SpecialistType): Promise<{\n success: boolean;\n message: string;\n tmuxSession?: string;\n error?: string;\n}> {\n // Check if already running\n if (isRunning(name)) {\n return {\n success: false,\n message: `Specialist ${name} is already running`,\n error: 'already_running',\n };\n }\n\n // Check if already initialized\n if (getSessionId(name)) {\n return {\n success: false,\n message: `Specialist ${name} is already initialized. Use wake to start it.`,\n error: 'already_initialized',\n };\n }\n\n const tmuxSession = getTmuxSessionName(name);\n const cwd = process.env.HOME || '/home/eltmon';\n\n // Create identity prompt for the specialist\n const identityPrompt = `You are the ${name} specialist agent for Panopticon.\nYour role: ${name === 'merge-agent' ? 'Resolve merge conflicts and ensure clean integrations' :\n name === 'review-agent' ? 'Review code changes and provide quality feedback' :\n name === 'test-agent' ? 'Execute and analyze test results' : 'Assist with development tasks'}\n\nYou will be woken up when your services are needed. For now, acknowledge your initialization and wait.\nSay: \"I am the ${name} specialist, ready and waiting for tasks.\"`;\n\n try {\n // Spawn Claude Code fresh in tmux\n execSync(\n `tmux new-session -d -s \"${tmuxSession}\" -c \"${cwd}\" \"claude --dangerously-skip-permissions\"`,\n { encoding: 'utf-8' }\n );\n\n // Wait for Claude to start, then send identity prompt\n await new Promise(resolve => setTimeout(resolve, 3000));\n\n const escapedPrompt = identityPrompt.replace(/'/g, \"'\\\\''\");\n // Send text and Enter SEPARATELY to avoid Enter being interpreted as newline\n execSync(`tmux send-keys -t \"${tmuxSession}\" '${escapedPrompt}'`, { encoding: 'utf-8' });\n await new Promise(resolve => setTimeout(resolve, 500));\n execSync(`tmux send-keys -t \"${tmuxSession}\" C-m`, { encoding: 'utf-8' });\n\n // Record wake event\n recordWake(name);\n\n return {\n success: true,\n message: `Specialist ${name} initialized and started`,\n tmuxSession,\n };\n } catch (error: any) {\n return {\n success: false,\n message: `Failed to initialize specialist ${name}: ${error.message}`,\n error: error.message,\n };\n }\n}\n\n/**\n * Initialize all enabled but uninitialized specialists\n *\n * Called during Cloister startup to ensure specialists are ready.\n *\n * @returns Promise with array of initialization results\n */\nexport async function initializeEnabledSpecialists(): Promise<Array<{\n name: SpecialistType;\n success: boolean;\n message: string;\n}>> {\n const enabled = getEnabledSpecialists();\n const results: Array<{ name: SpecialistType; success: boolean; message: string }> = [];\n\n for (const specialist of enabled) {\n const sessionId = getSessionId(specialist.name);\n\n if (!sessionId) {\n // Specialist is enabled but not initialized\n console.log(` → Auto-initializing specialist: ${specialist.name}`);\n const result = await initializeSpecialist(specialist.name);\n results.push({\n name: specialist.name,\n success: result.success,\n message: result.message,\n });\n\n // Small delay between initializations to avoid overwhelming the system\n if (results.length < enabled.length) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n } else {\n results.push({\n name: specialist.name,\n success: true,\n message: `Already initialized with session ${sessionId.substring(0, 8)}...`,\n });\n }\n }\n\n return results;\n}\n","/**\n * Claude Code JSONL Parser\n *\n * Parse token usage from Claude Code session files.\n * Session files are stored at: ~/.claude/projects/<project-path-hash>/<session-id>.jsonl\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync } from 'fs';\nimport { join, basename } from 'path';\nimport { homedir } from 'os';\nimport { TokenUsage, calculateCost, getPricing, AIProvider, logCost, CostEntry } from '../cost.js';\n\n// Claude Code JSONL message format\nexport interface ClaudeMessage {\n sessionId?: string;\n timestamp?: string;\n parentMessageId?: string;\n message?: {\n id?: string;\n role?: 'user' | 'assistant';\n model?: string;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n };\n // Some messages have usage at top level\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n model?: string;\n}\n\n// Parsed session usage\nexport interface SessionUsage {\n sessionId: string;\n sessionFile: string;\n startTime: string;\n endTime: string;\n model: string;\n usage: TokenUsage;\n cost: number;\n messageCount: number;\n}\n\n// Claude projects directory\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\n/**\n * Get all Claude Code project directories\n */\nexport function getProjectDirs(): string[] {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) {\n return [];\n }\n\n return readdirSync(CLAUDE_PROJECTS_DIR)\n .map(name => join(CLAUDE_PROJECTS_DIR, name))\n .filter(path => {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n });\n}\n\n/**\n * Get session JSONL files for a project directory\n */\nexport function getSessionFiles(projectDir: string): string[] {\n if (!existsSync(projectDir)) {\n return [];\n }\n\n return readdirSync(projectDir)\n .filter(name => name.endsWith('.jsonl'))\n .map(name => join(projectDir, name))\n .sort((a, b) => {\n try {\n return statSync(b).mtime.getTime() - statSync(a).mtime.getTime();\n } catch {\n return 0;\n }\n });\n}\n\n/**\n * Get all session files across all projects\n */\nexport function getAllSessionFiles(): string[] {\n const files: string[] = [];\n\n for (const projectDir of getProjectDirs()) {\n files.push(...getSessionFiles(projectDir));\n }\n\n return files.sort((a, b) => {\n try {\n return statSync(b).mtime.getTime() - statSync(a).mtime.getTime();\n } catch {\n return 0;\n }\n });\n}\n\n/**\n * Normalize model name for pricing lookup\n */\nfunction normalizeModelName(model: string): { provider: AIProvider; model: string } {\n // Claude models\n if (model.includes('claude')) {\n let normalizedModel = model;\n\n // Map full model IDs to pricing model names\n if (model.includes('opus-4-5') || model.includes('opus-4.5')) {\n normalizedModel = 'claude-opus-4';\n } else if (model.includes('opus-4') || model.includes('opus')) {\n normalizedModel = 'claude-opus-4';\n } else if (model.includes('sonnet-4') || model.includes('sonnet')) {\n normalizedModel = 'claude-sonnet-4';\n } else if (model.includes('haiku')) {\n normalizedModel = 'claude-haiku-3.5';\n }\n\n return { provider: 'anthropic', model: normalizedModel };\n }\n\n // OpenAI models\n if (model.includes('gpt')) {\n return { provider: 'openai', model };\n }\n\n // Google models\n if (model.includes('gemini')) {\n return { provider: 'google', model };\n }\n\n // Default to anthropic/claude\n return { provider: 'anthropic', model: 'claude-sonnet-4' };\n}\n\n/**\n * Parse a Claude Code session JSONL file and extract usage\n */\nexport function parseClaudeSession(sessionFile: string): SessionUsage | null {\n if (!existsSync(sessionFile)) {\n return null;\n }\n\n const content = readFileSync(sessionFile, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n\n let sessionId = '';\n let startTime = '';\n let endTime = '';\n let primaryModel = '';\n let messageCount = 0;\n\n const totalUsage: TokenUsage = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n\n for (const line of lines) {\n try {\n const msg: ClaudeMessage = JSON.parse(line);\n\n // Extract session ID from first message\n if (msg.sessionId && !sessionId) {\n sessionId = msg.sessionId;\n }\n\n // Track timestamps\n if (msg.timestamp) {\n if (!startTime || msg.timestamp < startTime) {\n startTime = msg.timestamp;\n }\n if (!endTime || msg.timestamp > endTime) {\n endTime = msg.timestamp;\n }\n }\n\n // Extract usage - can be in message.usage or top-level usage\n const usage = msg.message?.usage || msg.usage;\n const model = msg.message?.model || msg.model;\n\n if (usage) {\n totalUsage.inputTokens += usage.input_tokens || 0;\n totalUsage.outputTokens += usage.output_tokens || 0;\n totalUsage.cacheReadTokens = (totalUsage.cacheReadTokens || 0) + (usage.cache_read_input_tokens || 0);\n totalUsage.cacheWriteTokens = (totalUsage.cacheWriteTokens || 0) + (usage.cache_creation_input_tokens || 0);\n messageCount++;\n }\n\n // Track primary model (most frequently used)\n if (model && !primaryModel) {\n primaryModel = model;\n }\n } catch {\n // Skip invalid JSON lines\n }\n }\n\n // If no usage found, return null\n if (totalUsage.inputTokens === 0 && totalUsage.outputTokens === 0) {\n return null;\n }\n\n // Use filename as session ID if not found in messages\n if (!sessionId) {\n sessionId = basename(sessionFile, '.jsonl');\n }\n\n // Default model if not found\n if (!primaryModel) {\n primaryModel = 'claude-sonnet-4';\n }\n\n // Calculate cost\n const { provider, model } = normalizeModelName(primaryModel);\n const pricing = getPricing(provider, model);\n const cost = pricing ? calculateCost(totalUsage, pricing) : 0;\n\n return {\n sessionId,\n sessionFile,\n startTime: startTime || new Date().toISOString(),\n endTime: endTime || new Date().toISOString(),\n model: primaryModel,\n usage: totalUsage,\n cost,\n messageCount,\n };\n}\n\n/**\n * Parse all sessions and return usage summaries\n */\nexport function parseAllSessions(maxAge?: number): SessionUsage[] {\n const sessions: SessionUsage[] = [];\n const cutoffTime = maxAge ? Date.now() - maxAge : 0;\n\n for (const file of getAllSessionFiles()) {\n try {\n const stat = statSync(file);\n if (cutoffTime && stat.mtime.getTime() < cutoffTime) {\n continue;\n }\n\n const usage = parseClaudeSession(file);\n if (usage) {\n sessions.push(usage);\n }\n } catch {\n // Skip files that can't be read\n }\n }\n\n return sessions;\n}\n\n/**\n * Get recent sessions (last N days)\n */\nexport function getRecentSessions(days: number = 7): SessionUsage[] {\n const maxAge = days * 24 * 60 * 60 * 1000;\n return parseAllSessions(maxAge);\n}\n\n/**\n * Import session usage to cost log\n */\nexport function importSessionToCostLog(\n session: SessionUsage,\n options: {\n issueId?: string;\n agentId?: string;\n operation?: string;\n } = {}\n): CostEntry | null {\n const { provider, model } = normalizeModelName(session.model);\n const pricing = getPricing(provider, model);\n\n if (!pricing) {\n console.warn(`No pricing found for ${session.model}`);\n return null;\n }\n\n return logCost({\n provider,\n model,\n usage: session.usage,\n cost: session.cost,\n currency: 'USD',\n operation: options.operation || 'claude_session',\n issueId: options.issueId,\n agentId: options.agentId,\n metadata: {\n sessionId: session.sessionId,\n sessionFile: session.sessionFile,\n startTime: session.startTime,\n endTime: session.endTime,\n messageCount: session.messageCount,\n },\n });\n}\n","/**\n * Cost Tracking System\n *\n * Track AI usage costs per feature, issue, and project.\n * Supports multiple AI providers with configurable pricing.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { COSTS_DIR } from './paths.js';\n\n// ============== Types ==============\n\nexport type AIProvider = 'anthropic' | 'openai' | 'google' | 'custom';\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n}\n\nexport interface CostEntry {\n id: string;\n timestamp: string;\n provider: AIProvider;\n model: string;\n issueId?: string;\n featureId?: string;\n agentId?: string;\n operation: string;\n usage: TokenUsage;\n cost: number;\n currency: string;\n metadata?: Record<string, any>;\n}\n\nexport interface CostSummary {\n totalCost: number;\n currency: string;\n period: {\n start: string;\n end: string;\n };\n byProvider: Record<AIProvider, number>;\n byModel: Record<string, number>;\n byIssue: Record<string, number>;\n byFeature: Record<string, number>;\n entryCount: number;\n totalTokens: {\n input: number;\n output: number;\n total: number;\n };\n}\n\nexport interface CostBudget {\n id: string;\n name: string;\n type: 'issue' | 'feature' | 'project' | 'daily' | 'monthly';\n limit: number;\n currency: string;\n spent: number;\n alertThreshold: number; // e.g., 0.8 = alert at 80%\n enabled: boolean;\n}\n\nexport interface ModelPricing {\n provider: AIProvider;\n model: string;\n inputPer1k: number;\n outputPer1k: number;\n cacheReadPer1k?: number;\n cacheWritePer1k?: number;\n currency: string;\n}\n\n// ============== Pricing Data ==============\n\nexport const DEFAULT_PRICING: ModelPricing[] = [\n // Anthropic\n { provider: 'anthropic', model: 'claude-opus-4', inputPer1k: 0.015, outputPer1k: 0.075, cacheReadPer1k: 0.00175, cacheWritePer1k: 0.01875, currency: 'USD' },\n { provider: 'anthropic', model: 'claude-sonnet-4', inputPer1k: 0.003, outputPer1k: 0.015, cacheReadPer1k: 0.0003, cacheWritePer1k: 0.00375, currency: 'USD' },\n { provider: 'anthropic', model: 'claude-haiku-3.5', inputPer1k: 0.0008, outputPer1k: 0.004, cacheReadPer1k: 0.00008, cacheWritePer1k: 0.001, currency: 'USD' },\n // OpenAI\n { provider: 'openai', model: 'gpt-4-turbo', inputPer1k: 0.01, outputPer1k: 0.03, currency: 'USD' },\n { provider: 'openai', model: 'gpt-4o', inputPer1k: 0.005, outputPer1k: 0.015, currency: 'USD' },\n { provider: 'openai', model: 'gpt-4o-mini', inputPer1k: 0.00015, outputPer1k: 0.0006, currency: 'USD' },\n // Google\n { provider: 'google', model: 'gemini-1.5-pro', inputPer1k: 0.00125, outputPer1k: 0.005, currency: 'USD' },\n { provider: 'google', model: 'gemini-1.5-flash', inputPer1k: 0.000075, outputPer1k: 0.0003, currency: 'USD' },\n];\n\n// ============== Cost Calculation ==============\n\n/**\n * Calculate cost for token usage\n */\nexport function calculateCost(usage: TokenUsage, pricing: ModelPricing): number {\n let cost = 0;\n\n // Input tokens\n cost += (usage.inputTokens / 1000) * pricing.inputPer1k;\n\n // Output tokens\n cost += (usage.outputTokens / 1000) * pricing.outputPer1k;\n\n // Cache tokens (if applicable)\n if (usage.cacheReadTokens && pricing.cacheReadPer1k) {\n cost += (usage.cacheReadTokens / 1000) * pricing.cacheReadPer1k;\n }\n if (usage.cacheWriteTokens && pricing.cacheWritePer1k) {\n cost += (usage.cacheWriteTokens / 1000) * pricing.cacheWritePer1k;\n }\n\n return Math.round(cost * 1000000) / 1000000; // Round to 6 decimal places\n}\n\n/**\n * Get pricing for a model\n */\nexport function getPricing(provider: AIProvider, model: string): ModelPricing | null {\n // Try exact match first\n let pricing = DEFAULT_PRICING.find(\n p => p.provider === provider && p.model === model\n );\n\n if (!pricing) {\n // Try partial match (e.g., \"claude-sonnet-4-20250101\" matches \"claude-sonnet-4\")\n pricing = DEFAULT_PRICING.find(\n p => p.provider === provider && model.startsWith(p.model)\n );\n }\n\n return pricing || null;\n}\n\n// ============== Cost Logging ==============\n\nfunction getCostFile(date: string): string {\n return join(COSTS_DIR, `costs-${date}.jsonl`);\n}\n\nfunction getCurrentDateString(): string {\n return new Date().toISOString().split('T')[0];\n}\n\n/**\n * Log a cost entry\n */\nexport function logCost(entry: Omit<CostEntry, 'id' | 'timestamp'>): CostEntry {\n mkdirSync(COSTS_DIR, { recursive: true });\n\n const fullEntry: CostEntry = {\n ...entry,\n id: `cost-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n };\n\n const costFile = getCostFile(getCurrentDateString());\n appendFileSync(costFile, JSON.stringify(fullEntry) + '\\n');\n\n return fullEntry;\n}\n\n/**\n * Log cost from token usage\n */\nexport function logUsage(\n provider: AIProvider,\n model: string,\n usage: TokenUsage,\n options: {\n issueId?: string;\n featureId?: string;\n agentId?: string;\n operation?: string;\n metadata?: Record<string, any>;\n } = {}\n): CostEntry | null {\n const pricing = getPricing(provider, model);\n if (!pricing) {\n console.warn(`No pricing found for ${provider}/${model}`);\n return null;\n }\n\n const cost = calculateCost(usage, pricing);\n\n return logCost({\n provider,\n model,\n usage,\n cost,\n currency: pricing.currency,\n operation: options.operation || 'api_call',\n issueId: options.issueId,\n featureId: options.featureId,\n agentId: options.agentId,\n metadata: options.metadata,\n });\n}\n\n// ============== Cost Reading ==============\n\n/**\n * Read cost entries for a date range\n */\nexport function readCosts(startDate: string, endDate: string): CostEntry[] {\n const entries: CostEntry[] = [];\n\n const start = new Date(startDate);\n const end = new Date(endDate);\n\n for (let date = start; date <= end; date.setDate(date.getDate() + 1)) {\n const dateStr = date.toISOString().split('T')[0];\n const costFile = getCostFile(dateStr);\n\n if (existsSync(costFile)) {\n const content = readFileSync(costFile, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n\n for (const line of lines) {\n try {\n entries.push(JSON.parse(line));\n } catch {\n // Skip invalid entries\n }\n }\n }\n }\n\n return entries;\n}\n\n/**\n * Read costs for today\n */\nexport function readTodayCosts(): CostEntry[] {\n const today = getCurrentDateString();\n return readCosts(today, today);\n}\n\n/**\n * Read costs for an issue\n */\nexport function readIssueCosts(issueId: string, days: number = 30): CostEntry[] {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - days);\n\n const allCosts = readCosts(\n start.toISOString().split('T')[0],\n end.toISOString().split('T')[0]\n );\n\n return allCosts.filter(entry => entry.issueId === issueId);\n}\n\n// ============== Cost Aggregation ==============\n\n/**\n * Calculate cost summary for a set of entries\n */\nexport function summarizeCosts(entries: CostEntry[]): CostSummary {\n const summary: CostSummary = {\n totalCost: 0,\n currency: 'USD',\n period: {\n start: entries[0]?.timestamp || new Date().toISOString(),\n end: entries[entries.length - 1]?.timestamp || new Date().toISOString(),\n },\n byProvider: {} as Record<AIProvider, number>,\n byModel: {},\n byIssue: {},\n byFeature: {},\n entryCount: entries.length,\n totalTokens: {\n input: 0,\n output: 0,\n total: 0,\n },\n };\n\n for (const entry of entries) {\n summary.totalCost += entry.cost;\n\n // By provider\n summary.byProvider[entry.provider] =\n (summary.byProvider[entry.provider] || 0) + entry.cost;\n\n // By model\n summary.byModel[entry.model] =\n (summary.byModel[entry.model] || 0) + entry.cost;\n\n // By issue\n if (entry.issueId) {\n summary.byIssue[entry.issueId] =\n (summary.byIssue[entry.issueId] || 0) + entry.cost;\n }\n\n // By feature\n if (entry.featureId) {\n summary.byFeature[entry.featureId] =\n (summary.byFeature[entry.featureId] || 0) + entry.cost;\n }\n\n // Tokens\n summary.totalTokens.input += entry.usage.inputTokens;\n summary.totalTokens.output += entry.usage.outputTokens;\n }\n\n summary.totalTokens.total = summary.totalTokens.input + summary.totalTokens.output;\n summary.totalCost = Math.round(summary.totalCost * 100) / 100;\n\n return summary;\n}\n\n/**\n * Get daily cost summary\n */\nexport function getDailySummary(date?: string): CostSummary {\n const targetDate = date || getCurrentDateString();\n const entries = readCosts(targetDate, targetDate);\n return summarizeCosts(entries);\n}\n\n/**\n * Get weekly cost summary\n */\nexport function getWeeklySummary(): CostSummary {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n\n const entries = readCosts(\n start.toISOString().split('T')[0],\n end.toISOString().split('T')[0]\n );\n\n return summarizeCosts(entries);\n}\n\n/**\n * Get monthly cost summary\n */\nexport function getMonthlySummary(): CostSummary {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 30);\n\n const entries = readCosts(\n start.toISOString().split('T')[0],\n end.toISOString().split('T')[0]\n );\n\n return summarizeCosts(entries);\n}\n\n// ============== Cost Budgets ==============\n\nconst BUDGETS_FILE = join(COSTS_DIR, 'budgets.json');\n\nfunction loadBudgets(): CostBudget[] {\n if (!existsSync(BUDGETS_FILE)) {\n return [];\n }\n\n try {\n const content = readFileSync(BUDGETS_FILE, 'utf-8');\n return JSON.parse(content);\n } catch {\n return [];\n }\n}\n\nfunction saveBudgets(budgets: CostBudget[]): void {\n mkdirSync(COSTS_DIR, { recursive: true });\n writeFileSync(BUDGETS_FILE, JSON.stringify(budgets, null, 2));\n}\n\n/**\n * Create a cost budget\n */\nexport function createBudget(budget: Omit<CostBudget, 'id' | 'spent'>): CostBudget {\n const budgets = loadBudgets();\n\n const newBudget: CostBudget = {\n ...budget,\n id: `budget-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n spent: 0,\n };\n\n budgets.push(newBudget);\n saveBudgets(budgets);\n\n return newBudget;\n}\n\n/**\n * Get a budget by ID\n */\nexport function getBudget(id: string): CostBudget | null {\n const budgets = loadBudgets();\n return budgets.find(b => b.id === id) || null;\n}\n\n/**\n * Get all budgets\n */\nexport function getAllBudgets(): CostBudget[] {\n return loadBudgets();\n}\n\n/**\n * Update budget spent amount\n */\nexport function updateBudgetSpent(id: string, spent: number): boolean {\n const budgets = loadBudgets();\n const budget = budgets.find(b => b.id === id);\n\n if (!budget) return false;\n\n budget.spent = spent;\n saveBudgets(budgets);\n\n return true;\n}\n\n/**\n * Check budget status\n */\nexport function checkBudget(id: string): {\n budget: CostBudget | null;\n remaining: number;\n percentUsed: number;\n exceeded: boolean;\n alert: boolean;\n} {\n const budget = getBudget(id);\n\n if (!budget) {\n return {\n budget: null,\n remaining: 0,\n percentUsed: 0,\n exceeded: false,\n alert: false,\n };\n }\n\n const remaining = budget.limit - budget.spent;\n const percentUsed = budget.spent / budget.limit;\n\n return {\n budget,\n remaining,\n percentUsed,\n exceeded: percentUsed >= 1,\n alert: percentUsed >= budget.alertThreshold,\n };\n}\n\n/**\n * Delete a budget\n */\nexport function deleteBudget(id: string): boolean {\n const budgets = loadBudgets();\n const index = budgets.findIndex(b => b.id === id);\n\n if (index === -1) return false;\n\n budgets.splice(index, 1);\n saveBudgets(budgets);\n\n return true;\n}\n\n// ============== Reports ==============\n\n/**\n * Generate a cost report\n */\nexport function generateReport(startDate: string, endDate: string): string {\n const entries = readCosts(startDate, endDate);\n const summary = summarizeCosts(entries);\n\n const lines: string[] = [\n '# Cost Report',\n '',\n `**Period:** ${startDate} to ${endDate}`,\n '',\n '## Summary',\n '',\n `- **Total Cost:** $${summary.totalCost.toFixed(2)}`,\n `- **Total Entries:** ${summary.entryCount}`,\n `- **Total Tokens:** ${summary.totalTokens.total.toLocaleString()}`,\n ` - Input: ${summary.totalTokens.input.toLocaleString()}`,\n ` - Output: ${summary.totalTokens.output.toLocaleString()}`,\n '',\n '## By Provider',\n '',\n ];\n\n for (const [provider, cost] of Object.entries(summary.byProvider)) {\n lines.push(`- **${provider}:** $${cost.toFixed(2)}`);\n }\n\n lines.push('');\n lines.push('## By Model');\n lines.push('');\n\n for (const [model, cost] of Object.entries(summary.byModel)) {\n lines.push(`- **${model}:** $${cost.toFixed(2)}`);\n }\n\n if (Object.keys(summary.byIssue).length > 0) {\n lines.push('');\n lines.push('## By Issue');\n lines.push('');\n\n const sortedIssues = Object.entries(summary.byIssue)\n .sort(([, a], [, b]) => b - a);\n\n for (const [issue, cost] of sortedIssues.slice(0, 10)) {\n lines.push(`- **${issue}:** $${cost.toFixed(2)}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Format cost for display\n */\nexport function formatCost(cost: number, currency: string = 'USD'): string {\n if (currency === 'USD') {\n return `$${cost.toFixed(4)}`;\n }\n return `${cost.toFixed(4)} ${currency}`;\n}\n","/**\n * Cloister Runtime Abstraction\n *\n * Export all runtime types and provide a unified registry for managing\n * multiple AI coding assistant runtimes.\n */\n\nexport * from './types.js';\nexport { ClaudeCodeRuntime, createClaudeCodeRuntime } from './claude-code.js';\n\nimport type {\n AgentRuntime,\n RuntimeName,\n RuntimeRegistry as RuntimeRegistryInterface,\n} from './types.js';\nimport { getAgentState } from '../agents.js';\nimport { createClaudeCodeRuntime } from './claude-code.js';\n\n/**\n * Runtime registry implementation\n *\n * Manages multiple runtime adapters and provides lookup by agent ID.\n */\nexport class RuntimeRegistry implements RuntimeRegistryInterface {\n private runtimes: Map<RuntimeName, AgentRuntime> = new Map();\n\n /**\n * Register a runtime adapter\n */\n register(runtime: AgentRuntime): void {\n this.runtimes.set(runtime.name, runtime);\n }\n\n /**\n * Get a runtime by name\n */\n get(name: RuntimeName): AgentRuntime | undefined {\n return this.runtimes.get(name);\n }\n\n /**\n * Get all registered runtimes\n */\n getAll(): AgentRuntime[] {\n return Array.from(this.runtimes.values());\n }\n\n /**\n * Get the runtime for a specific agent\n *\n * Looks up the agent's state file to determine which runtime it's using.\n */\n getRuntimeForAgent(agentId: string): AgentRuntime | null {\n const state = getAgentState(agentId);\n if (!state) {\n return null;\n }\n\n // Map the state.runtime to a RuntimeName\n // The state.runtime may be 'claude', 'opencode', etc.\n let runtimeName: RuntimeName;\n\n switch (state.runtime) {\n case 'claude':\n case 'claude-code':\n runtimeName = 'claude-code';\n break;\n case 'opencode':\n runtimeName = 'opencode';\n break;\n case 'codex':\n runtimeName = 'codex';\n break;\n default:\n // Default to claude-code if unknown\n runtimeName = 'claude-code';\n }\n\n return this.get(runtimeName) || null;\n }\n}\n\n/**\n * Global runtime registry instance\n */\nlet globalRegistry: RuntimeRegistry | null = null;\n\n/**\n * Get the global runtime registry\n *\n * Creates a new registry if one doesn't exist.\n * Registers Claude Code runtime by default.\n */\nexport function getGlobalRegistry(): RuntimeRegistry {\n if (!globalRegistry) {\n globalRegistry = new RuntimeRegistry();\n\n // Register Claude Code runtime by default\n globalRegistry.register(createClaudeCodeRuntime());\n\n // TODO: Register other runtimes (OpenCode, Codex) when implemented\n }\n return globalRegistry;\n}\n\n/**\n * Set the global runtime registry\n *\n * Useful for testing or custom configurations.\n */\nexport function setGlobalRegistry(registry: RuntimeRegistry): void {\n globalRegistry = registry;\n}\n\n/**\n * Helper to get a runtime by name from the global registry\n */\nexport function getRuntime(name: RuntimeName): AgentRuntime | undefined {\n return getGlobalRegistry().get(name);\n}\n\n/**\n * Helper to get the runtime for an agent from the global registry\n */\nexport function getRuntimeForAgent(agentId: string): AgentRuntime | null {\n return getGlobalRegistry().getRuntimeForAgent(agentId);\n}\n","/**\n * Cloister Runtime Abstraction\n *\n * Types for agent health monitoring across different AI coding assistants.\n * This is separate from the general RuntimeAdapter (src/lib/runtime/) which handles\n * skill syncing and general runtime management.\n *\n * Cloister's runtime abstraction focuses on:\n * - Health monitoring (heartbeats, activity detection)\n * - Session management (finding sessions, reading session data)\n * - Cost tracking (token usage, estimated costs)\n * - Agent lifecycle (spawn, kill, message)\n */\n\n/**\n * Supported runtime types for agent execution\n */\nexport type RuntimeName = 'claude-code' | 'opencode' | 'codex';\n\n/**\n * Health state of an agent\n */\nexport type HealthState = 'active' | 'stale' | 'warning' | 'stuck';\n\n/**\n * Source of activity detection\n */\nexport type ActivitySource = 'jsonl' | 'tmux' | 'git' | 'active-heartbeat';\n\n/**\n * Heartbeat data from an agent\n */\nexport interface Heartbeat {\n timestamp: Date;\n agentId: string;\n source: ActivitySource;\n confidence: 'high' | 'medium' | 'low';\n toolName?: string;\n lastAction?: string;\n currentTask?: string;\n gitBranch?: string;\n workspace?: string;\n pid?: number;\n sessionId?: string;\n}\n\n/**\n * Token usage statistics\n */\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n}\n\n/**\n * Cost breakdown for a session\n */\nexport interface CostBreakdown {\n inputCost: number;\n outputCost: number;\n cacheReadCost: number;\n cacheWriteCost: number;\n totalCost: number;\n currency: 'USD';\n}\n\n/**\n * Agent session information\n */\nexport interface Session {\n id: string;\n agentId: string;\n workspace: string;\n model: string;\n startedAt: Date;\n lastActivity: Date;\n tokenUsage: TokenUsage;\n}\n\n/**\n * Configuration for spawning an agent\n */\nexport interface SpawnConfig {\n agentId: string;\n workspace: string;\n prompt?: string;\n model?: string;\n sessionId?: string; // For resuming existing sessions\n runtime?: RuntimeName;\n env?: Record<string, string>;\n}\n\n/**\n * Agent information\n */\nexport interface Agent {\n id: string;\n sessionId: string;\n runtime: RuntimeName;\n model: string;\n workspace: string;\n startedAt: Date;\n}\n\n/**\n * Runtime abstraction for agent health monitoring\n *\n * Each runtime (Claude Code, OpenCode, Codex) implements this interface\n * to provide Cloister with health monitoring capabilities.\n */\nexport interface AgentRuntime {\n /**\n * Runtime identifier\n */\n readonly name: RuntimeName;\n\n /**\n * Get the path to the session file/directory for an agent\n *\n * @param agentId - The agent identifier (e.g., \"agent-pan-18\")\n * @returns Path to the session storage\n *\n * @example\n * // Claude Code\n * \"/home/user/.claude/projects/workspace-123/sessions/abc123.jsonl\"\n *\n * // OpenCode\n * \"/home/user/.local/share/opencode/sessions/xyz789/\"\n */\n getSessionPath(agentId: string): string | null;\n\n /**\n * Get the last activity timestamp for an agent\n *\n * This is used for passive heartbeat detection (no agent modification needed).\n * Common sources:\n * - JSONL file modification time (Claude Code, Codex)\n * - SQLite database last update (OpenCode)\n * - Tmux window activity\n * - Git commits in workspace\n *\n * @param agentId - The agent identifier\n * @returns Last activity timestamp, or null if agent not found\n */\n getLastActivity(agentId: string): Date | null;\n\n /**\n * Get a heartbeat from an agent\n *\n * Attempts to read an active heartbeat (if hooks configured), falls back\n * to passive detection via file timestamps.\n *\n * @param agentId - The agent identifier\n * @returns Heartbeat data, or null if agent not found\n */\n getHeartbeat(agentId: string): Heartbeat | null;\n\n /**\n * Get token usage for an agent's current session\n *\n * @param agentId - The agent identifier\n * @returns Token usage statistics, or null if not available\n */\n getTokenUsage(agentId: string): TokenUsage | null;\n\n /**\n * Get cost breakdown for an agent's current session\n *\n * @param agentId - The agent identifier\n * @returns Cost breakdown, or null if not available\n */\n getSessionCost(agentId: string): CostBreakdown | null;\n\n /**\n * Send a message to a running agent\n *\n * This typically uses tmux send-keys to inject a message into the agent's\n * terminal session.\n *\n * @param agentId - The agent identifier\n * @param message - The message to send\n * @throws Error if agent is not running\n */\n sendMessage(agentId: string, message: string): void;\n\n /**\n * Kill an agent (terminate the session)\n *\n * This typically kills the tmux session and cleans up any state files.\n *\n * @param agentId - The agent identifier\n * @throws Error if agent cannot be killed\n */\n killAgent(agentId: string): void;\n\n /**\n * Spawn a new agent\n *\n * Creates a tmux session and starts the runtime with the given configuration.\n *\n * @param config - Spawn configuration\n * @returns Agent information\n * @throws Error if spawn fails\n */\n spawnAgent(config: SpawnConfig): Agent;\n\n /**\n * List all sessions for this runtime\n *\n * @param workspace - Optional workspace filter\n * @returns Array of session information\n */\n listSessions(workspace?: string): Session[];\n\n /**\n * Check if an agent is running\n *\n * @param agentId - The agent identifier\n * @returns True if agent has an active tmux session\n */\n isRunning(agentId: string): boolean;\n}\n\n/**\n * Registry for managing multiple runtimes\n */\nexport interface RuntimeRegistry {\n /**\n * Register a runtime\n */\n register(runtime: AgentRuntime): void;\n\n /**\n * Get a runtime by name\n */\n get(name: RuntimeName): AgentRuntime | undefined;\n\n /**\n * Get all registered runtimes\n */\n getAll(): AgentRuntime[];\n\n /**\n * Get the runtime for a specific agent\n *\n * Looks up the agent's state file to determine which runtime it's using.\n */\n getRuntimeForAgent(agentId: string): AgentRuntime | null;\n}\n","/**\n * Claude Code Runtime Implementation\n *\n * Implements AgentRuntime for Claude Code CLI.\n *\n * Session storage: ~/.claude/projects/<workspace-hash>/<session-id>.jsonl\n * Session index: ~/.claude/projects/<workspace-hash>/sessions-index.json\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync, mkdirSync } from 'fs';\nimport { join, basename } from 'path';\nimport { homedir } from 'os';\nimport type {\n AgentRuntime,\n Heartbeat,\n TokenUsage,\n CostBreakdown,\n Session,\n SpawnConfig,\n Agent,\n ActivitySource,\n} from './types.js';\nimport { getAgentState, getAgentDir, spawnAgent as spawnAgentImpl } from '../agents.js';\nimport { sessionExists, killSession, sendKeys, getAgentSessions } from '../tmux.js';\nimport { parseClaudeSession, getSessionFiles, getProjectDirs } from '../cost-parsers/jsonl-parser.js';\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\n/**\n * Claude Code session index entry\n */\ninterface SessionIndexEntry {\n sessionId: string;\n createdAt: string;\n updatedAt: string;\n filePath: string;\n}\n\n/**\n * Claude Code Runtime implementation\n */\nexport class ClaudeCodeRuntime implements AgentRuntime {\n readonly name = 'claude-code' as const;\n\n /**\n * Get the project directory for a workspace\n *\n * Claude Code hashes the workspace path to create project directories.\n * We need to find the project directory that contains sessions for this workspace.\n */\n private getProjectDirForWorkspace(workspace: string): string | null {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) {\n return null;\n }\n\n // Get all project directories\n const projectDirs = getProjectDirs();\n\n for (const projectDir of projectDirs) {\n // Check if this project's sessions-index.json references the workspace\n const indexPath = join(projectDir, 'sessions-index.json');\n if (existsSync(indexPath)) {\n try {\n const indexContent = readFileSync(indexPath, 'utf-8');\n // Sessions index contains the workspace path\n if (indexContent.includes(workspace)) {\n return projectDir;\n }\n } catch {\n // Skip invalid index files\n }\n }\n }\n\n return null;\n }\n\n /**\n * Get the active session ID for an agent from the sessions index\n */\n private getActiveSessionId(projectDir: string): string | null {\n const indexPath = join(projectDir, 'sessions-index.json');\n if (!existsSync(indexPath)) {\n return null;\n }\n\n try {\n const indexContent = readFileSync(indexPath, 'utf-8');\n const index = JSON.parse(indexContent);\n\n // The sessions-index.json has a structure like:\n // { \"sessions\": [{ \"sessionId\": \"...\", \"filePath\": \"...\", ... }] }\n // Find the most recent session\n if (index.sessions && Array.isArray(index.sessions)) {\n const sessions = index.sessions as SessionIndexEntry[];\n if (sessions.length === 0) return null;\n\n // Sort by updatedAt and get the most recent\n const sorted = sessions.sort((a, b) => {\n return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();\n });\n\n return sorted[0].sessionId;\n }\n } catch {\n // Skip invalid index files\n }\n\n return null;\n }\n\n /**\n * Get the most recent JSONL file for a project\n */\n private getMostRecentJSONL(projectDir: string): string | null {\n const files = getSessionFiles(projectDir);\n return files.length > 0 ? files[0] : null;\n }\n\n /**\n * Get the session path for an agent\n */\n getSessionPath(agentId: string): string | null {\n const state = getAgentState(agentId);\n if (!state) {\n return null;\n }\n\n const projectDir = this.getProjectDirForWorkspace(state.workspace);\n if (!projectDir) {\n return null;\n }\n\n // Try to get active session from index\n const sessionId = this.getActiveSessionId(projectDir);\n if (sessionId) {\n const sessionPath = join(projectDir, `${sessionId}.jsonl`);\n if (existsSync(sessionPath)) {\n return sessionPath;\n }\n }\n\n // Fall back to most recent JSONL file\n return this.getMostRecentJSONL(projectDir);\n }\n\n /**\n * Get last activity timestamp for an agent\n *\n * Uses passive detection via JSONL file modification time.\n */\n getLastActivity(agentId: string): Date | null {\n const sessionPath = this.getSessionPath(agentId);\n if (!sessionPath || !existsSync(sessionPath)) {\n return null;\n }\n\n try {\n const stat = statSync(sessionPath);\n return stat.mtime;\n } catch {\n return null;\n }\n }\n\n /**\n * Read active heartbeat file if it exists\n */\n private getActiveHeartbeat(agentId: string): Heartbeat | null {\n // Heartbeats are now in shared directory: ~/.panopticon/heartbeats/\n const heartbeatPath = join(homedir(), '.panopticon', 'heartbeats', `${agentId}.json`);\n if (!existsSync(heartbeatPath)) {\n return null;\n }\n\n try {\n const content = readFileSync(heartbeatPath, 'utf-8');\n const data = JSON.parse(content);\n\n // Check if heartbeat is recent (within 5 minutes)\n const timestamp = new Date(data.timestamp);\n const now = new Date();\n const ageMs = now.getTime() - timestamp.getTime();\n if (ageMs > 5 * 60 * 1000) {\n // Heartbeat is stale\n return null;\n }\n\n return {\n timestamp,\n agentId: data.agent_id || agentId,\n source: 'active-heartbeat',\n confidence: 'high',\n toolName: data.tool_name,\n lastAction: data.last_action,\n currentTask: data.current_task,\n gitBranch: data.git_branch,\n workspace: data.workspace,\n pid: data.pid,\n sessionId: data.session_id,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Get passive heartbeat from file timestamps\n */\n private getPassiveHeartbeat(agentId: string): Heartbeat | null {\n const lastActivity = this.getLastActivity(agentId);\n if (!lastActivity) {\n return null;\n }\n\n return {\n timestamp: lastActivity,\n agentId,\n source: 'jsonl',\n confidence: 'medium',\n };\n }\n\n /**\n * Get heartbeat for an agent\n *\n * Tries active heartbeat first (if hooks configured), falls back to passive.\n */\n getHeartbeat(agentId: string): Heartbeat | null {\n // Try active heartbeat first\n const activeHeartbeat = this.getActiveHeartbeat(agentId);\n if (activeHeartbeat) {\n return activeHeartbeat;\n }\n\n // Fall back to passive detection\n return this.getPassiveHeartbeat(agentId);\n }\n\n /**\n * Get token usage for an agent's current session\n */\n getTokenUsage(agentId: string): TokenUsage | null {\n const sessionPath = this.getSessionPath(agentId);\n if (!sessionPath) {\n return null;\n }\n\n const sessionUsage = parseClaudeSession(sessionPath);\n if (!sessionUsage) {\n return null;\n }\n\n return sessionUsage.usage;\n }\n\n /**\n * Get cost breakdown for an agent's current session\n */\n getSessionCost(agentId: string): CostBreakdown | null {\n const sessionPath = this.getSessionPath(agentId);\n if (!sessionPath) {\n return null;\n }\n\n const sessionUsage = parseClaudeSession(sessionPath);\n if (!sessionUsage) {\n return null;\n }\n\n // Calculate breakdown based on token usage\n // Prices for Claude Sonnet 4 (most common)\n // TODO: Use actual model pricing from session\n const inputPrice = 3.0 / 1_000_000; // $3 per 1M input tokens\n const outputPrice = 15.0 / 1_000_000; // $15 per 1M output tokens\n const cacheReadPrice = 0.3 / 1_000_000; // $0.30 per 1M cache read tokens\n const cacheWritePrice = 3.75 / 1_000_000; // $3.75 per 1M cache write tokens\n\n const usage = sessionUsage.usage;\n const inputCost = usage.inputTokens * inputPrice;\n const outputCost = usage.outputTokens * outputPrice;\n const cacheReadCost = (usage.cacheReadTokens || 0) * cacheReadPrice;\n const cacheWriteCost = (usage.cacheWriteTokens || 0) * cacheWritePrice;\n\n return {\n inputCost,\n outputCost,\n cacheReadCost,\n cacheWriteCost,\n totalCost: inputCost + outputCost + cacheReadCost + cacheWriteCost,\n currency: 'USD',\n };\n }\n\n /**\n * Send a message to a running agent\n */\n sendMessage(agentId: string, message: string): void {\n if (!sessionExists(agentId)) {\n throw new Error(`Agent ${agentId} is not running`);\n }\n\n sendKeys(agentId, message);\n\n // Also save to mail queue for persistence\n const mailDir = join(getAgentDir(agentId), 'mail');\n mkdirSync(mailDir, { recursive: true });\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const fs = require('fs');\n fs.writeFileSync(\n join(mailDir, `${timestamp}.md`),\n `# Message\\n\\n${message}\\n`\n );\n }\n\n /**\n * Kill an agent\n */\n killAgent(agentId: string): void {\n if (!sessionExists(agentId)) {\n throw new Error(`Agent ${agentId} is not running`);\n }\n\n killSession(agentId);\n\n // Update agent state\n const state = getAgentState(agentId);\n if (state) {\n state.status = 'stopped';\n const { saveAgentState } = require('../agents.js');\n saveAgentState(state);\n }\n }\n\n /**\n * Spawn a new agent\n */\n spawnAgent(config: SpawnConfig): Agent {\n // Use the existing spawnAgent implementation from agents.ts\n const state = spawnAgentImpl({\n issueId: config.agentId.replace(/^agent-/, ''),\n workspace: config.workspace,\n runtime: 'claude',\n model: config.model || 'sonnet',\n prompt: config.prompt,\n });\n\n // Get the session ID (we'll need to look it up from the workspace)\n const projectDir = this.getProjectDirForWorkspace(config.workspace);\n const sessionId = projectDir ? this.getActiveSessionId(projectDir) : undefined;\n\n return {\n id: state.id,\n sessionId: sessionId || 'unknown',\n runtime: 'claude-code',\n model: state.model,\n workspace: state.workspace,\n startedAt: new Date(state.startedAt),\n };\n }\n\n /**\n * List all sessions for this runtime\n */\n listSessions(workspace?: string): Session[] {\n const sessions: Session[] = [];\n\n if (workspace) {\n // Get sessions for specific workspace\n const projectDir = this.getProjectDirForWorkspace(workspace);\n if (projectDir) {\n const files = getSessionFiles(projectDir);\n for (const file of files) {\n const session = this.parseSessionFile(file, workspace);\n if (session) {\n sessions.push(session);\n }\n }\n }\n } else {\n // Get all sessions\n const projectDirs = getProjectDirs();\n for (const projectDir of projectDirs) {\n const files = getSessionFiles(projectDir);\n for (const file of files) {\n const session = this.parseSessionFile(file);\n if (session) {\n sessions.push(session);\n }\n }\n }\n }\n\n return sessions;\n }\n\n /**\n * Parse a session file into a Session object\n */\n private parseSessionFile(file: string, workspace?: string): Session | null {\n const sessionUsage = parseClaudeSession(file);\n if (!sessionUsage) {\n return null;\n }\n\n const stat = statSync(file);\n\n return {\n id: sessionUsage.sessionId,\n agentId: 'unknown', // We'd need to reverse-lookup from agent state\n workspace: workspace || 'unknown',\n model: sessionUsage.model,\n startedAt: new Date(sessionUsage.startTime),\n lastActivity: stat.mtime,\n tokenUsage: sessionUsage.usage,\n };\n }\n\n /**\n * Check if an agent is running\n */\n isRunning(agentId: string): boolean {\n return sessionExists(agentId);\n }\n}\n\n/**\n * Create a Claude Code runtime instance\n */\nexport function createClaudeCodeRuntime(): ClaudeCodeRuntime {\n return new ClaudeCodeRuntime();\n}\n","/**\n * Handoff Triggers\n *\n * Detects conditions that should trigger model handoffs:\n * 1. Stuck escalation - Agent inactive for too long\n * 2. Planning complete - Planning phase finished, ready for implementation\n * 3. Test failure - Tests failing, need more powerful model\n * 4. Task completion - Implementation done, ready for specialist testing\n */\n\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport type { AgentHealth } from './health.js';\nimport type { CloisterConfig } from './config.js';\nimport { loadCloisterConfig } from './config.js';\n\n/**\n * Trigger type\n */\nexport type TriggerType =\n | 'stuck_escalation'\n | 'planning_complete'\n | 'test_failure'\n | 'task_complete'\n | 'manual';\n\n/**\n * Trigger detection result\n */\nexport interface TriggerDetection {\n triggered: boolean;\n type: TriggerType;\n reason: string;\n suggestedModel?: string;\n confidence: 'high' | 'medium' | 'low';\n}\n\n/**\n * Check if agent should be handed off due to stuck escalation\n *\n * Model-specific thresholds:\n * - Haiku: Stuck after 10 minutes → escalate to Sonnet\n * - Sonnet: Stuck after 20 minutes → escalate to Opus\n * - Opus: Stuck after 30 minutes → alert user (no auto-escalation)\n *\n * @param health - Agent health state\n * @param currentModel - Current model\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkStuckEscalation(\n health: AgentHealth,\n currentModel: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get stuck escalation config\n const stuckConfig = conf.handoffs?.auto_triggers?.stuck_escalation;\n if (!stuckConfig?.enabled) {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: 'Stuck escalation disabled in config',\n confidence: 'high',\n };\n }\n\n // Check if agent is stuck based on health state\n if (health.state !== 'stuck') {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: `Agent is ${health.state}, not stuck`,\n confidence: 'high',\n };\n }\n\n // Get minutes since last activity\n if (!health.lastActivity) {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: 'No last activity timestamp available',\n confidence: 'low',\n };\n }\n const minutesSinceActivity = (Date.now() - health.lastActivity.getTime()) / (1000 * 60);\n\n // Check model-specific thresholds\n if (currentModel === 'haiku' && minutesSinceActivity >= stuckConfig.haiku_to_sonnet_minutes) {\n return {\n triggered: true,\n type: 'stuck_escalation',\n reason: `Haiku agent stuck for ${Math.round(minutesSinceActivity)} minutes`,\n suggestedModel: 'sonnet',\n confidence: 'high',\n };\n }\n\n if (currentModel === 'sonnet' && minutesSinceActivity >= stuckConfig.sonnet_to_opus_minutes) {\n return {\n triggered: true,\n type: 'stuck_escalation',\n reason: `Sonnet agent stuck for ${Math.round(minutesSinceActivity)} minutes`,\n suggestedModel: 'opus',\n confidence: 'high',\n };\n }\n\n if (currentModel === 'opus') {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: 'Opus agent stuck - no higher model available, manual intervention needed',\n confidence: 'high',\n };\n }\n\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: `Agent stuck but threshold not reached (${Math.round(minutesSinceActivity)} minutes)`,\n confidence: 'medium',\n };\n}\n\n/**\n * Check if planning phase is complete\n *\n * Multi-signal detection:\n * 1. Primary: Beads task with \"plan\" in title is closed\n * 2. Secondary: PRD file created at docs/prds/active/{issue}-plan.md\n * 3. Tertiary: Agent used ExitPlanMode tool (if detectable)\n *\n * @param agentId - Agent ID\n * @param workspace - Workspace path\n * @param issueId - Issue ID\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkPlanningComplete(\n agentId: string,\n workspace: string,\n issueId: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get planning complete config\n const planningConfig = conf.handoffs?.auto_triggers?.planning_complete;\n if (!planningConfig?.enabled) {\n return {\n triggered: false,\n type: 'planning_complete',\n reason: 'Planning complete detection disabled in config',\n confidence: 'high',\n };\n }\n\n const signals: string[] = [];\n let signalCount = 0;\n\n // Signal 1: Check for closed beads task with \"plan\" in title\n try {\n const output = execSync(`bd list --json -l ${issueId.toLowerCase()} --status closed`, {\n encoding: 'utf-8',\n });\n const tasks = JSON.parse(output);\n const planTask = tasks.find((t: any) =>\n t.title.toLowerCase().includes('plan') ||\n t.labels?.includes('planning')\n );\n if (planTask) {\n signals.push(`Beads planning task closed: ${planTask.id}`);\n signalCount++;\n }\n } catch (error) {\n // Beads not available or error querying\n }\n\n // Signal 2: Check for PRD file\n const prdPath = join(workspace, `docs/prds/active/${issueId.toLowerCase()}-plan.md`);\n if (existsSync(prdPath)) {\n signals.push('PRD file exists');\n signalCount++;\n }\n\n // Signal 3: Check for ExitPlanMode usage (TODO: requires hook integration)\n // This would require reading the session JSONL and checking for ExitPlanMode tool use\n // Skipping for now\n\n // Trigger if we have at least 2 signals\n if (signalCount >= 2) {\n return {\n triggered: true,\n type: 'planning_complete',\n reason: `Planning complete detected: ${signals.join(', ')}`,\n suggestedModel: planningConfig.to_model,\n confidence: 'high',\n };\n }\n\n if (signalCount === 1) {\n return {\n triggered: false,\n type: 'planning_complete',\n reason: `Planning possibly complete (${signals.join(', ')}) but need more signals`,\n confidence: 'medium',\n };\n }\n\n return {\n triggered: false,\n type: 'planning_complete',\n reason: 'No planning completion signals detected',\n confidence: 'high',\n };\n}\n\n/**\n * Check if test failures should trigger escalation\n *\n * Aggressive escalation: Any test failure from Haiku escalates to Sonnet\n * Reasoning: Haiku is for simple tasks - if tests fail, the task isn't simple\n *\n * @param workspace - Workspace path\n * @param currentModel - Current model\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkTestFailure(\n workspace: string,\n currentModel: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get test failure config\n const testConfig = conf.handoffs?.auto_triggers?.test_failure;\n if (!testConfig?.enabled) {\n return {\n triggered: false,\n type: 'test_failure',\n reason: 'Test failure escalation disabled in config',\n confidence: 'high',\n };\n }\n\n // Only escalate from Haiku or configured from_model\n if (currentModel !== testConfig.from_model) {\n return {\n triggered: false,\n type: 'test_failure',\n reason: `Test failure escalation only applies to ${testConfig.from_model} model`,\n confidence: 'high',\n };\n }\n\n // Check for test failures\n // Look for common test result files/patterns\n const testFailure = detectTestFailure(workspace);\n\n if (testFailure.failed) {\n return {\n triggered: true,\n type: 'test_failure',\n reason: `Test failures detected: ${testFailure.reason}`,\n suggestedModel: testConfig.to_model,\n confidence: testFailure.confidence,\n };\n }\n\n return {\n triggered: false,\n type: 'test_failure',\n reason: 'No test failures detected',\n confidence: 'medium',\n };\n}\n\n/**\n * Detect test failures in workspace\n *\n * Checks for:\n * - npm test output\n * - Jest results\n * - pytest results\n * - cargo test results\n *\n * @param workspace - Workspace path\n * @returns Test failure detection\n */\nfunction detectTestFailure(workspace: string): {\n failed: boolean;\n reason: string;\n confidence: 'high' | 'medium' | 'low';\n} {\n // TODO: Implement proper test result detection\n // For now, this is a placeholder that checks for common test result files\n\n // Check for .test-results or similar\n const commonTestPaths = [\n '.test-results',\n 'test-results',\n 'junit.xml',\n 'coverage',\n '.nyc_output',\n ];\n\n // This is a simplified check - in reality we'd parse test output\n return {\n failed: false,\n reason: 'Test result detection not yet implemented',\n confidence: 'low',\n };\n}\n\n/**\n * Check if implementation is complete and ready for testing\n *\n * Detection:\n * - Beads task with \"implement\" in title is closed\n * - No remaining implementation tasks\n *\n * @param issueId - Issue ID\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkTaskCompletion(\n issueId: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get task completion config\n const completionConfig = conf.handoffs?.auto_triggers?.implementation_complete;\n if (!completionConfig?.enabled) {\n return {\n triggered: false,\n type: 'task_complete',\n reason: 'Task completion detection disabled in config',\n confidence: 'high',\n };\n }\n\n // Check for closed implementation task\n try {\n const output = execSync(`bd list --json -l ${issueId.toLowerCase()} --status closed`, {\n encoding: 'utf-8',\n });\n const tasks = JSON.parse(output);\n const implementTask = tasks.find((t: any) =>\n t.title.toLowerCase().includes('implement') ||\n t.labels?.includes('implementation')\n );\n\n if (implementTask) {\n // Check if there are remaining open tasks\n const openOutput = execSync(`bd list --json -l ${issueId.toLowerCase()} --status open`, {\n encoding: 'utf-8',\n });\n const openTasks = JSON.parse(openOutput);\n\n if (openTasks.length === 0) {\n return {\n triggered: true,\n type: 'task_complete',\n reason: 'Implementation task closed, no remaining tasks',\n suggestedModel: completionConfig.to_specialist,\n confidence: 'high',\n };\n } else {\n return {\n triggered: false,\n type: 'task_complete',\n reason: `Implementation task closed but ${openTasks.length} tasks remain`,\n confidence: 'medium',\n };\n }\n }\n } catch (error) {\n // Beads not available or error querying\n }\n\n return {\n triggered: false,\n type: 'task_complete',\n reason: 'No implementation completion signals detected',\n confidence: 'high',\n };\n}\n\n/**\n * Check all triggers for an agent\n *\n * @param agentId - Agent ID\n * @param workspace - Workspace path\n * @param issueId - Issue ID\n * @param currentModel - Current model\n * @param health - Agent health state\n * @param config - Cloister configuration\n * @returns Array of triggered detections\n */\nexport function checkAllTriggers(\n agentId: string,\n workspace: string,\n issueId: string,\n currentModel: string,\n health: AgentHealth,\n config?: CloisterConfig\n): TriggerDetection[] {\n const triggers: TriggerDetection[] = [];\n\n // Check each trigger type\n const stuckCheck = checkStuckEscalation(health, currentModel, config);\n if (stuckCheck.triggered) triggers.push(stuckCheck);\n\n const planningCheck = checkPlanningComplete(agentId, workspace, issueId, config);\n if (planningCheck.triggered) triggers.push(planningCheck);\n\n const testCheck = checkTestFailure(workspace, currentModel, config);\n if (testCheck.triggered) triggers.push(testCheck);\n\n const completionCheck = checkTaskCompletion(issueId, config);\n if (completionCheck.triggered) triggers.push(completionCheck);\n\n return triggers;\n}\n","/**\n * Handoff Manager\n *\n * Orchestrates model handoffs for running agents using two methods:\n * 1. Kill & Spawn: For general agents (clean handoff with context preservation)\n * 2. Specialist Wake: For permanent specialists (resume with preserved context)\n */\n\nimport { existsSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport type { AgentState } from '../agents.js';\nimport { getAgentState, saveAgentState, stopAgent, spawnAgent, getAgentDir } from '../agents.js';\nimport type { HandoffContext } from './handoff-context.js';\nimport { captureHandoffContext, buildHandoffPrompt } from './handoff-context.js';\nimport { sessionExists } from '../tmux.js';\n\n/**\n * Handoff method type\n */\nexport type HandoffMethod = 'kill-spawn' | 'specialist-wake';\n\n/**\n * Handoff result\n */\nexport interface HandoffResult {\n success: boolean;\n method: HandoffMethod;\n newAgentId?: string;\n newSessionId?: string;\n context?: HandoffContext;\n error?: string;\n}\n\n/**\n * Handoff options\n */\nexport interface HandoffOptions {\n targetModel: string;\n reason: string;\n method?: HandoffMethod; // Auto-detect if not specified\n waitForIdle?: boolean; // Wait for agent to be idle before killing (default: true)\n idleTimeoutMs?: number; // How long to wait for idle (default: 30000)\n additionalInstructions?: string; // Extra instructions for new agent\n}\n\n/**\n * Perform a model handoff for an agent\n *\n * Auto-selects handoff method based on agent type:\n * - Specialists (merge-agent, test-agent, etc.): Use specialist-wake\n * - General agents: Use kill-spawn\n *\n * @param agentId - Agent to hand off\n * @param options - Handoff options\n * @returns Handoff result\n */\nexport async function performHandoff(\n agentId: string,\n options: HandoffOptions\n): Promise<HandoffResult> {\n // Get current agent state\n const state = getAgentState(agentId);\n if (!state) {\n return {\n success: false,\n method: 'kill-spawn',\n error: `Agent ${agentId} not found`,\n };\n }\n\n // Auto-detect method if not specified\n const method = options.method || detectHandoffMethod(agentId);\n\n // Execute appropriate handoff method\n if (method === 'specialist-wake') {\n return await performSpecialistWake(state, options);\n } else {\n return await performKillAndSpawn(state, options);\n }\n}\n\n/**\n * Detect appropriate handoff method for an agent\n *\n * @param agentId - Agent ID\n * @returns Handoff method\n */\nfunction detectHandoffMethod(agentId: string): HandoffMethod {\n // Specialists use specialist-wake (context-preserving resume)\n const specialists = ['merge-agent', 'review-agent', 'test-agent', 'planning-agent'];\n if (specialists.some(s => agentId.includes(s))) {\n return 'specialist-wake';\n }\n\n // General agents use kill-spawn\n return 'kill-spawn';\n}\n\n/**\n * Kill & Spawn handoff method\n *\n * Process:\n * 1. Signal agent to save state (update STATE.md)\n * 2. Wait for idle (check for activity)\n * 3. Capture handoff context\n * 4. Kill current agent\n * 5. Build handoff prompt\n * 6. Spawn new agent with target model\n *\n * @param state - Current agent state\n * @param options - Handoff options\n * @returns Handoff result\n */\nasync function performKillAndSpawn(\n state: AgentState,\n options: HandoffOptions\n): Promise<HandoffResult> {\n try {\n // Step 1: Signal agent to save state\n // TODO: Send message to agent asking to update STATE.md\n // For now, we'll capture what's there\n\n // Step 2: Wait for idle if requested\n if (options.waitForIdle !== false) {\n const timeout = options.idleTimeoutMs || 30000;\n const idle = await waitForIdle(state.id, timeout);\n if (!idle) {\n console.warn(`Agent ${state.id} did not become idle within ${timeout}ms`);\n }\n }\n\n // Step 3: Capture handoff context\n const context = await captureHandoffContext(state, options.targetModel, options.reason);\n\n // Step 4: Kill current agent\n stopAgent(state.id);\n\n // Step 5: Build handoff prompt\n const prompt = buildHandoffPrompt(context, options.additionalInstructions);\n\n // Save handoff prompt for debugging\n const handoffDir = join(getAgentDir(state.id), 'handoffs');\n mkdirSync(handoffDir, { recursive: true });\n const handoffFile = join(handoffDir, `handoff-${Date.now()}.md`);\n writeFileSync(handoffFile, prompt);\n\n // Step 6: Spawn new agent with target model\n // Use same agent ID to preserve identity\n const newState = spawnAgent({\n issueId: state.issueId,\n workspace: state.workspace,\n runtime: state.runtime,\n model: options.targetModel,\n prompt,\n });\n\n // Update handoff metrics\n newState.handoffCount = (state.handoffCount || 0) + 1;\n newState.costSoFar = state.costSoFar || 0;\n newState.complexity = state.complexity;\n saveAgentState(newState);\n\n return {\n success: true,\n method: 'kill-spawn',\n newAgentId: newState.id,\n context,\n };\n } catch (error) {\n return {\n success: false,\n method: 'kill-spawn',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Specialist Wake handoff method\n *\n * Process:\n * 1. Capture handoff context\n * 2. Use `claude --resume {sessionId}` to wake specialist\n * 3. Pass task-specific prompt\n * 4. Faster context loading, specialist expertise retained\n *\n * NOTE: This requires the specialist to have been initialized first.\n * Specialists are persistent sessions that can be resumed.\n *\n * @param state - Current agent state\n * @param options - Handoff options\n * @returns Handoff result\n */\nasync function performSpecialistWake(\n state: AgentState,\n options: HandoffOptions\n): Promise<HandoffResult> {\n try {\n // Step 1: Capture handoff context\n const context = await captureHandoffContext(state, options.targetModel, options.reason);\n\n // Step 2: Build task prompt for specialist\n const prompt = buildHandoffPrompt(context, options.additionalInstructions);\n\n // Step 3: Wake specialist using --resume\n // Determine specialist session ID from agent ID\n const specialistName = extractSpecialistName(state.id);\n if (!specialistName) {\n return {\n success: false,\n method: 'specialist-wake',\n error: 'Could not determine specialist name from agent ID',\n };\n }\n\n // Check if specialist session exists\n // TODO: Implement specialist session tracking\n // For now, fall back to kill-spawn\n console.warn(`Specialist wake not yet fully implemented, falling back to kill-spawn`);\n return await performKillAndSpawn(state, options);\n\n // Future implementation:\n // const specialistSessionId = await getSpecialistSessionId(specialistName);\n // if (!specialistSessionId) {\n // return { success: false, method: 'specialist-wake', error: 'Specialist session not found' };\n // }\n //\n // // Resume specialist with new task\n // execSync(`claude --resume ${specialistSessionId} --model ${options.targetModel}`, {\n // cwd: state.workspace,\n // });\n //\n // // Send prompt\n // messageAgent(state.id, prompt);\n //\n // return {\n // success: true,\n // method: 'specialist-wake',\n // newSessionId: specialistSessionId,\n // context,\n // };\n } catch (error) {\n return {\n success: false,\n method: 'specialist-wake',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Wait for agent to become idle\n *\n * @param agentId - Agent ID\n * @param timeoutMs - Timeout in milliseconds\n * @returns True if agent became idle, false if timeout\n */\nasync function waitForIdle(agentId: string, timeoutMs: number): Promise<boolean> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n // Check if agent session still exists\n if (!sessionExists(agentId)) {\n return true; // Agent is gone, consider it idle\n }\n\n // Check for recent activity\n // TODO: Implement proper activity detection\n // For now, just wait a bit\n await sleep(1000);\n }\n\n return false; // Timeout\n}\n\n/**\n * Extract specialist name from agent ID\n *\n * @param agentId - Agent ID (e.g., \"agent-merge-pan-18\")\n * @returns Specialist name or null\n */\nfunction extractSpecialistName(agentId: string): string | null {\n const specialists = ['merge-agent', 'review-agent', 'test-agent', 'planning-agent'];\n for (const specialist of specialists) {\n if (agentId.includes(specialist.replace('-agent', ''))) {\n return specialist;\n }\n }\n return null;\n}\n\n/**\n * Sleep helper\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Check if handoff is recommended for an agent\n *\n * This is a placeholder for future trigger logic.\n * Triggers will be implemented in Phase C.\n *\n * @param agentId - Agent ID\n * @returns True if handoff is recommended\n */\nexport function shouldHandoff(agentId: string): boolean {\n // TODO: Implement trigger logic in Phase C\n return false;\n}\n","/**\n * Handoff Context Module\n *\n * Captures and serializes agent context for handoffs between models.\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport type { TokenUsage } from '../runtimes/types.js';\nimport type { ComplexityLevel } from './complexity.js';\nimport type { AgentState } from '../agents.js';\nimport { getAgentDir } from '../agents.js';\n\n/**\n * Beads task snapshot for handoff\n */\nexport interface BeadsTask {\n id: string;\n title: string;\n description?: string;\n status: 'open' | 'in_progress' | 'closed';\n priority: number;\n labels?: string[];\n complexity?: ComplexityLevel;\n}\n\n/**\n * Handoff context - captures full state for agent transition\n */\nexport interface HandoffContext {\n // Agent identity\n issueId: string;\n agentId: string;\n workspace: string;\n\n // Source info\n previousModel: string;\n previousRuntime: 'claude-code';\n previousSessionId?: string;\n\n // Files\n stateFile?: string; // .planning/STATE.md content\n claudeMd?: string; // CLAUDE.md content\n\n // Git state\n gitBranch?: string;\n uncommittedFiles?: string[];\n lastCommit?: string;\n\n // Beads state\n activeBeadsTasks?: BeadsTask[];\n remainingTasks?: BeadsTask[];\n completedTasks?: BeadsTask[];\n\n // AI summaries\n whatWasDone?: string;\n whatRemains?: string;\n blockers?: string[];\n decisions?: string[];\n\n // Metrics\n tokenUsage?: TokenUsage;\n costSoFar?: number;\n handoffCount?: number;\n\n // New agent target\n targetModel: string;\n reason: string;\n}\n\n/**\n * Capture full handoff context from an agent\n *\n * @param agentState - Current agent state\n * @param targetModel - Model to hand off to\n * @param reason - Reason for handoff\n * @returns Handoff context\n */\nexport async function captureHandoffContext(\n agentState: AgentState,\n targetModel: string,\n reason: string\n): Promise<HandoffContext> {\n const context: HandoffContext = {\n issueId: agentState.issueId,\n agentId: agentState.id,\n workspace: agentState.workspace,\n previousModel: agentState.model,\n previousRuntime: 'claude-code',\n previousSessionId: agentState.sessionId,\n targetModel,\n reason,\n handoffCount: agentState.handoffCount || 0,\n costSoFar: agentState.costSoFar || 0,\n };\n\n // Capture files (STATE.md, CLAUDE.md)\n await captureFiles(context, agentState.workspace);\n\n // Capture git state\n await captureGitState(context, agentState.workspace);\n\n // Capture beads tasks\n await captureBeadsTasks(context, agentState.issueId);\n\n return context;\n}\n\n/**\n * Capture workspace files (STATE.md, CLAUDE.md)\n */\nasync function captureFiles(context: HandoffContext, workspace: string): Promise<void> {\n try {\n // Read STATE.md if it exists\n const stateFile = join(workspace, '.planning/STATE.md');\n if (existsSync(stateFile)) {\n context.stateFile = readFileSync(stateFile, 'utf-8');\n }\n\n // Read CLAUDE.md if it exists\n const claudeMd = join(workspace, 'CLAUDE.md');\n if (existsSync(claudeMd)) {\n context.claudeMd = readFileSync(claudeMd, 'utf-8');\n }\n } catch (error) {\n console.error('Error capturing files:', error);\n }\n}\n\n/**\n * Capture git state\n */\nasync function captureGitState(context: HandoffContext, workspace: string): Promise<void> {\n try {\n // Get current branch\n const branch = execSync('git branch --show-current', {\n cwd: workspace,\n encoding: 'utf-8',\n }).trim();\n context.gitBranch = branch;\n\n // Get uncommitted files\n const status = execSync('git status --porcelain', {\n cwd: workspace,\n encoding: 'utf-8',\n });\n context.uncommittedFiles = status\n .split('\\n')\n .filter(line => line.trim())\n .map(line => line.substring(3)); // Remove status prefix\n\n // Get last commit\n const lastCommit = execSync('git log -1 --oneline', {\n cwd: workspace,\n encoding: 'utf-8',\n }).trim();\n context.lastCommit = lastCommit;\n } catch (error) {\n console.error('Error capturing git state:', error);\n }\n}\n\n/**\n * Capture beads tasks state\n */\nasync function captureBeadsTasks(context: HandoffContext, issueId: string): Promise<void> {\n try {\n // List all tasks with this issue's label\n const label = issueId.toLowerCase();\n const output = execSync(`bd list --json -l ${label}`, {\n encoding: 'utf-8',\n });\n\n const tasks: BeadsTask[] = JSON.parse(output);\n\n // Categorize tasks\n context.activeBeadsTasks = tasks.filter(t => t.status === 'in_progress');\n context.remainingTasks = tasks.filter(t => t.status === 'open');\n context.completedTasks = tasks.filter(t => t.status === 'closed');\n } catch (error) {\n console.error('Error capturing beads tasks:', error);\n context.activeBeadsTasks = [];\n context.remainingTasks = [];\n context.completedTasks = [];\n }\n}\n\n/**\n * Serialize handoff context to markdown for agent prompt\n *\n * @param context - Handoff context\n * @returns Markdown representation\n */\nexport function serializeHandoffContext(context: HandoffContext): string {\n const lines: string[] = [];\n\n lines.push('# Handoff Context');\n lines.push('');\n lines.push(`**Reason:** ${context.reason}`);\n lines.push(`**From:** ${context.previousModel}`);\n lines.push(`**To:** ${context.targetModel}`);\n lines.push(`**Handoff Count:** ${context.handoffCount}`);\n if (context.costSoFar) {\n lines.push(`**Cost So Far:** $${context.costSoFar.toFixed(4)}`);\n }\n lines.push('');\n\n // Git state\n if (context.gitBranch) {\n lines.push('## Git State');\n lines.push('');\n lines.push(`**Branch:** ${context.gitBranch}`);\n if (context.lastCommit) {\n lines.push(`**Last Commit:** ${context.lastCommit}`);\n }\n if (context.uncommittedFiles && context.uncommittedFiles.length > 0) {\n lines.push(`**Uncommitted Files:** ${context.uncommittedFiles.length}`);\n lines.push('```');\n context.uncommittedFiles.forEach(file => lines.push(file));\n lines.push('```');\n }\n lines.push('');\n }\n\n // Beads tasks\n if (context.completedTasks && context.completedTasks.length > 0) {\n lines.push('## Completed Tasks');\n lines.push('');\n context.completedTasks.forEach(task => {\n lines.push(`- [x] ${task.title} (${task.id})`);\n });\n lines.push('');\n }\n\n if (context.activeBeadsTasks && context.activeBeadsTasks.length > 0) {\n lines.push('## Active Tasks');\n lines.push('');\n context.activeBeadsTasks.forEach(task => {\n lines.push(`- [ ] ${task.title} (${task.id}) - IN PROGRESS`);\n });\n lines.push('');\n }\n\n if (context.remainingTasks && context.remainingTasks.length > 0) {\n lines.push('## Remaining Tasks');\n lines.push('');\n context.remainingTasks.forEach(task => {\n lines.push(`- [ ] ${task.title} (${task.id})`);\n });\n lines.push('');\n }\n\n // STATE.md content\n if (context.stateFile) {\n lines.push('## Current State (STATE.md)');\n lines.push('');\n lines.push('```markdown');\n lines.push(context.stateFile);\n lines.push('```');\n lines.push('');\n }\n\n // AI summaries (if available)\n if (context.whatWasDone) {\n lines.push('## What Was Done');\n lines.push('');\n lines.push(context.whatWasDone);\n lines.push('');\n }\n\n if (context.whatRemains) {\n lines.push('## What Remains');\n lines.push('');\n lines.push(context.whatRemains);\n lines.push('');\n }\n\n if (context.blockers && context.blockers.length > 0) {\n lines.push('## Blockers');\n lines.push('');\n context.blockers.forEach(blocker => lines.push(`- ${blocker}`));\n lines.push('');\n }\n\n if (context.decisions && context.decisions.length > 0) {\n lines.push('## Decisions Made');\n lines.push('');\n context.decisions.forEach(decision => lines.push(`- ${decision}`));\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Build handoff prompt for new agent\n *\n * @param context - Handoff context\n * @param additionalInstructions - Optional additional instructions\n * @returns Prompt for new agent\n */\nexport function buildHandoffPrompt(\n context: HandoffContext,\n additionalInstructions?: string\n): string {\n const lines: string[] = [];\n\n lines.push('# Agent Handoff');\n lines.push('');\n lines.push(`You are taking over work on issue ${context.issueId} from a ${context.previousModel} agent.`);\n lines.push('');\n lines.push(`**Handoff Reason:** ${context.reason}`);\n lines.push('');\n lines.push('Please review the context below and continue the work.');\n lines.push('');\n lines.push('---');\n lines.push('');\n lines.push(serializeHandoffContext(context));\n\n if (additionalInstructions) {\n lines.push('---');\n lines.push('');\n lines.push('## Additional Instructions');\n lines.push('');\n lines.push(additionalInstructions);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","/**\n * Handoff Event Logger\n *\n * Logs handoff events to JSONL file for tracking and analysis.\n */\n\nimport { existsSync, mkdirSync, appendFileSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { PANOPTICON_HOME } from '../paths.js';\nimport type { HandoffContext } from './handoff-context.js';\nimport type { TriggerType } from './triggers.js';\n\n/**\n * Handoff event structure\n */\nexport interface HandoffEvent {\n timestamp: string;\n agentId: string;\n issueId: string;\n\n // Model transition\n from: {\n model: string;\n runtime: string;\n sessionId?: string;\n };\n to: {\n model: string;\n runtime: string;\n sessionId?: string;\n };\n\n // Trigger information\n trigger: TriggerType | 'manual';\n reason: string;\n\n // Context\n context: {\n beadsTaskCompleted?: string;\n stuckMinutes?: number;\n costAtHandoff?: number;\n handoffCount?: number;\n };\n\n // Result\n success: boolean;\n errorMessage?: string;\n}\n\n/**\n * Handoff log file path\n */\nconst HANDOFF_LOG_FILE = join(PANOPTICON_HOME, 'logs', 'handoffs.jsonl');\n\n/**\n * Ensure log directory exists\n */\nfunction ensureLogDir(): void {\n const logDir = join(PANOPTICON_HOME, 'logs');\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n}\n\n/**\n * Log a handoff event\n *\n * @param event - Handoff event to log\n */\nexport function logHandoffEvent(event: HandoffEvent): void {\n ensureLogDir();\n\n const line = JSON.stringify(event) + '\\n';\n appendFileSync(HANDOFF_LOG_FILE, line, 'utf-8');\n}\n\n/**\n * Create a handoff event from handoff result\n *\n * @param agentId - Agent ID\n * @param issueId - Issue ID\n * @param context - Handoff context\n * @param trigger - Trigger type\n * @param success - Whether handoff succeeded\n * @param errorMessage - Error message if failed\n * @returns Handoff event\n */\nexport function createHandoffEvent(\n agentId: string,\n issueId: string,\n context: HandoffContext,\n trigger: TriggerType | 'manual',\n success: boolean,\n errorMessage?: string\n): HandoffEvent {\n // Calculate stuck minutes if applicable\n let stuckMinutes: number | undefined;\n if (trigger === 'stuck_escalation') {\n // This would be calculated from health state\n // For now, we'll omit it unless available in context\n }\n\n return {\n timestamp: new Date().toISOString(),\n agentId,\n issueId,\n from: {\n model: context.previousModel,\n runtime: context.previousRuntime,\n sessionId: context.previousSessionId,\n },\n to: {\n model: context.targetModel,\n runtime: 'claude-code', // New agent runtime\n sessionId: undefined, // Will be set after spawn\n },\n trigger,\n reason: context.reason,\n context: {\n costAtHandoff: context.costSoFar,\n handoffCount: context.handoffCount,\n stuckMinutes,\n },\n success,\n errorMessage,\n };\n}\n\n/**\n * Read all handoff events from log\n *\n * @param limit - Maximum number of events to return (most recent first)\n * @returns Array of handoff events\n */\nexport function readHandoffEvents(limit?: number): HandoffEvent[] {\n ensureLogDir();\n\n if (!existsSync(HANDOFF_LOG_FILE)) {\n return [];\n }\n\n const content = readFileSync(HANDOFF_LOG_FILE, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.trim());\n\n const events = lines.map(line => JSON.parse(line) as HandoffEvent);\n\n // Return most recent first\n events.reverse();\n\n if (limit) {\n return events.slice(0, limit);\n }\n\n return events;\n}\n\n/**\n * Read handoff events for a specific issue\n *\n * @param issueId - Issue ID\n * @returns Array of handoff events for the issue\n */\nexport function readIssueHandoffEvents(issueId: string): HandoffEvent[] {\n const allEvents = readHandoffEvents();\n return allEvents.filter(e => e.issueId === issueId);\n}\n\n/**\n * Read handoff events for a specific agent\n *\n * @param agentId - Agent ID\n * @returns Array of handoff events for the agent\n */\nexport function readAgentHandoffEvents(agentId: string): HandoffEvent[] {\n const allEvents = readHandoffEvents();\n return allEvents.filter(e => e.agentId === agentId);\n}\n\n/**\n * Get handoff statistics\n *\n * @returns Handoff statistics\n */\nexport function getHandoffStats(): {\n totalHandoffs: number;\n byTrigger: Record<string, number>;\n byModel: {\n from: Record<string, number>;\n to: Record<string, number>;\n };\n successRate: number;\n} {\n const events = readHandoffEvents();\n\n const stats = {\n totalHandoffs: events.length,\n byTrigger: {} as Record<string, number>,\n byModel: {\n from: {} as Record<string, number>,\n to: {} as Record<string, number>,\n },\n successRate: 0,\n };\n\n let successCount = 0;\n\n for (const event of events) {\n // Count by trigger\n stats.byTrigger[event.trigger] = (stats.byTrigger[event.trigger] || 0) + 1;\n\n // Count by model\n stats.byModel.from[event.from.model] = (stats.byModel.from[event.from.model] || 0) + 1;\n stats.byModel.to[event.to.model] = (stats.byModel.to[event.to.model] || 0) + 1;\n\n // Count successes\n if (event.success) {\n successCount++;\n }\n }\n\n stats.successRate = events.length > 0 ? successCount / events.length : 0;\n\n return stats;\n}\n","/**\n * pan cloister start command\n *\n * Start Cloister monitoring service.\n */\n\nimport chalk from 'chalk';\nimport { getCloisterService } from '../../../lib/cloister/service.js';\n\nexport async function startCommand(): Promise<void> {\n const service = getCloisterService();\n\n if (service.isRunning()) {\n console.log(chalk.yellow('⚠️ Cloister is already running'));\n return;\n }\n\n await service.start();\n console.log(chalk.green('✓ Cloister started'));\n console.log(chalk.dim(' Monitoring all running agents...'));\n}\n","/**\n * pan cloister stop command\n *\n * Stop Cloister monitoring service (agents continue running).\n */\n\nimport chalk from 'chalk';\nimport { getCloisterService } from '../../../lib/cloister/service.js';\n\ninterface StopOptions {\n emergency?: boolean;\n}\n\nexport async function stopCommand(options: StopOptions): Promise<void> {\n const service = getCloisterService();\n\n if (!service.isRunning() && !options.emergency) {\n console.log(chalk.yellow('⚠️ Cloister is not running'));\n return;\n }\n\n if (options.emergency) {\n // Emergency stop - kill all agents\n console.log(chalk.red.bold('🚨 EMERGENCY STOP - Killing all agents'));\n console.log(chalk.dim(' This will terminate all running agent sessions'));\n\n const killedAgents = service.emergencyStop();\n\n console.log('');\n console.log(chalk.green(`✓ Killed ${killedAgents.length} agent(s):`));\n for (const agentId of killedAgents) {\n console.log(chalk.dim(` - ${agentId}`));\n }\n } else {\n // Normal stop - just stop monitoring\n service.stop();\n console.log(chalk.green('✓ Cloister stopped'));\n console.log(chalk.dim(' Agents are still running'));\n }\n}\n","import { Command } from 'commander';\nimport { setupHooksCommand } from './hooks.js';\n\n/**\n * Register all setup subcommands\n */\nexport function registerSetupCommands(program: Command): void {\n const setup = program\n .command('setup')\n .description('Setup and configure Panopticon components');\n\n setup\n .command('hooks')\n .description('Configure Claude Code hooks for heartbeat tracking')\n .action(setupHooksCommand);\n}\n","import chalk from 'chalk';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, chmodSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { homedir } from 'os';\n\ninterface ClaudeSettings {\n hooks?: {\n PostToolUse?: Array<{\n matcher: string; // Regex pattern, e.g. \".*\" for all tools or \"Bash\" for specific\n hooks: Array<{\n type: string;\n command: string;\n }>;\n }>;\n };\n [key: string]: any;\n}\n\n/**\n * Check if jq is installed\n */\nfunction checkJqInstalled(): boolean {\n try {\n execSync('which jq', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Attempt to install jq using package manager\n */\nfunction installJq(): boolean {\n console.log(chalk.yellow('Installing jq dependency...'));\n\n try {\n // Detect platform and package manager\n const platform = process.platform;\n\n if (platform === 'darwin') {\n // macOS - try homebrew\n try {\n execSync('brew --version', { stdio: 'pipe' });\n execSync('brew install jq', { stdio: 'inherit' });\n console.log(chalk.green('✓ jq installed via Homebrew'));\n return true;\n } catch {\n console.log(chalk.yellow('⚠ Homebrew not found'));\n }\n } else if (platform === 'linux') {\n // Linux - try apt, then yum\n try {\n execSync('apt-get --version', { stdio: 'pipe' });\n execSync('sudo apt-get update && sudo apt-get install -y jq', { stdio: 'inherit' });\n console.log(chalk.green('✓ jq installed via apt'));\n return true;\n } catch {\n try {\n execSync('yum --version', { stdio: 'pipe' });\n execSync('sudo yum install -y jq', { stdio: 'inherit' });\n console.log(chalk.green('✓ jq installed via yum'));\n return true;\n } catch {\n console.log(chalk.yellow('⚠ No supported package manager found (apt/yum)'));\n }\n }\n }\n\n return false;\n } catch (error) {\n console.log(chalk.red('✗ Failed to install jq automatically'));\n return false;\n }\n}\n\n/**\n * Check if Panopticon heartbeat hook is already configured\n */\nfunction hookAlreadyConfigured(settings: ClaudeSettings, hookPath: string): boolean {\n const postToolUse = settings?.hooks?.PostToolUse || [];\n return postToolUse.some((hookConfig) =>\n hookConfig.hooks?.some((hook) =>\n hook.command === hookPath ||\n hook.command?.includes('panopticon') ||\n hook.command?.includes('heartbeat-hook')\n )\n );\n}\n\n/**\n * Setup Claude Code hooks for Panopticon heartbeat\n */\nexport async function setupHooksCommand(): Promise<void> {\n console.log(chalk.bold('Setting up Panopticon heartbeat hooks\\n'));\n\n // 1. Check for jq dependency\n if (!checkJqInstalled()) {\n console.log(chalk.yellow('⚠ jq is required for heartbeat hooks'));\n const installed = installJq();\n\n if (!installed) {\n console.log(chalk.red('\\n✗ Setup failed: jq dependency missing'));\n console.log(chalk.dim('\\nPlease install jq manually:'));\n console.log(chalk.dim(' macOS: brew install jq'));\n console.log(chalk.dim(' Ubuntu: sudo apt-get install jq'));\n console.log(chalk.dim(' CentOS: sudo yum install jq\\n'));\n process.exit(1);\n }\n } else {\n console.log(chalk.green('✓ jq is installed'));\n }\n\n // 2. Ensure ~/.panopticon/bin directory exists\n const panopticonHome = join(homedir(), '.panopticon');\n const binDir = join(panopticonHome, 'bin');\n const heartbeatsDir = join(panopticonHome, 'heartbeats');\n\n if (!existsSync(binDir)) {\n mkdirSync(binDir, { recursive: true });\n console.log(chalk.green('✓ Created ~/.panopticon/bin/'));\n }\n\n if (!existsSync(heartbeatsDir)) {\n mkdirSync(heartbeatsDir, { recursive: true });\n console.log(chalk.green('✓ Created ~/.panopticon/heartbeats/'));\n }\n\n // 3. Copy heartbeat-hook script to ~/.panopticon/bin/\n // Find the script in the Panopticon installation\n const scriptSource = join(process.cwd(), 'scripts', 'heartbeat-hook');\n const scriptDest = join(binDir, 'heartbeat-hook');\n\n // Check if script exists in cwd/scripts (development mode)\n let sourcePath = scriptSource;\n if (!existsSync(sourcePath)) {\n // Try finding it relative to CLI location (installed mode)\n const { fileURLToPath } = await import('url');\n const { dirname } = await import('path');\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const installedSource = join(__dirname, '..', '..', '..', 'scripts', 'heartbeat-hook');\n\n if (existsSync(installedSource)) {\n sourcePath = installedSource;\n } else {\n console.log(chalk.red('✗ Could not find heartbeat-hook script'));\n console.log(chalk.dim(` Checked: ${scriptSource}`));\n console.log(chalk.dim(` Checked: ${installedSource}`));\n process.exit(1);\n }\n }\n\n copyFileSync(sourcePath, scriptDest);\n chmodSync(scriptDest, 0o755); // Make executable\n console.log(chalk.green('✓ Installed heartbeat-hook script'));\n\n // 4. Read or create Claude Code settings.json\n const claudeDir = join(homedir(), '.claude');\n const settingsPath = join(claudeDir, 'settings.json');\n\n let settings: ClaudeSettings = {};\n\n if (existsSync(settingsPath)) {\n try {\n const settingsContent = readFileSync(settingsPath, 'utf-8');\n settings = JSON.parse(settingsContent);\n console.log(chalk.green('✓ Read existing Claude Code settings'));\n } catch (error) {\n console.log(chalk.yellow('⚠ Could not parse settings.json, creating new file'));\n settings = {};\n }\n } else {\n console.log(chalk.dim('No existing settings.json found, creating new file'));\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n }\n\n // 5. Check if hook is already configured\n if (hookAlreadyConfigured(settings, scriptDest)) {\n console.log(chalk.cyan('\\n✓ Panopticon heartbeat hook already configured'));\n console.log(chalk.dim(' No changes needed\\n'));\n return;\n }\n\n // 6. Add Panopticon hook to settings\n if (!settings.hooks) {\n settings.hooks = {};\n }\n\n if (!settings.hooks.PostToolUse) {\n settings.hooks.PostToolUse = [];\n }\n\n // Append Panopticon hook (matcher: \".*\" matches all tools)\n settings.hooks.PostToolUse.push({\n matcher: '.*',\n hooks: [\n {\n type: 'command',\n command: scriptDest\n }\n ]\n });\n\n // 7. Write updated settings\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2));\n console.log(chalk.green('✓ Updated Claude Code settings.json'));\n\n // 8. Success message\n console.log(chalk.green.bold('\\n✓ Setup complete!\\n'));\n console.log(chalk.dim('Heartbeat hooks are now active. When you run agents via'));\n console.log(chalk.dim('`pan work issue`, they will send real-time activity updates'));\n console.log(chalk.dim('to the Panopticon dashboard.\\n'));\n}\n","import chalk from 'chalk';\nimport { existsSync, readFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport {\n listProjects,\n registerProject,\n unregisterProject,\n getProject,\n initializeProjectsConfig,\n PROJECTS_CONFIG_FILE,\n ProjectConfig,\n IssueRoutingRule,\n} from '../../lib/projects.js';\n\ninterface AddOptions {\n name?: string;\n type?: 'standalone' | 'monorepo';\n linearTeam?: string;\n}\n\nexport async function projectAddCommand(\n projectPath: string,\n options: AddOptions = {}\n): Promise<void> {\n const fullPath = resolve(projectPath);\n\n if (!existsSync(fullPath)) {\n console.log(chalk.red(`Path does not exist: ${fullPath}`));\n return;\n }\n\n // Determine name/key from directory if not provided\n const name = options.name || fullPath.split('/').pop() || 'unknown';\n const key = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n\n // Check if already registered\n const existing = getProject(key);\n if (existing) {\n console.log(chalk.yellow(`Project already registered with key: ${key}`));\n console.log(chalk.dim(`Existing path: ${existing.path}`));\n console.log(chalk.dim(`To update, first run: pan project remove ${key}`));\n return;\n }\n\n // Try to detect Linear team from .panopticon/project.toml or package.json\n let linearTeam = options.linearTeam;\n if (!linearTeam) {\n const projectToml = join(fullPath, '.panopticon', 'project.toml');\n if (existsSync(projectToml)) {\n const content = readFileSync(projectToml, 'utf-8');\n const match = content.match(/team\\s*=\\s*\"([^\"]+)\"/);\n if (match) linearTeam = match[1];\n }\n }\n\n const projectConfig: ProjectConfig = {\n name,\n path: fullPath,\n };\n\n if (linearTeam) {\n projectConfig.linear_team = linearTeam.toUpperCase();\n }\n\n registerProject(key, projectConfig);\n\n console.log(chalk.green(`✓ Added project: ${name}`));\n console.log(chalk.dim(` Key: ${key}`));\n console.log(chalk.dim(` Path: ${fullPath}`));\n if (linearTeam) {\n console.log(chalk.dim(` Linear team: ${linearTeam}`));\n }\n console.log('');\n console.log(chalk.dim(`Edit ${PROJECTS_CONFIG_FILE} to add issue routing rules.`));\n}\n\ninterface ListOptions {\n json?: boolean;\n}\n\nexport async function projectListCommand(options: ListOptions = {}): Promise<void> {\n const projects = listProjects();\n\n if (projects.length === 0) {\n console.log(chalk.dim('No projects registered.'));\n console.log(chalk.dim('Add one with: pan project add <path> --linear-team <TEAM>'));\n console.log(chalk.dim(`Or edit: ${PROJECTS_CONFIG_FILE}`));\n return;\n }\n\n if (options.json) {\n const output: Record<string, ProjectConfig> = {};\n for (const { key, config } of projects) {\n output[key] = config;\n }\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n console.log(chalk.bold('\\nRegistered Projects:\\n'));\n\n for (const { key, config } of projects) {\n const exists = existsSync(config.path);\n const statusIcon = exists ? chalk.green('✓') : chalk.red('✗');\n\n console.log(`${statusIcon} ${chalk.bold(config.name)} ${chalk.dim(`(${key})`)}`);\n console.log(` ${chalk.dim(config.path)}`);\n if (config.linear_team) {\n console.log(` ${chalk.cyan(`Linear: ${config.linear_team}`)}`);\n }\n if (config.issue_routing && config.issue_routing.length > 0) {\n console.log(` ${chalk.dim(`Routes: ${config.issue_routing.length} rules`)}`);\n }\n console.log('');\n }\n\n console.log(chalk.dim(`Config: ${PROJECTS_CONFIG_FILE}`));\n}\n\nexport async function projectRemoveCommand(nameOrPath: string): Promise<void> {\n // Try to find by key first, then by name, then by path\n const projects = listProjects();\n\n // Try direct key match\n if (unregisterProject(nameOrPath)) {\n console.log(chalk.green(`✓ Removed project: ${nameOrPath}`));\n return;\n }\n\n // Try to find by name or path\n for (const { key, config } of projects) {\n if (config.name === nameOrPath || config.path === resolve(nameOrPath)) {\n unregisterProject(key);\n console.log(chalk.green(`✓ Removed project: ${config.name}`));\n return;\n }\n }\n\n console.log(chalk.red(`Project not found: ${nameOrPath}`));\n console.log(chalk.dim(`Use 'pan project list' to see registered projects.`));\n}\n\nexport async function projectInitCommand(): Promise<void> {\n if (existsSync(PROJECTS_CONFIG_FILE)) {\n console.log(chalk.yellow(`Config already exists: ${PROJECTS_CONFIG_FILE}`));\n return;\n }\n\n initializeProjectsConfig();\n\n console.log(chalk.green('✓ Projects config initialized'));\n console.log('');\n console.log(chalk.dim(`Edit ${PROJECTS_CONFIG_FILE} to add your projects.`));\n console.log('');\n console.log(chalk.bold('Quick start:'));\n console.log(\n chalk.dim(\n ' pan project add /path/to/project --name \"My Project\" --linear-team MIN'\n )\n );\n}\n\nexport async function projectShowCommand(keyOrName: string): Promise<void> {\n const projects = listProjects();\n\n // Find by key or name\n let found = getProject(keyOrName);\n let foundKey = keyOrName;\n\n if (!found) {\n for (const { key, config } of projects) {\n if (config.name.toLowerCase() === keyOrName.toLowerCase()) {\n found = config;\n foundKey = key;\n break;\n }\n }\n }\n\n if (!found) {\n console.error(chalk.red(`Project not found: ${keyOrName}`));\n console.log(chalk.dim(`Use 'pan project list' to see registered projects.`));\n process.exit(1);\n }\n\n const pathExists = existsSync(found.path);\n const pathStatus = pathExists ? chalk.green('✓') : chalk.red('✗');\n\n console.log(chalk.bold(`\\nProject: ${foundKey}\\n`));\n console.log(` Name: ${found.name}`);\n console.log(` Path: ${pathStatus} ${found.path}`);\n if (found.linear_team) {\n console.log(` Team: ${found.linear_team}`);\n }\n\n if (found.issue_routing && found.issue_routing.length > 0) {\n console.log('\\n ' + chalk.bold('Routing Rules:'));\n for (const rule of found.issue_routing) {\n if (rule.labels) {\n console.log(` Labels: ${rule.labels.join(', ')}`);\n console.log(` → ${rule.path}`);\n } else if (rule.default) {\n console.log(` Default:`);\n console.log(` → ${rule.path}`);\n }\n }\n }\n\n console.log('');\n}\n","import chalk from 'chalk';\nimport { existsSync, readdirSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport {\n PANOPTICON_HOME,\n SKILLS_DIR,\n COMMANDS_DIR,\n AGENTS_DIR,\n CLAUDE_DIR,\n} from '../../lib/paths.js';\n\ninterface CheckResult {\n name: string;\n status: 'ok' | 'warn' | 'error';\n message: string;\n fix?: string;\n}\n\nfunction checkCommand(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { encoding: 'utf-8', stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction checkDirectory(path: string): boolean {\n return existsSync(path);\n}\n\nfunction countItems(path: string): number {\n if (!existsSync(path)) return 0;\n try {\n return readdirSync(path).length;\n } catch {\n return 0;\n }\n}\n\nexport async function doctorCommand(): Promise<void> {\n console.log(chalk.bold('\\nPanopticon Doctor\\n'));\n console.log(chalk.dim('Checking system health...\\n'));\n\n const checks: CheckResult[] = [];\n\n // Check required commands\n const requiredCommands = [\n { cmd: 'git', name: 'Git', fix: 'Install git' },\n { cmd: 'tmux', name: 'tmux', fix: 'Install tmux: apt install tmux / brew install tmux' },\n { cmd: 'node', name: 'Node.js', fix: 'Install Node.js 18+' },\n { cmd: 'claude', name: 'Claude CLI', fix: 'Install: npm install -g @anthropic-ai/claude-code' },\n ];\n\n for (const { cmd, name, fix } of requiredCommands) {\n if (checkCommand(cmd)) {\n checks.push({ name, status: 'ok', message: 'Installed' });\n } else {\n checks.push({ name, status: 'error', message: 'Not found', fix });\n }\n }\n\n // Check optional commands\n const optionalCommands = [\n { cmd: 'gh', name: 'GitHub CLI', fix: 'Install: gh auth login' },\n { cmd: 'bd', name: 'Beads CLI', fix: 'Install beads for task tracking' },\n { cmd: 'docker', name: 'Docker', fix: 'Install Docker for workspace containers' },\n ];\n\n for (const { cmd, name, fix } of optionalCommands) {\n if (checkCommand(cmd)) {\n checks.push({ name, status: 'ok', message: 'Installed' });\n } else {\n checks.push({ name, status: 'warn', message: 'Not installed (optional)', fix });\n }\n }\n\n // Check Panopticon directories\n const directories = [\n { path: PANOPTICON_HOME, name: 'Panopticon Home', fix: 'Run: pan init' },\n { path: SKILLS_DIR, name: 'Skills Directory', fix: 'Run: pan init' },\n { path: COMMANDS_DIR, name: 'Commands Directory', fix: 'Run: pan init' },\n { path: AGENTS_DIR, name: 'Agents Directory', fix: 'Run: pan init' },\n ];\n\n for (const { path, name, fix } of directories) {\n if (checkDirectory(path)) {\n const count = countItems(path);\n checks.push({ name, status: 'ok', message: `Exists (${count} items)` });\n } else {\n checks.push({ name, status: 'error', message: 'Missing', fix });\n }\n }\n\n // Check Claude Code integration\n if (checkDirectory(CLAUDE_DIR)) {\n const skillsCount = countItems(join(CLAUDE_DIR, 'skills'));\n const commandsCount = countItems(join(CLAUDE_DIR, 'commands'));\n checks.push({\n name: 'Claude Code Skills',\n status: skillsCount > 0 ? 'ok' : 'warn',\n message: `${skillsCount} skills`,\n fix: skillsCount === 0 ? 'Run: pan sync' : undefined,\n });\n checks.push({\n name: 'Claude Code Commands',\n status: commandsCount > 0 ? 'ok' : 'warn',\n message: `${commandsCount} commands`,\n fix: commandsCount === 0 ? 'Run: pan sync' : undefined,\n });\n } else {\n checks.push({\n name: 'Claude Code Directory',\n status: 'warn',\n message: 'Not found',\n fix: 'Install Claude Code first',\n });\n }\n\n // Check environment variables\n const envFile = join(homedir(), '.panopticon.env');\n if (existsSync(envFile)) {\n checks.push({ name: 'Config File', status: 'ok', message: '~/.panopticon.env exists' });\n } else {\n checks.push({\n name: 'Config File',\n status: 'warn',\n message: '~/.panopticon.env not found',\n fix: 'Create ~/.panopticon.env with LINEAR_API_KEY=...',\n });\n }\n\n // Check for LINEAR_API_KEY\n if (process.env.LINEAR_API_KEY) {\n checks.push({ name: 'LINEAR_API_KEY', status: 'ok', message: 'Set in environment' });\n } else if (existsSync(envFile)) {\n const content = require('fs').readFileSync(envFile, 'utf-8');\n if (content.includes('LINEAR_API_KEY')) {\n checks.push({ name: 'LINEAR_API_KEY', status: 'ok', message: 'Set in config file' });\n } else {\n checks.push({\n name: 'LINEAR_API_KEY',\n status: 'warn',\n message: 'Not configured',\n fix: 'Add LINEAR_API_KEY to ~/.panopticon.env',\n });\n }\n } else {\n checks.push({\n name: 'LINEAR_API_KEY',\n status: 'warn',\n message: 'Not configured',\n fix: 'Set LINEAR_API_KEY environment variable or add to ~/.panopticon.env',\n });\n }\n\n // Check tmux sessions\n try {\n const sessions = execSync('tmux list-sessions 2>/dev/null || true', { encoding: 'utf-8' });\n const agentSessions = sessions.split('\\n').filter((s) => s.includes('agent-')).length;\n checks.push({\n name: 'Running Agents',\n status: 'ok',\n message: `${agentSessions} agent sessions`,\n });\n } catch {\n checks.push({\n name: 'Running Agents',\n status: 'ok',\n message: '0 agent sessions',\n });\n }\n\n // Print results\n const icons = {\n ok: chalk.green('\\u2713'),\n warn: chalk.yellow('\\u26a0'),\n error: chalk.red('\\u2717'),\n };\n\n let hasErrors = false;\n let hasWarnings = false;\n\n for (const check of checks) {\n const icon = icons[check.status];\n const message = check.status === 'error' ? chalk.red(check.message) :\n check.status === 'warn' ? chalk.yellow(check.message) :\n chalk.dim(check.message);\n\n console.log(`${icon} ${check.name}: ${message}`);\n\n if (check.fix && check.status !== 'ok') {\n console.log(chalk.dim(` Fix: ${check.fix}`));\n }\n\n if (check.status === 'error') hasErrors = true;\n if (check.status === 'warn') hasWarnings = true;\n }\n\n console.log('');\n\n if (hasErrors) {\n console.log(chalk.red('Some required components are missing.'));\n console.log(chalk.dim('Fix the errors above before using Panopticon.'));\n } else if (hasWarnings) {\n console.log(chalk.yellow('System is functional with some optional features missing.'));\n } else {\n console.log(chalk.green('All systems operational!'));\n }\n console.log('');\n}\n","/**\n * pan update - Update Panopticon to latest version\n */\n\nimport { execSync } from 'child_process';\nimport chalk from 'chalk';\nimport { loadConfig } from '../../lib/config.js';\nimport { syncCommand } from './sync.js';\n\n// Get current installed version\nfunction getCurrentVersion(): string {\n try {\n const pkg = require('../../../package.json');\n return pkg.version;\n } catch {\n return 'unknown';\n }\n}\n\n// Get latest version from npm\nasync function getLatestVersion(): Promise<string> {\n try {\n const result = execSync('npm view panopticon-cli version', {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return result.trim();\n } catch {\n throw new Error('Failed to check npm for latest version');\n }\n}\n\n// Compare semver versions\nfunction isNewer(latest: string, current: string): boolean {\n const parseVersion = (v: string) => {\n const parts = v.replace(/^v/, '').split('.');\n return {\n major: parseInt(parts[0] || '0', 10),\n minor: parseInt(parts[1] || '0', 10),\n patch: parseInt(parts[2] || '0', 10),\n };\n };\n\n const l = parseVersion(latest);\n const c = parseVersion(current);\n\n if (l.major !== c.major) return l.major > c.major;\n if (l.minor !== c.minor) return l.minor > c.minor;\n return l.patch > c.patch;\n}\n\nexport async function updateCommand(options: {\n check?: boolean;\n force?: boolean;\n}) {\n console.log(chalk.bold('Panopticon Update\\n'));\n\n const currentVersion = getCurrentVersion();\n console.log(`Current version: ${chalk.cyan(currentVersion)}`);\n\n let latestVersion: string;\n try {\n console.log(chalk.dim('Checking npm for latest version...'));\n latestVersion = await getLatestVersion();\n console.log(`Latest version: ${chalk.cyan(latestVersion)}`);\n } catch (error) {\n console.error(chalk.red('Failed to check for updates'));\n console.error(chalk.dim('Make sure you have internet connectivity'));\n process.exit(1);\n }\n\n const needsUpdate = isNewer(latestVersion, currentVersion);\n\n if (!needsUpdate) {\n console.log(chalk.green('\\n✓ You are on the latest version'));\n return;\n }\n\n console.log(\n chalk.yellow(`\\n↑ Update available: ${currentVersion} → ${latestVersion}`)\n );\n\n if (options.check) {\n console.log(chalk.dim('\\nRun `pan update` to install'));\n return;\n }\n\n // Perform the update\n console.log(chalk.dim('\\nUpdating Panopticon...'));\n\n try {\n execSync('npm install -g panopticon-cli@latest', {\n stdio: 'inherit',\n });\n\n console.log(chalk.green(`\\n✓ Updated to ${latestVersion}`));\n\n // Auto-sync if enabled\n const config = loadConfig();\n if (config.sync.auto_sync) {\n console.log(chalk.dim('\\nRunning auto-sync...'));\n await syncCommand({});\n }\n\n console.log(chalk.dim('\\nRestart any running agents to use the new version.'));\n } catch (error) {\n console.error(chalk.red('\\nUpdate failed'));\n console.error(\n chalk.dim('Try running with sudo: sudo npm install -g panopticon-cli@latest')\n );\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AASlB,SAAS,eAA8B;AAC5C,MAAI;AACF,UAAM,SAAS,SAAS,qGAAqG;AAAA,MAC3H,UAAU;AAAA,IACZ,CAAC;AAED,WAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE,IAAI,UAAQ;AAC3D,YAAM,CAAC,MAAM,SAAS,UAAU,OAAO,IAAI,KAAK,MAAM,GAAG;AACzD,aAAO;AAAA,QACL;AAAA,QACA,SAAS,IAAI,KAAK,SAAS,OAAO,IAAI,GAAI;AAAA,QAC1C,UAAU,aAAa;AAAA,QACvB,SAAS,SAAS,OAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,cAAc,MAAuB;AACnD,MAAI;AACF,aAAS,uBAAuB,IAAI,cAAc;AAClD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,cACd,MACA,KACA,gBACA,SACM;AACN,QAAM,aAAa,IAAI,QAAQ,MAAM,KAAK;AAG1C,MAAI,WAAW;AACf,MAAI,SAAS,KAAK;AAChB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG,GAAG;AACtD,kBAAY,OAAO,GAAG,KAAK,MAAM,QAAQ,MAAM,KAAK,CAAC;AAAA,IACvD;AAAA,EACF;AAGA,MAAI,mBAAmB,eAAe,SAAS,GAAG,KAAK,eAAe,SAAS,IAAI,KAAK,eAAe,SAAS,MAAM;AAEpH,aAAS,0BAA0B,IAAI,QAAQ,UAAU,IAAI,QAAQ,EAAE;AAGvE,aAAS,WAAW;AAIpB,UAAM,UAAU,gBAAgB,IAAI;AACpC,UAAM,KAAK,UAAQ,IAAI;AACvB,OAAG,cAAc,SAAS,cAAc;AACxC,OAAG,UAAU,SAAS,KAAK;AAG3B,aAAS,qBAAqB,IAAI,UAAU,OAAO,SAAS;AAAA,EAC9D,WAAW,gBAAgB;AAEzB,UAAM,MAAM,0BAA0B,IAAI,QAAQ,UAAU,IAAI,QAAQ,KAAK,eAAe,QAAQ,MAAM,KAAK,CAAC;AAChH,aAAS,GAAG;AAAA,EACd,OAAO;AACL,aAAS,0BAA0B,IAAI,QAAQ,UAAU,IAAI,QAAQ,EAAE;AAAA,EACzE;AACF;AAEO,SAAS,YAAY,MAAoB;AAC9C,WAAS,wBAAwB,IAAI,EAAE;AACzC;AAEO,SAAS,SAAS,aAAqB,MAAoB;AAGhE,QAAM,cAAc,KAAK,QAAQ,MAAM,KAAK;AAC5C,WAAS,qBAAqB,WAAW,KAAK,WAAW,GAAG;AAC5D,WAAS,qBAAqB,WAAW,QAAQ;AACnD;AAYO,SAAS,mBAAkC;AAChD,SAAO,aAAa,EAAE,OAAO,OAAK,EAAE,KAAK,WAAW,QAAQ,CAAC;AAC/D;AAxGA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACSA,SAAS,cAAAA,aAAY,aAAAC,YAAW,gBAAAC,eAAc,eAAe,eAAAC,cAAa,kBAAkB;AAC5F,SAAS,QAAAC,aAAY;AAwBrB,SAAS,WAAW,SAAyB;AAC3C,SAAOA,MAAK,YAAY,OAAO;AACjC;AAEA,SAAS,YAAY,SAAyB;AAC5C,SAAOA,MAAK,WAAW,OAAO,GAAG,WAAW;AAC9C;AAEA,SAAS,WAAW,SAAyB;AAC3C,SAAOA,MAAK,WAAW,OAAO,GAAG,MAAM;AACzC;AAKO,SAAS,SAAS,SAAuB;AAC9C,QAAM,UAAU,WAAW,OAAO;AAClC,QAAM,UAAU,WAAW,OAAO;AAElC,EAAAH,WAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC,EAAAA,WAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAEtC,QAAM,WAAW,YAAY,OAAO;AACpC,MAAI,CAACD,YAAW,QAAQ,GAAG;AACzB,UAAM,OAAa;AAAA,MACjB;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AACA,kBAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EACvD;AACF;AAKO,SAAS,QAAQ,SAA8B;AACpD,QAAM,WAAW,YAAY,OAAO;AACpC,MAAI,CAACA,YAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAUE,cAAa,UAAU,OAAO;AAC9C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,WAAW,SAAiB,MAAoD;AAC9F,WAAS,OAAO;AAEhB,QAAM,OAAO,QAAQ,OAAO,KAAK,EAAE,SAAS,OAAO,CAAC,EAAE;AAEtD,QAAM,UAAoB;AAAA,IACxB,GAAG;AAAA,IACH,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,IAChE,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AAEA,OAAK,MAAM,KAAK,OAAO;AACvB,gBAAc,YAAY,OAAO,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAEjE,SAAO;AACT;AAKO,SAAS,UAAU,SAA+E;AACvG,QAAM,OAAO,QAAQ,OAAO;AAE5B,MAAI,CAAC,QAAQ,KAAK,MAAM,WAAW,GAAG;AAEpC,UAAM,UAAU,WAAW,OAAO;AAClC,QAAIF,YAAW,OAAO,GAAG;AACvB,YAAM,QAAQG,aAAY,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC;AACpE,UAAI,MAAM,SAAS,GAAG;AAEpB,cAAM,YAAwB,MAAM,IAAI,CAAC,SAAS;AAChD,cAAI;AACF,kBAAM,UAAUD,cAAaE,MAAK,SAAS,IAAI,GAAG,OAAO;AACzD,mBAAO,KAAK,MAAM,OAAO;AAAA,UAC3B,QAAQ;AACN,mBAAO;AAAA,UACT;AAAA,QACF,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO;AAAA,UACL,SAAS,UAAU,SAAS;AAAA,UAC5B,aAAa,UAAU,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ,EAAE;AAAA,UAC9D,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,OAAO,aAAa,GAAG,OAAO,CAAC,EAAE;AAAA,EACrD;AAGA,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,cAAc,KAAK,MAAM,OAAO,CAAC,SAAS;AAC9C,QAAI,KAAK,WAAW;AAClB,aAAO,IAAI,KAAK,KAAK,SAAS,IAAI;AAAA,IACpC;AACA,WAAO;AAAA,EACT,CAAC;AAGD,QAAM,gBAAgB,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,EAAE;AAC9D,cAAY,KAAK,CAAC,GAAG,MAAM,cAAc,EAAE,QAAQ,IAAI,cAAc,EAAE,QAAQ,CAAC;AAEhF,SAAO;AAAA,IACL,SAAS,YAAY,SAAS;AAAA,IAC9B,aAAa,YAAY,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ,EAAE;AAAA,IAChE,OAAO;AAAA,EACT;AACF;AAKO,SAAS,YAAY,SAAiB,QAAyB;AACpE,QAAM,OAAO,QAAQ,OAAO;AAC5B,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,QAAQ,KAAK,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM;AACzD,MAAI,UAAU,GAAI,QAAO;AAEzB,OAAK,MAAM,OAAO,OAAO,CAAC;AAC1B,OAAK,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC1C,gBAAc,YAAY,OAAO,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAEjE,SAAO;AACT;AAKO,SAAS,UAAU,SAAuB;AAC/C,QAAM,OAAO,QAAQ,OAAO;AAC5B,MAAI,CAAC,KAAM;AAEX,OAAK,QAAQ,CAAC;AACd,OAAK,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC1C,gBAAc,YAAY,OAAO,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACnE;AAKO,SAAS,SACd,WACA,MACA,SACA,WAAiC,UAC3B;AACN,WAAS,SAAS;AAClB,QAAM,UAAU,WAAW,SAAS;AAEpC,QAAM,WAAqB;AAAA,IACzB,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,IAChE,MAAM;AAAA,IACN;AAAA,IACA,QAAQ;AAAA,IACR,SAAS,EAAE,QAAQ;AAAA,IACnB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AAEA;AAAA,IACEA,MAAK,SAAS,GAAG,SAAS,EAAE,OAAO;AAAA,IACnC,KAAK,UAAU,UAAU,MAAM,CAAC;AAAA,EAClC;AACF;AA6BO,SAAS,mBAAmB,SAAgC;AACjE,QAAM,EAAE,SAAS,aAAa,MAAM,IAAI,UAAU,OAAO;AAEzD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,cAAc,GAAG;AACnB,UAAM,KAAK,kBAAQ,WAAW,+CAA+C;AAC7E,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,0BAA0B,MAAM,MAAM,GAAG;AACpD,QAAM,KAAK,EAAE;AAEb,aAAW,QAAQ,OAAO;AACxB,UAAM,gBAAgB;AAAA,MACpB,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,IACP,EAAE,KAAK,QAAQ;AAEf,UAAM,KAAK,OAAO,aAAa,IAAI,KAAK,KAAK,YAAY,CAAC,KAAK,KAAK,EAAE,EAAE;AACxE,UAAM,KAAK,aAAa,KAAK,MAAM,EAAE;AACrC,UAAM,KAAK,cAAc,KAAK,SAAS,EAAE;AAEzC,QAAI,KAAK,QAAQ,SAAS;AACxB,YAAM,KAAK,YAAY,KAAK,QAAQ,OAAO,EAAE;AAAA,IAC/C;AACA,QAAI,KAAK,QAAQ,SAAS;AACxB,YAAM,KAAK,cAAc,KAAK,QAAQ,OAAO,EAAE;AAAA,IACjD;AACA,QAAI,KAAK,QAAQ,QAAQ;AACvB,YAAM,KAAK,aAAa,KAAK,QAAQ,MAAM,EAAE;AAAA,IAC/C;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,2FAA2F;AAEtG,SAAO,MAAM,KAAK,IAAI;AACxB;AAhSA;AAAA;AAAA;AAAA;AAWA;AAAA;AAAA;;;ACLA,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,gBAAe,eAAAC,oBAAmB;AAChF,SAAS,QAAAC,aAAY;AAiCrB,SAAS,UAAU,SAAyB;AAC1C,SAAOA,MAAK,YAAY,SAAS,SAAS;AAC5C;AAKO,SAAS,WAAW,SAA0B;AACnD,QAAM,SAAS,UAAU,OAAO;AAEhC,MAAIL,YAAW,MAAM,GAAG;AACtB,QAAI;AACF,aAAO,KAAK,MAAME,cAAa,QAAQ,OAAO,CAAC;AAAA,IACjD,QAAQ;AAAA,IAAC;AAAA,EACX;AAGA,QAAM,KAAc;AAAA,IAClB;AAAA,IACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACnC,SAAS;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,MACL,aAAa;AAAA,MACb,cAAc;AAAA,MACd,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,YAAY,CAAC;AAAA,IACb,YAAY,CAAC;AAAA,EACf;AAEA,cAAY,EAAE;AACd,SAAO;AACT;AAKO,SAAS,YAAY,IAAmB;AAC7C,QAAM,MAAMG,MAAK,YAAY,GAAG,OAAO;AACvC,EAAAJ,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,EAAAE,eAAc,UAAU,GAAG,OAAO,GAAG,KAAK,UAAU,IAAI,MAAM,CAAC,CAAC;AAClE;AAKO,SAAS,UAAU,SAAiB,SAAiB,QAAyB;AACnF,QAAM,KAAK,WAAW,OAAO;AAE7B,QAAM,QAAmB;AAAA,IACvB;AAAA,IACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS;AAAA,IACT;AAAA,EACF;AAEA,KAAG,WAAW,QAAQ,KAAK;AAC3B,KAAG,MAAM;AACT,KAAG,cAAa,oBAAI,KAAK,GAAE,YAAY;AAGvC,MAAI,QAAQ;AACV,eAAW,SAAS,QAAQ;AAC1B,UAAI,CAAC,GAAG,WAAW,SAAS,KAAK,GAAG;AAClC,WAAG,WAAW,KAAK,KAAK;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAGA,MAAI,GAAG,WAAW,SAAS,IAAI;AAC7B,OAAG,aAAa,GAAG,WAAW,MAAM,GAAG,EAAE;AAAA,EAC3C;AAEA,cAAY,EAAE;AAChB;AA0DO,SAAS,mBAKb;AACD,QAAM,WAKD,CAAC;AAEN,MAAI,CAACH,YAAW,UAAU,EAAG,QAAO;AAEpC,QAAM,OAAOI,aAAY,YAAY,EAAE,eAAe,KAAK,CAAC,EAAE;AAAA,IAC5D,CAAC,MAAM,EAAE,YAAY;AAAA,EACvB;AAEA,aAAW,OAAO,MAAM;AACtB,UAAM,KAAK,WAAW,IAAI,IAAI;AAC9B,QAAI,GAAG,MAAM,cAAc,GAAG;AAC5B,eAAS,KAAK;AAAA,QACZ,SAAS,IAAI;AAAA,QACb,aAAa,GAAG,MAAM;AAAA,QACtB,aAAa,GAAG,MAAM;AAAA,QACtB,aAAa,GAAG,MAAM;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,WAAS,KAAK,CAAC,GAAG,MAAM;AACtB,QAAI,EAAE,gBAAgB,EAAE,aAAa;AACnC,aAAO,EAAE,cAAc,EAAE;AAAA,IAC3B;AACA,WAAO,EAAE,cAAc,EAAE;AAAA,EAC3B,CAAC;AAED,SAAO;AACT;AAKO,SAAS,SAAS,IAAqB;AAC5C,QAAM,QAAkB;AAAA,IACtB,eAAe,GAAG,OAAO;AAAA,IACzB;AAAA,IACA,YAAY,GAAG,OAAO,KAAK,GAAG,KAAK;AAAA,IACnC,YAAY,GAAG,SAAS;AAAA,IACxB,gBAAgB,GAAG,UAAU;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,GAAG,MAAM,WAAW;AAAA,IACvC,oBAAoB,GAAG,MAAM,cAAc,KAAK,QAAQ,CAAC,CAAC;AAAA,IAC1D,gBAAgB,GAAG,MAAM,YAAY;AAAA,IACrC,eAAe,GAAG,MAAM,YAAY;AAAA,IACpC,gBAAgB,GAAG,MAAM,cAAc;AAAA,IACvC,mBAAmB,GAAG,MAAM,WAAW;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,UAAM,KAAK,gBAAgB;AAC3B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,WAAW,KAAK,IAAI,CAAC;AACnC,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,UAAM,KAAK,gBAAgB;AAC3B,UAAM,KAAK,EAAE;AAEb,eAAW,QAAQ,GAAG,WAAW,MAAM,GAAG,EAAE,GAAG;AAC7C,YAAM,aAAa;AAAA,QACjB,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,MACf,EAAE,KAAK,OAAO;AAEd,YAAM,WAAW,KAAK,WAAW,KAAK,KAAK,QAAQ,OAAO;AAC1D,YAAM,KAAK,GAAG,UAAU,IAAI,KAAK,OAAO,GAAG,QAAQ,EAAE;AAErD,UAAI,KAAK,eAAe;AACtB,cAAM,KAAK,aAAa,KAAK,aAAa,EAAE;AAAA,MAC9C;AAAA,IACF;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAhRA;AAAA;AAAA;AAAA;AAQA;AAAA;AAAA;;;ACRA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,cAAAE,aAAY,aAAAC,YAAW,iBAAAC,gBAAe,gBAAAC,eAAc,eAAAC,oBAAmB;AAChF,SAAS,QAAAC,aAAY;AACrB,SAAS,YAAAC,iBAAgB;AAwBlB,SAAS,YAAY,SAAyB;AACnD,SAAOD,MAAK,YAAY,OAAO;AACjC;AAEO,SAAS,cAAc,SAAoC;AAChE,QAAM,YAAYA,MAAK,YAAY,OAAO,GAAG,YAAY;AACzD,MAAI,CAACL,YAAW,SAAS,EAAG,QAAO;AAEnC,QAAM,UAAUG,cAAa,WAAW,MAAM;AAC9C,SAAO,KAAK,MAAM,OAAO;AAC3B;AAEO,SAAS,eAAe,OAAyB;AACtD,QAAM,MAAM,YAAY,MAAM,EAAE;AAChC,EAAAF,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,EAAAC;AAAA,IACEG,MAAK,KAAK,YAAY;AAAA,IACtB,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,EAC/B;AACF;AAUO,SAAS,WAAW,SAAmC;AAC5D,QAAM,UAAU,SAAS,QAAQ,QAAQ,YAAY,CAAC;AAGtD,MAAI,cAAc,OAAO,GAAG;AAC1B,UAAM,IAAI,MAAM,SAAS,OAAO,sDAAsD;AAAA,EACxF;AAGA,WAAS,OAAO;AAGhB,QAAM,QAAoB;AAAA,IACxB,IAAI;AAAA,IACJ,SAAS,QAAQ;AAAA,IACjB,WAAW,QAAQ;AAAA,IACnB,SAAS,QAAQ,WAAW;AAAA,IAC5B,OAAO,QAAQ,SAAS;AAAA,IACxB,QAAQ;AAAA,IACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA;AAAA,IAElC,cAAc;AAAA,IACd,WAAW;AAAA,EACb;AAEA,iBAAe,KAAK;AAGpB,MAAI,SAAS,QAAQ,UAAU;AAG/B,QAAM,EAAE,SAAS,MAAM,IAAI,UAAU,OAAO;AAC5C,MAAI,SAAS;AACX,UAAM,aAAa,mBAAmB,OAAO;AAC7C,QAAI,YAAY;AACd,eAAS,aAAa,gBAAgB;AAAA,IACxC;AAAA,EACF;AAGA,QAAM,aAAaA,MAAK,YAAY,OAAO,GAAG,mBAAmB;AACjE,MAAI,QAAQ;AACV,IAAAH,eAAc,YAAY,MAAM;AAAA,EAClC;AAGA,qBAAmB;AAGnB,iBAAe,SAAS,QAAQ,OAAO;AAGvC,QAAM,YAAY,iDAAiD,MAAM,KAAK;AAC9E,gBAAc,SAAS,QAAQ,WAAW,WAAW;AAAA,IACnD,KAAK;AAAA,MACH,qBAAqB;AAAA,IACvB;AAAA,EACF,CAAC;AAGD,MAAI,QAAQ;AAGV,QAAI,QAAQ;AACZ,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,MAAAI,UAAS,SAAS;AAClB,UAAI;AACF,cAAM,OAAOA,UAAS,wBAAwB,OAAO,OAAO,EAAE,UAAU,QAAQ,CAAC;AACjF,YAAI,KAAK,SAAS,QAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAC5C,kBAAQ;AACR;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAAC;AAAA,IACX;AAEA,QAAI,OAAO;AAGT,MAAAA,UAAS,qBAAqB,UAAU,GAAG;AAC3C,MAAAA,UAAS,wBAAwB,OAAO,EAAE;AAE1C,MAAAA,UAAS,WAAW;AACpB,MAAAA,UAAS,qBAAqB,OAAO,QAAQ;AAAA,IAC/C,OAAO;AACL,cAAQ,MAAM,sDAAsD;AAAA,IACtE;AAAA,EACF;AAGA,QAAM,SAAS;AACf,iBAAe,KAAK;AAGpB,YAAU,SAAS,QAAQ,OAAO;AAElC,SAAO;AACT;AAEO,SAAS,oBAA8D;AAC5E,QAAM,eAAe,iBAAiB;AACtC,QAAM,YAAY,IAAI,IAAI,aAAa,IAAI,OAAK,EAAE,IAAI,CAAC;AAEvD,QAAM,SAAmD,CAAC;AAG1D,MAAI,CAACN,YAAW,UAAU,EAAG,QAAO;AAEpC,QAAM,OAAOI,aAAY,YAAY,EAAE,eAAe,KAAK,CAAC,EACzD,OAAO,OAAK,EAAE,YAAY,CAAC;AAE9B,aAAW,OAAO,MAAM;AACtB,UAAM,QAAQ,cAAc,IAAI,IAAI;AACpC,QAAI,OAAO;AACT,aAAO,KAAK;AAAA,QACV,GAAG;AAAA,QACH,YAAY,UAAU,IAAI,MAAM,EAAE;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,UAAU,SAAuB;AAE/C,QAAM,eAAe,QAAQ,WAAW,QAAQ,IAAI,UAAU,SAAS,QAAQ,YAAY,CAAC;AAE5F,MAAI,cAAc,YAAY,GAAG;AAC/B,gBAAY,YAAY;AAAA,EAC1B;AAEA,QAAM,QAAQ,cAAc,YAAY;AACxC,MAAI,OAAO;AACT,UAAM,SAAS;AACf,mBAAe,KAAK;AAAA,EACtB;AACF;AAEO,SAAS,aAAa,SAAiB,SAAuB;AAEnE,QAAM,eAAe,QAAQ,WAAW,QAAQ,IAAI,UAAU,SAAS,QAAQ,YAAY,CAAC;AAE5F,MAAI,CAAC,cAAc,YAAY,GAAG;AAChC,UAAM,IAAI,MAAM,SAAS,YAAY,cAAc;AAAA,EACrD;AAEA,WAAS,cAAc,OAAO;AAG9B,QAAM,UAAUC,MAAK,YAAY,YAAY,GAAG,MAAM;AACtD,EAAAJ,WAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAEtC,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC/D,EAAAC;AAAA,IACEG,MAAK,SAAS,GAAG,SAAS,KAAK;AAAA,IAC/B;AAAA;AAAA,EAAgB,OAAO;AAAA;AAAA,EACzB;AACF;AAKO,SAAS,sBAAoC;AAClD,QAAM,SAAS,kBAAkB;AACjC,SAAO,OAAO;AAAA,IACZ,CAAC,UAAU,MAAM,WAAW,aAAa,CAAC,MAAM;AAAA,EAClD;AACF;AAKO,SAAS,aAAa,SAAoC;AAC/D,QAAM,eAAe,QAAQ,WAAW,QAAQ,IAAI,UAAU,SAAS,QAAQ,YAAY,CAAC;AAC5F,QAAM,QAAQ,cAAc,YAAY;AAExC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAGA,MAAI,cAAc,YAAY,GAAG;AAC/B,WAAO;AAAA,EACT;AAGA,QAAM,aAAaA,MAAK,YAAY,YAAY,GAAG,aAAa;AAChE,MAAI,SAAS,EAAE,qBAAqB,GAAG,WAAW,GAAG,eAAe,EAAE;AACtE,MAAIL,YAAW,UAAU,GAAG;AAC1B,QAAI;AACF,eAAS,EAAE,GAAG,QAAQ,GAAG,KAAK,MAAMG,cAAa,YAAY,OAAO,CAAC,EAAE;AAAA,IACzE,QAAQ;AAAA,IAAC;AAAA,EACX;AACA,SAAO,iBAAiB,OAAO,iBAAiB,KAAK;AACrD,EAAAD,eAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAGzD,QAAM,iBAAiB,uBAAuB,KAAK;AAGnD,QAAM,YAAY,iDAAiD,MAAM,KAAK,KAAK,eAAe,QAAQ,MAAM,KAAK,EAAE,QAAQ,OAAO,KAAK,CAAC;AAC5I,gBAAc,cAAc,MAAM,WAAW,SAAS;AAGtD,QAAM,SAAS;AACf,QAAM,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAC5C,iBAAe,KAAK;AAEpB,SAAO;AACT;AAKA,SAAS,uBAAuB,OAA2B;AACzD,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,MAAM,OAAO;AAAA,IACzB,gBAAgB,MAAM,SAAS;AAAA,IAC/B,cAAc,MAAM,SAAS;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,0CAA0C,MAAM,UAAU;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,QAAM,EAAE,QAAQ,IAAI,UAAU,MAAM,EAAE;AACtC,MAAI,SAAS;AACX,UAAM,aAAa,mBAAmB,MAAM,EAAE;AAC9C,QAAI,YAAY;AACd,YAAM,KAAK,KAAK;AAChB,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,UAAU;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKO,SAAS,oBAA+D;AAC7E,QAAM,UAAU,oBAAoB;AACpC,QAAM,YAAsB,CAAC;AAC7B,QAAM,SAAmB,CAAC;AAE1B,aAAW,SAAS,SAAS;AAC3B,QAAI;AACF,YAAM,SAAS,aAAa,MAAM,EAAE;AACpC,UAAI,QAAQ;AACV,kBAAU,KAAK,MAAM,EAAE;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,MAAM,EAAE;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,MAAM,EAAE;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,EAAE,WAAW,OAAO;AAC7B;AAKA,SAAS,qBAA2B;AAClC,QAAM,EAAE,SAAAK,SAAQ,IAAI,UAAQ,IAAI;AAChC,QAAM,eAAeF,MAAKE,SAAQ,GAAG,WAAW,eAAe;AAC/D,QAAM,WAAWF,MAAKE,SAAQ,GAAG,eAAe,OAAO,gBAAgB;AAGvE,MAAIP,YAAW,YAAY,GAAG;AAC5B,QAAI;AACF,YAAM,kBAAkBG,cAAa,cAAc,OAAO;AAC1D,YAAM,WAAW,KAAK,MAAM,eAAe;AAC3C,YAAM,cAAc,UAAU,OAAO,eAAe,CAAC;AAErD,YAAM,iBAAiB,YAAY;AAAA,QAAK,CAAC,eACvC,WAAW,OAAO;AAAA,UAAK,CAAC,SACtB,KAAK,YAAY,YACjB,KAAK,SAAS,SAAS,YAAY,KACnC,KAAK,SAAS,SAAS,gBAAgB;AAAA,QACzC;AAAA,MACF;AAEA,UAAI,gBAAgB;AAClB;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,MAAI;AACF,YAAQ,IAAI,2CAA2C;AACvD,IAAAG,UAAS,mBAAmB,EAAE,OAAO,OAAO,CAAC;AAC7C,YAAQ,IAAI,mCAA8B;AAAA,EAC5C,SAAS,OAAO;AACd,YAAQ,KAAK,wEAAmE;AAAA,EAClF;AACF;AAKA,SAAS,eAAe,SAAiB,SAAuB;AAC9D,QAAM,WAAWD,MAAK,YAAY,OAAO,CAAC;AAC1C,EAAAJ,WAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAEvC,QAAM,YAAYI,MAAK,UAAU,mBAAmB;AACpD,EAAAH;AAAA,IACE;AAAA,IACA,KAAK,UAAU;AAAA,MACb,IAAI;AAAA,MACJ,OAAO,cAAc,OAAO;AAAA,MAC5B,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrC,GAAG,MAAM,CAAC;AAAA,EACZ;AACF;AAnYA;AAAA;AAAA;AAAA;AAGA;AACA;AACA;AACA;AAAA;AAAA;;;ACNA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,SAAW;AAAA,MACX,aAAe;AAAA,MACf,UAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,QAAU;AAAA,MACV,SAAW;AAAA,MACX,YAAc;AAAA,QACZ,MAAQ;AAAA,QACR,KAAO;AAAA,MACT;AAAA,MACA,UAAY;AAAA,MACZ,MAAQ;AAAA,QACN,KAAO;AAAA,MACT;AAAA,MACA,MAAQ;AAAA,MACR,KAAO;AAAA,QACL,KAAO;AAAA,QACP,YAAc;AAAA,MAChB;AAAA,MACA,MAAQ;AAAA,MACR,OAAS;AAAA,MACT,OAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,MACV;AAAA,MACA,SAAW;AAAA,QACT,KAAO;AAAA,QACP,OAAS;AAAA,QACT,WAAa;AAAA,QACb,MAAQ;AAAA,QACR,MAAQ;AAAA,QACR,aAAa;AAAA,QACb,oBAAoB;AAAA,QACpB,YAAY;AAAA,QACZ,iBAAiB;AAAA,QACjB,MAAQ;AAAA,QACR,cAAc;AAAA,QACd,gBAAkB;AAAA,QAClB,aAAe;AAAA,MACjB;AAAA,MACA,cAAgB;AAAA,QACd,eAAe;AAAA,QACf,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,kBAAkB;AAAA,QAClB,OAAS;AAAA,QACT,WAAa;AAAA,QACb,MAAQ;AAAA,QACR,OAAS;AAAA,QACT,UAAY;AAAA,QACZ,KAAO;AAAA,QACP,OAAS;AAAA,QACT,MAAQ;AAAA,MACV;AAAA,MACA,iBAAmB;AAAA,QACjB,yBAAyB;AAAA,QACzB,mBAAmB;AAAA,QACnB,eAAe;AAAA,QACf,uBAAuB;AAAA,QACvB,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,KAAO;AAAA,QACP,SAAW;AAAA,QACX,YAAc;AAAA,QACd,QAAU;AAAA,MACZ;AAAA,IACF;AAAA;AAAA;;;AClFA;AACA,SAAS,eAAe;AACxB,OAAOM,aAAW;;;ACFlB;AAKA;AALA,SAAS,YAAY,WAAW,aAAa,cAAc;AAC3D,SAAS,MAAM,eAAe;AAC9B,SAAS,qBAAqB;AAC9B,OAAO,WAAW;AAClB,OAAO,SAAS;AAOhB,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,QAAQ,UAAU;AACpC,IAAM,eAAe,KAAK,WAAW,MAAM,IAAI;AAC/C,IAAM,qBAAqB,KAAK,cAAc,QAAQ;AACtD,IAAM,qBAAqB,KAAK,cAAc,QAAQ;AAMtD,SAAS,oBAA4B;AACnC,MAAI,CAAC,WAAW,kBAAkB,GAAG;AACnC,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,cAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AAEA,QAAM,SAAS,YAAY,oBAAoB,EAAE,eAAe,KAAK,CAAC,EACnE,OAAO,OAAK,EAAE,YAAY,CAAC;AAE9B,MAAI,SAAS;AACb,aAAW,SAAS,QAAQ;AAC1B,UAAM,aAAa,KAAK,oBAAoB,MAAM,IAAI;AACtD,UAAM,aAAa,KAAK,YAAY,MAAM,IAAI;AAG9C,WAAO,YAAY,YAAY,EAAE,WAAW,KAAK,CAAC;AAClD;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,oBAA4B;AACnC,MAAI,CAAC,WAAW,kBAAkB,GAAG;AACnC,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,cAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AAEA,QAAM,SAAS,YAAY,oBAAoB,EAAE,eAAe,KAAK,CAAC,EACnE,OAAO,WAAS,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,KAAK,CAAC;AAE/D,MAAI,SAAS;AACb,aAAW,SAAS,QAAQ;AAC1B,UAAM,aAAa,KAAK,oBAAoB,MAAM,IAAI;AACtD,UAAM,aAAa,KAAK,YAAY,MAAM,IAAI;AAG9C,WAAO,YAAY,UAAU;AAC7B;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,cAA6B;AACjD,QAAM,UAAU,IAAI,4BAA4B,EAAE,MAAM;AAGxD,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,KAAK,gCAAgC;AAC7C,YAAQ,IAAI,MAAM,IAAI,aAAa,WAAW,EAAE,CAAC;AACjD,YAAQ,IAAI,MAAM,IAAI,WAAW,eAAe,EAAE,CAAC;AACnD,YAAQ,IAAI,MAAM,IAAI,mCAAmC,CAAC;AAC1D;AAAA,EACF;AAEA,MAAI;AAEF,eAAW,OAAO,WAAW;AAC3B,UAAI,CAAC,WAAW,GAAG,GAAG;AACpB,kBAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,MACpC;AAAA,IACF;AACA,YAAQ,OAAO;AAGf,UAAM,SAAS,iBAAiB;AAChC,eAAW,MAAM;AACjB,YAAQ,OAAO;AAGf,YAAQ,OAAO;AACf,UAAM,eAAe,kBAAkB;AAGvC,YAAQ,OAAO;AACf,UAAM,eAAe,kBAAkB;AAGvC,UAAM,QAAQ,YAAY;AAC1B,UAAM,SAAS,eAAe,KAAK;AAEnC,QAAI,UAAU,WAAW,MAAM,GAAG;AAChC,eAAS,MAAM;AACf,cAAQ,QAAQ,yBAAyB;AACzC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,MAAM,KAAK,eAAe,CAAC;AACxE,cAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,MAAM,KAAK,WAAW,CAAC;AACpE,UAAI,eAAe,GAAG;AACpB,gBAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,YAAY,iBAAiB;AAAA,MAC5E;AACA,UAAI,eAAe,GAAG;AACpB,gBAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,YAAY,iBAAiB;AAAA,MAC5E;AACA,cAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,MAAM,qBAAqB,KAAK,CAAC;AAAA,IAClE,OAAO;AACL,cAAQ,QAAQ,yBAAyB;AACzC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,MAAM,KAAK,eAAe,CAAC;AACxE,cAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,MAAM,KAAK,WAAW,CAAC;AACpE,UAAI,eAAe,GAAG;AACpB,gBAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,YAAY,iBAAiB;AAAA,MAC5E;AACA,UAAI,eAAe,GAAG;AACpB,gBAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,cAAc,YAAY,iBAAiB;AAAA,MAC5E;AACA,cAAQ,IAAI,MAAM,OAAO,GAAG,IAAI,8CAA8C;AAC9E,cAAQ,IAAI,MAAM,IAAI,4BAA4B,CAAC;AAAA,IACrD;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,aAAa;AACzB,YAAQ,IAAI,MAAM,IAAI,oBAAoB,CAAC;AAC3C,YAAQ,IAAI,MAAM,IAAI,8BAA8B,CAAC;AAAA,EAEvD,SAAS,OAAY;AACnB,YAAQ,KAAK,sBAAsB;AACnC,YAAQ,MAAM,MAAM,IAAI,MAAM,OAAO,CAAC;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACzJA;AAAA,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAIhB;AAQA,eAAsB,YAAY,SAAqC;AACrE,QAAM,SAAS,WAAW;AAC1B,QAAM,UAAU,OAAO,MAAM;AAG7B,MAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAAG;AAC/D,YAAQ,IAAIC,OAAM,OAAO,6BAA6B,CAAC;AACvD,YAAQ,IAAIA,OAAM,IAAI,sEAAsE,CAAC;AAC7F,YAAQ,IAAIA,OAAM,IAAI,8CAA8C,CAAC;AACrE;AAAA,EACF;AAGA,QAAM,eAAe;AAGrB,MAAI,QAAQ,QAAQ;AAClB,YAAQ,IAAIA,OAAM,KAAK,wBAAwB,CAAC;AAGhD,UAAM,YAAY,cAAc;AAChC,QAAI,UAAU,SAAS,GAAG;AACxB,cAAQ,IAAIA,OAAM,KAAK,sBAAsB,CAAC;AAC9C,iBAAW,QAAQ,WAAW;AAC5B,cAAM,OAAO,KAAK,WAAW,QAAQA,OAAM,MAAM,GAAG,IAAIA,OAAM,KAAK,QAAG;AACtE,cAAM,SAAS,KAAK,WAAW,QAAQ,KAAKA,OAAM,IAAI,UAAU;AAChE,gBAAQ,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,EAAE;AAAA,MAChD;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,eAAW,WAAW,cAAc;AAClC,YAAM,OAAO,SAAS,OAAO;AAE7B,cAAQ,IAAIA,OAAM,KAAK,GAAG,OAAO,GAAG,CAAC;AAErC,UAAI,KAAK,OAAO,WAAW,KAAK,KAAK,SAAS,WAAW,KAAK,KAAK,OAAO,WAAW,GAAG;AACtF,gBAAQ,IAAIA,OAAM,IAAI,qBAAqB,CAAC;AAC5C;AAAA,MACF;AAEA,iBAAW,QAAQ,KAAK,QAAQ;AAC9B,cAAM,OAAO,KAAK,WAAW,aAAaA,OAAM,OAAO,GAAG,IAAIA,OAAM,MAAM,GAAG;AAC7E,cAAM,SAAS,KAAK,WAAW,aAAaA,OAAM,OAAO,YAAY,IAAI;AACzE,gBAAQ,IAAI,KAAK,IAAI,UAAU,KAAK,IAAI,IAAI,MAAM,EAAE;AAAA,MACtD;AAEA,iBAAW,QAAQ,KAAK,UAAU;AAChC,cAAM,OAAO,KAAK,WAAW,aAAaA,OAAM,OAAO,GAAG,IAAIA,OAAM,MAAM,GAAG;AAC7E,cAAM,SAAS,KAAK,WAAW,aAAaA,OAAM,OAAO,YAAY,IAAI;AACzE,gBAAQ,IAAI,KAAK,IAAI,YAAY,KAAK,IAAI,IAAI,MAAM,EAAE;AAAA,MACxD;AAEA,iBAAW,QAAQ,KAAK,QAAQ;AAC9B,cAAM,OAAO,KAAK,WAAW,aAAaA,OAAM,OAAO,GAAG,IAAIA,OAAM,MAAM,GAAG;AAC7E,cAAM,SAAS,KAAK,WAAW,aAAaA,OAAM,OAAO,YAAY,IAAI;AACzE,gBAAQ,IAAI,KAAK,IAAI,UAAU,KAAK,IAAI,IAAI,MAAM,EAAE;AAAA,MACtD;AAEA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,YAAQ,IAAIA,OAAM,IAAI,yCAAyC,CAAC;AAChE;AAAA,EACF;AAGA,MAAI,OAAO,KAAK,oBAAoB;AAClC,UAAMC,WAAUC,KAAI,oBAAoB,EAAE,MAAM;AAEhD,UAAM,aAAa,aAAa,QAAQ,CAAC,MAAM;AAAA,MAC7C,aAAa,CAAC,EAAE;AAAA,MAChB,aAAa,CAAC,EAAE;AAAA,MAChB,aAAa,CAAC,EAAE;AAAA,IAClB,CAAC;AAED,UAAMC,UAAS,aAAa,UAAU;AAEtC,QAAIA,QAAO,QAAQ,SAAS,GAAG;AAC7B,MAAAF,SAAQ,QAAQ,mBAAmBE,QAAO,SAAS,EAAE;AAAA,IACvD,OAAO;AACL,MAAAF,SAAQ,KAAK,+BAA+B;AAAA,IAC9C;AAEA,QAAI,QAAQ,YAAY;AACtB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UAAUC,KAAI,YAAY,EAAE,MAAM;AAExC,MAAI,eAAe;AACnB,MAAI,iBAAiB;AAErB,aAAW,WAAW,cAAc;AAClC,YAAQ,OAAO,cAAc,OAAO;AAEpC,UAAM,SAAS,YAAY,SAAS,EAAE,OAAO,QAAQ,MAAM,CAAC;AAE5D,oBAAgB,OAAO,QAAQ;AAC/B,sBAAkB,OAAO,UAAU;AAEnC,QAAI,OAAO,UAAU,SAAS,KAAK,CAAC,QAAQ,OAAO;AACjD,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIF,OAAM,OAAO,gBAAgB,OAAO,GAAG,CAAC;AACpD,iBAAW,QAAQ,OAAO,WAAW;AACnC,gBAAQ,IAAIA,OAAM,IAAI,OAAO,IAAI,6BAA6B,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,iBAAiB,KAAK,CAAC,QAAQ,OAAO;AACxC,YAAQ,KAAK,UAAU,YAAY,WAAW,cAAc,YAAY;AACxE,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,IAAI,6CAA6C,CAAC;AAAA,EACtE,OAAO;AACL,YAAQ,QAAQ,UAAU,YAAY,aAAa,aAAa,KAAK,IAAI,CAAC,EAAE;AAAA,EAC9E;AAGA,QAAM,eAAeE,KAAI,kBAAkB,EAAE,MAAM;AACnD,QAAM,cAAc,UAAU;AAE9B,MAAI,YAAY,OAAO,SAAS,GAAG;AACjC,iBAAa,KAAK,UAAU,YAAY,OAAO,MAAM,WAAW,YAAY,OAAO,MAAM,SAAS;AAClG,eAAW,SAAS,YAAY,QAAQ;AACtC,cAAQ,IAAIF,OAAM,IAAI,YAAO,KAAK,EAAE,CAAC;AAAA,IACvC;AAAA,EACF,WAAW,YAAY,OAAO,SAAS,GAAG;AACxC,iBAAa,QAAQ,UAAU,YAAY,OAAO,MAAM,8BAA8B;AAAA,EACxF,OAAO;AACL,iBAAa,KAAK,kBAAkB;AAAA,EACtC;AACF;;;ACnJA;AAAA,OAAOI,YAAW;AAClB,OAAOC,UAAS;AAChB,OAAO,cAAc;AAGrB;AAEA,eAAsB,eAAe,WAAmC;AACtE,QAAM,UAAU,YAAY;AAE5B,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAIC,OAAM,OAAO,mBAAmB,CAAC;AAC7C;AAAA,EACF;AAGA,MAAI,CAAC,WAAW;AACd,YAAQ,IAAIA,OAAM,KAAK,sBAAsB,CAAC;AAE9C,eAAWC,WAAU,QAAQ,MAAM,GAAG,EAAE,GAAG;AACzC,cAAQ,IAAI,KAAKD,OAAM,KAAKC,QAAO,SAAS,CAAC,MAAMA,QAAO,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,IAChF;AAEA,QAAI,QAAQ,SAAS,IAAI;AACvB,cAAQ,IAAID,OAAM,IAAI,aAAa,QAAQ,SAAS,EAAE,OAAO,CAAC;AAAA,IAChE;AAEA,YAAQ,IAAI,EAAE;AAEd,UAAM,EAAE,SAAS,IAAI,MAAM,SAAS,OAAO;AAAA,MACzC;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS,QAAQ,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,OAAO;AAAA,UACxC,MAAM,GAAG,EAAE,SAAS,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,UAC7C,OAAO,EAAE;AAAA,QACX,EAAE;AAAA,MACJ;AAAA,IACF,CAAC;AAED,gBAAY;AAAA,EACd;AAGA,QAAM,EAAE,QAAQ,IAAI,MAAM,SAAS,OAAO;AAAA,IACxC;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,kBAAkB,SAAS;AAAA,MACpC,SAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,MAAI,CAAC,SAAS;AACZ,YAAQ,IAAIA,OAAM,IAAI,oBAAoB,CAAC;AAC3C;AAAA,EACF;AAEA,QAAM,UAAUE,KAAI,qBAAqB,EAAE,MAAM;AAEjD,MAAI;AACF,UAAM,SAAS,WAAW;AAC1B,UAAM,UAAU,OAAO,KAAK;AAG5B,UAAM,aAAqC,CAAC;AAE5C,eAAW,WAAW,SAAS;AAC7B,iBAAW,GAAG,OAAO,SAAS,IAAI,aAAa,OAAO,EAAE;AACxD,iBAAW,GAAG,OAAO,WAAW,IAAI,aAAa,OAAO,EAAE;AAE1D,iBAAW,QAAQ,IAAI,aAAa,OAAO,EAAE;AAC7C,iBAAW,UAAU,IAAI,aAAa,OAAO,EAAE;AAAA,IACjD;AAEA,kBAAc,WAAY,UAAU;AAEpC,YAAQ,QAAQ,oBAAoB,SAAS,EAAE;AAAA,EAEjD,SAAS,OAAY;AACnB,YAAQ,KAAK,mBAAmB;AAChC,YAAQ,MAAMF,OAAM,IAAI,MAAM,OAAO,CAAC;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACrFA;AAAA,OAAOG,YAAW;AAGlB,eAAsB,kBAAkB,SAA4C;AAClF,QAAM,UAAU,YAAY;AAE5B,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC5C;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAIC,OAAM,IAAI,mBAAmB,CAAC;AAC1C,YAAQ,IAAIA,OAAM,IAAI,gDAAgD,CAAC;AACvE;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,KAAK,YAAY,CAAC;AAEpC,aAAWC,WAAU,SAAS;AAC5B,YAAQ,IAAI,KAAKD,OAAM,KAAKC,QAAO,SAAS,CAAC,EAAE;AAC/C,YAAQ,IAAI,OAAOD,OAAM,IAAI,WAAW,CAAC,IAAIC,QAAO,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EAC1E;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAID,OAAM,IAAI,UAAU,QAAQ,MAAM,UAAU,CAAC;AACzD,UAAQ,IAAIA,OAAM,IAAI,oDAAoD,CAAC;AAC7E;AAEA,eAAsB,mBAAmB,SAA2C;AAClF,QAAM,YAAY,SAAS,QAAQ,QAAQ,MAAM,EAAE;AACnD,QAAM,UAAU,gBAAgB,SAAS;AAEzC,MAAI,YAAY,GAAG;AACjB,YAAQ,IAAIA,OAAM,IAAI,+BAA+B,SAAS,IAAI,CAAC;AAAA,EACrE,OAAO;AACL,YAAQ,IAAIA,OAAM,MAAM,WAAW,OAAO,2BAA2B,SAAS,GAAG,CAAC;AAAA,EACpF;AACF;;;ACtCA;AAGA;AAHA,SAAS,eAAAE,cAAa,cAAc,cAAAC,mBAAkB;AACtD,SAAS,QAAAC,aAAY;AACrB,OAAOC,YAAW;AASlB,SAAS,sBAAsB,SAA0D;AACvF,QAAM,QAAQ,QAAQ,MAAM,uBAAuB;AACnD,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,QAAM,cAAc,MAAM,CAAC;AAC3B,QAAM,OAAO,YAAY,MAAM,cAAc,IAAI,CAAC,GAAG,KAAK;AAC1D,QAAM,cAAc,YAAY,MAAM,qBAAqB,IAAI,CAAC,GAAG,KAAK;AAExE,SAAO,EAAE,MAAM,YAAY;AAC7B;AAEO,SAAS,aAA0B;AACxC,MAAI,CAACF,YAAW,UAAU,EAAG,QAAO,CAAC;AAErC,QAAM,SAAsB,CAAC;AAC7B,QAAM,OAAOD,aAAY,YAAY,EAAE,eAAe,KAAK,CAAC,EACzD,OAAO,OAAK,EAAE,YAAY,CAAC;AAE9B,aAAW,OAAO,MAAM;AACtB,UAAM,YAAYE,MAAK,YAAY,IAAI,MAAM,UAAU;AACvD,QAAI,CAACD,YAAW,SAAS,EAAG;AAE5B,UAAM,UAAU,aAAa,WAAW,MAAM;AAC9C,UAAM,EAAE,MAAM,YAAY,IAAI,sBAAsB,OAAO;AAE3D,WAAO,KAAK;AAAA,MACV,MAAM,QAAQ,IAAI;AAAA,MAClB,aAAa,eAAe;AAAA,MAC5B,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO,OAAO,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC3D;AAEA,eAAsB,cAAc,SAA4C;AAC9E,QAAM,SAAS,WAAW;AAE1B,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,EACF;AAEA,UAAQ,IAAIE,OAAM,KAAK;AAAA,qBAAwB,OAAO,MAAM;AAAA,CAAK,CAAC;AAElE,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAIA,OAAM,OAAO,kBAAkB,CAAC;AAC5C,YAAQ,IAAIA,OAAM,IAAI,0DAA0D,CAAC;AACjF;AAAA,EACF;AAEA,aAAW,SAAS,QAAQ;AAC1B,YAAQ,IAAIA,OAAM,KAAK,MAAM,IAAI,CAAC;AAClC,YAAQ,IAAIA,OAAM,IAAI,KAAK,MAAM,WAAW,EAAE,CAAC;AAAA,EACjD;AAEA,UAAQ,IAAI;AAAA,EAAKA,OAAM,IAAI,8CAA8C,CAAC,EAAE;AAC9E;;;ACpEA;;;ACAA;AAIA;AAJA,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAChB,SAAS,cAAAC,aAAY,gBAAAC,qBAAiC;AACtD,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAe9B,SAAS,cAAc,SAAiB,SAAmB,CAAC,GAAkB;AAC5E,QAAM,eAAe,QAAQ,YAAY;AAGzC,QAAM,WAAW,wBAAwB,SAAS,MAAM;AACxD,MAAI,UAAU;AACZ,UAAM,gBAAgB,WAAW,YAAY;AAC7C,UAAM,gBAAgBC,MAAK,SAAS,aAAa,cAAc,aAAa;AAC5E,QAAIC,YAAW,aAAa,GAAG;AAC7B,aAAO;AAAA,IACT;AAEA,UAAM,UAAUD,MAAK,SAAS,aAAa,cAAc,YAAY;AACrE,QAAIC,YAAW,OAAO,GAAG;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,IAAI;AACtB,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,gBAAgBD,MAAK,KAAK,YAAY;AAC5C,QAAIC,YAAW,aAAa,GAAG;AAE7B,YAAM,gBAAgB,WAAW,YAAY;AAC7C,YAAM,gBAAgBD,MAAK,eAAe,aAAa;AACvD,UAAIC,YAAW,aAAa,GAAG;AAC7B,eAAO;AAAA,MACT;AAGA,YAAM,UAAUD,MAAK,eAAe,YAAY;AAChD,UAAIC,YAAW,OAAO,GAAG;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,SAASC,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AAEA,SAAO;AACT;AAMA,SAAS,gBAAgB,SAAkB,SAAmB,CAAC,GAAW;AAExE,MAAI,SAAS;AACX,UAAM,WAAW,wBAAwB,SAAS,MAAM;AACxD,QAAI,UAAU;AACZ,aAAO,SAAS;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,IAAI;AACtB,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,QAAID,YAAWD,MAAK,KAAK,YAAY,CAAC,KAClCC,YAAWD,MAAK,KAAK,MAAM,CAAC,KAC5BC,YAAWD,MAAK,KAAK,WAAW,CAAC,GAAG;AACtC,aAAO;AAAA,IACT;AACA,UAAM,SAASE,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,SAAO,QAAQ,IAAI;AACrB;AAKA,SAAS,oBAAoB,eAAsC;AACjE,QAAM,YAAYF,MAAK,eAAe,aAAa,UAAU;AAC7D,MAAIC,YAAW,SAAS,GAAG;AACzB,WAAOE,cAAa,WAAW,OAAO;AAAA,EACxC;AACA,SAAO;AACT;AAMA,SAAS,yBAAyB,cAAgC;AAChE,QAAM,MAAgB,CAAC;AAGvB,QAAM,kBAAkB,aAAa,MAAM,uBAAuB,KAAK,CAAC;AACxE,aAAW,SAAS,iBAAiB;AACnC,UAAM,KAAK,MAAM,QAAQ,MAAM,EAAE;AAEjC,QAAI,GAAG,MAAM,wBAAwB,GAAG;AACtC,UAAI,KAAK,EAAE;AAAA,IACb;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,IAAI,IAAI,GAAG,CAAC;AACzB;AAMA,SAAS,eAAe,eAAuB,aAAqB,SAA2B;AAC7F,QAAM,QAAkB,CAAC;AACzB,QAAM,eAAe,QAAQ,YAAY;AAGzC,QAAM,eAAe,oBAAoB,aAAa;AACtD,QAAM,WAAW,eAAe,yBAAyB,YAAY,IAAI,CAAC;AAG1E,QAAM,aAAa;AAAA,IACjBH,MAAK,eAAe,UAAU,cAAc;AAAA,IAC5CA,MAAK,aAAa,UAAU,cAAc;AAAA,EAC5C;AAEA,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,aAAa,YAAY;AAClC,QAAI,CAACC,YAAW,SAAS,EAAG;AAE5B,QAAI;AACF,YAAM,UAAUE,cAAa,WAAW,OAAO;AAC/C,YAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,KAAK,CAAC;AAE5D,iBAAW,QAAQ,OAAO;AACxB,YAAI;AACF,gBAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,cAAI,QAAQ,IAAI,KAAK,EAAE,EAAG;AAM1B,gBAAM,OAAO,KAAK,QAAQ,CAAC;AAC3B,gBAAM,UACJ,SAAS,SAAS,KAAK,EAAE,KACzB,KAAK,KAAK,CAAC,MAAc,EAAE,YAAY,EAAE,SAAS,YAAY,CAAC,KAC/D,KAAK,OAAO,YAAY,EAAE,SAAS,YAAY;AAEjD,cAAI,SAAS;AACX,oBAAQ,IAAI,KAAK,EAAE;AACnB,kBAAM,KAAK,MAAM,KAAK,UAAU,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,GAAG;AAAA,UACtE;AAAA,QACF,QAAQ;AAAA,QAAC;AAAA,MACX;AAAA,IACF,QAAQ;AAAA,IAAC;AAAA,EACX;AAEA,SAAO;AACT;AAKA,SAAS,iBAAiB,SAAiB,eAAuB,aAA6B;AAC7F,QAAM,QAAkB;AAAA,IACtB,uBAAuB,OAAO;AAAA,IAC9B;AAAA,IACA,kBAAkB,aAAa;AAAA,IAC/B;AAAA,EACF;AAGA,QAAM,eAAeF,YAAWD,MAAK,eAAe,aAAa,UAAU,CAAC;AAC5E,QAAM,cAAcC,YAAWD,MAAK,eAAe,WAAW,CAAC;AAC/D,QAAM,qBAAqBC,YAAWD,MAAK,aAAa,WAAW,CAAC;AAGpE,QAAM,KAAK,wCAAwC;AACnD,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,qFAAqF;AAChG,QAAM,KAAK,EAAE;AAEb,MAAI,cAAc;AAChB,UAAM,KAAK,6HAA6H;AAAA,EAC1I;AACA,MAAI,aAAa;AACf,UAAM,KAAK,mGAAmG;AAAA,EAChH;AACA,MAAI,sBAAsB,gBAAgB,eAAe;AACvD,UAAM,KAAK,eAAe,WAAW,gEAAgE;AAAA,EACvG;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,yFAAyF;AACpG,QAAM,KAAK,EAAE;AAGb,QAAM,aAAa,eAAe,eAAe,aAAa,OAAO;AACrE,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,KAAK,gBAAgB;AAC3B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,wEAAwE;AACnF,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,WAAW,KAAK,IAAI,CAAC;AAChC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,wGAAwG;AACnH,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,cAAc;AACzB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,wCAAwC;AACnD,QAAM,KAAK,4DAA4D;AACvE,QAAM,KAAK,2CAA2C;AACtD,QAAM,KAAK,2FAA2F;AACtG,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,oCAAoC;AAC/C,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,sGAAsG;AACjH,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oEAAoE;AAC/E,QAAM,KAAK,6FAA6F;AACxG,QAAM,KAAK,wDAAwD;AACnE,QAAM,KAAK,+CAA+C;AAC1D,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,yGAAyG;AACpH,QAAM,KAAK,gGAAgG;AAC3G,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,2CAA2C;AACtD,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,mDAAmD;AAC9D,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,wEAAwE;AACnF,QAAM,KAAK,2FAA2F;AACtG,QAAM,KAAK,6EAA6E;AACxF,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,0CAA0C;AACrD,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,8DAA8D;AACzE,QAAM,KAAK,uEAAuE;AAClF,QAAM,KAAK,yDAAyD;AACpE,QAAM,KAAK,kFAAkF;AAC7F,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,gGAAgG;AAC3G,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,eAAsB,aAAa,IAAY,SAAsC;AACnF,QAAM,UAAUI,KAAI,2BAA2B,EAAE,KAAK,EAAE,MAAM;AAE9D,MAAI;AAEF,UAAM,eAAe,GAAG,YAAY;AAGpC,UAAM,cAAc,gBAAgB,EAAE;AACtC,QAAI,YAAY,cAAc,EAAE;AAGhC,UAAM,WAAW,wBAAwB,EAAE;AAC3C,QAAI,UAAU;AACZ,cAAQ,OAAO,qBAAqB,SAAS,WAAW,KAAK,SAAS,WAAW;AAAA,IACnF;AAEA,QAAI,CAAC,WAAW;AACd,cAAQ,KAAK,0BAA0B,EAAE,sBAAsB;AAC/D,kBAAY;AAAA,IACd,OAAO;AACL,cAAQ,OAAO,oBAAoB,SAAS;AAAA,IAC9C;AAEA,QAAI,QAAQ,QAAQ;AAClB,cAAQ,KAAK,cAAc;AAC3B,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIC,OAAM,KAAK,eAAe,CAAC;AACvC,cAAQ,IAAI,uBAAuB,YAAY,EAAE;AACjD,cAAQ,IAAI,iBAAiB,SAAS,EAAE;AACxC,cAAQ,IAAI,iBAAiB,QAAQ,OAAO,EAAE;AAC9C,cAAQ,IAAI,iBAAiB,QAAQ,KAAK,EAAE;AAG5C,YAAMC,mBAAkB,oBAAoB,SAAS;AACrD,YAAMC,cAAa,eAAe,WAAW,aAAa,EAAE;AAC5D,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIF,OAAM,KAAK,UAAU,CAAC;AAClC,cAAQ,IAAI,iBAAiBC,mBAAkB,+BAA+B,MAAM,EAAE;AACtF,cAAQ,IAAI,iBAAiBC,YAAW,MAAM,QAAQ;AACtD;AAAA,IACF;AAEA,YAAQ,OAAO;AACf,UAAM,SAAS,iBAAiB,IAAI,WAAW,WAAW;AAE1D,YAAQ,OAAO;AAEf,UAAM,QAAQ,WAAW;AAAA,MACvB,SAAS;AAAA,MACT;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf;AAAA,IACF,CAAC;AAED,YAAQ,QAAQ,kBAAkB,MAAM,EAAE,EAAE;AAE5C,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIF,OAAM,KAAK,gBAAgB,CAAC;AACxC,YAAQ,IAAI,iBAAiBA,OAAM,KAAK,MAAM,EAAE,CAAC,EAAE;AACnD,YAAQ,IAAI,iBAAiB,SAAS,EAAE;AACxC,YAAQ,IAAI,iBAAiB,MAAM,OAAO,KAAK,MAAM,KAAK,GAAG;AAG7D,UAAM,kBAAkB,oBAAoB,SAAS;AACrD,UAAM,aAAa,eAAe,WAAW,aAAa,EAAE;AAC5D,QAAI,mBAAmB,WAAW,SAAS,GAAG;AAC5C,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AACzC,UAAI,gBAAiB,SAAQ,IAAI,iBAAiBA,OAAM,MAAM,QAAG,CAAC,WAAW;AAC7E,UAAI,WAAW,SAAS,EAAG,SAAQ,IAAI,iBAAiBA,OAAM,MAAM,QAAG,CAAC,IAAI,WAAW,MAAM,QAAQ;AAAA,IACvG;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,IAAI,WAAW,CAAC;AAClC,YAAQ,IAAI,8BAA8B,MAAM,EAAE,EAAE;AACpD,YAAQ,IAAI,6BAA6B,EAAE,iBAAiB;AAC5D,YAAQ,IAAI,6BAA6B,EAAE,EAAE;AAAA,EAE/C,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AClWA;AACA;AADA,OAAOG,YAAW;AAOlB,eAAsB,cAAc,SAAuC;AACzE,QAAM,SAAS,kBAAkB;AAEjC,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAIA,OAAM,IAAI,oBAAoB,CAAC;AAC3C,YAAQ,IAAIA,OAAM,IAAI,yCAAyC,CAAC;AAChE;AAAA,EACF;AAEA,UAAQ,IAAIA,OAAM,KAAK,oBAAoB,CAAC;AAE5C,aAAW,SAAS,QAAQ;AAC1B,UAAM,cAAc,MAAM,aAAaA,OAAM,QAAQA,OAAM;AAC3D,UAAM,SAAS,MAAM,aAAa,YAAY;AAE9C,UAAM,YAAY,IAAI,KAAK,MAAM,SAAS;AAC1C,UAAM,WAAW,KAAK,OAAO,KAAK,IAAI,IAAI,UAAU,QAAQ,KAAK,MAAO,EAAE;AAE1E,YAAQ,IAAI,GAAGA,OAAM,KAAK,MAAM,EAAE,CAAC,EAAE;AACrC,YAAQ,IAAI,eAAe,MAAM,OAAO,EAAE;AAC1C,YAAQ,IAAI,eAAe,YAAY,MAAM,CAAC,EAAE;AAChD,YAAQ,IAAI,eAAe,MAAM,OAAO,KAAK,MAAM,KAAK,GAAG;AAC3D,YAAQ,IAAI,eAAe,QAAQ,MAAM;AACzC,YAAQ,IAAI,gBAAgBA,OAAM,IAAI,MAAM,SAAS,CAAC,EAAE;AACxD,YAAQ,IAAI,EAAE;AAAA,EAChB;AACF;;;ACtCA;AACA;AADA,OAAOC,YAAW;AAGlB,eAAsB,YAAY,IAAY,SAAgC;AAC5E,QAAM,UAAU,GAAG,WAAW,QAAQ,IAAI,KAAK,SAAS,GAAG,YAAY,CAAC;AAExE,MAAI;AACF,iBAAa,SAAS,OAAO;AAC7B,YAAQ,IAAIA,OAAM,MAAM,qBAAqB,OAAO,CAAC;AACrD,YAAQ,IAAIA,OAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,EACzC,SAAS,OAAY;AACnB,YAAQ,MAAMA,OAAM,IAAI,YAAY,MAAM,OAAO,CAAC;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACdA;AACA;AACA;AAFA,OAAOC,YAAW;AAQlB,eAAsB,YAAY,IAAY,SAAqC;AACjF,QAAM,UAAU,GAAG,WAAW,QAAQ,IAAI,KAAK,SAAS,GAAG,YAAY,CAAC;AAGxE,QAAM,QAAQ,cAAc,OAAO;AACnC,QAAMC,aAAY,cAAc,OAAO;AAEvC,MAAI,CAAC,SAAS,CAACA,YAAW;AACxB,YAAQ,IAAID,OAAM,OAAO,SAAS,OAAO,aAAa,CAAC;AACvD;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,SAASC,YAAW;AAAA,EAGjC;AAEA,MAAI;AACF,cAAU,OAAO;AACjB,YAAQ,IAAID,OAAM,MAAM,iBAAiB,OAAO,EAAE,CAAC;AAAA,EACrD,SAAS,OAAY;AACnB,YAAQ,MAAMA,OAAM,IAAI,YAAY,MAAM,OAAO,CAAC;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AChCA;AACA;AAGA;AAJA,OAAOE,aAAW;AAElB,SAAS,cAAAC,aAAY,gBAAAC,qBAAiC;AACtD,SAAS,QAAAC,aAAY;AAGrB,eAAsB,iBAAgC;AAIpD,QAAM,SAAS,kBAAkB,EAAE,OAAO,OAAK,CAAC,EAAE,cAAc,EAAE,WAAW,OAAO;AAEpF,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAIH,QAAM,IAAI,qBAAqB,CAAC;AAC5C,YAAQ,IAAIA,QAAM,IAAI,kDAAkD,CAAC;AACzE;AAAA,EACF;AAEA,UAAQ,IAAIA,QAAM,KAAK,qBAAqB,CAAC;AAE7C,aAAW,SAAS,QAAQ;AAC1B,YAAQ,IAAI,GAAGA,QAAM,KAAK,MAAM,OAAO,CAAC,EAAE;AAC1C,YAAQ,IAAI,gBAAgB,MAAM,EAAE,EAAE;AACtC,YAAQ,IAAI,gBAAgBA,QAAM,IAAI,MAAM,SAAS,CAAC,EAAE;AAGxD,UAAM,iBAAiBG,MAAK,YAAY,MAAM,IAAI,eAAe;AACjE,QAAIF,YAAW,cAAc,GAAG;AAC9B,YAAM,UAAUC,cAAa,gBAAgB,MAAM;AACnD,YAAM,YAAY,QAAQ,MAAM,IAAI,EAAE,KAAK,OAAK,EAAE,KAAK,KAAK,CAAC,EAAE,WAAW,GAAG,CAAC;AAC9E,UAAI,WAAW;AACb,gBAAQ,IAAI,gBAAgBF,QAAM,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE;AAAA,MAC3D;AAAA,IACF;AAEA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAEA,UAAQ,IAAIA,QAAM,IAAI,mDAAmD,CAAC;AAC5E;;;ACvCA;AAEA;AAKA;AAPA,OAAOI,aAAW;AAClB,OAAOC,UAAS;AAEhB,SAAS,cAAAC,aAAY,iBAAAC,gBAAe,gBAAAC,qBAAoB;AACxD,SAAS,QAAAC,aAAY;AACrB,SAAS,eAAe;AACxB,SAAS,YAAAC,iBAAgB;AAQzB,SAAS,kBAAiC;AACxC,QAAM,UAAUD,MAAK,QAAQ,GAAG,iBAAiB;AACjD,MAAIH,YAAW,OAAO,GAAG;AACvB,UAAM,UAAUE,cAAa,SAAS,OAAO;AAC7C,UAAM,QAAQ,QAAQ,MAAM,qBAAqB;AACjD,QAAI,MAAO,QAAO,MAAM,CAAC,EAAE,KAAK;AAAA,EAClC;AACA,SAAO,QAAQ,IAAI,kBAAkB;AACvC;AAEA,SAAS,aAAsB;AAC7B,MAAI;AACF,IAAAE,UAAS,YAAY,EAAE,OAAO,OAAO,CAAC;AACtC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAAgB,WAA2D;AAClF,MAAI;AAEF,UAAM,SAASA,UAAS,mCAAmC;AAAA,MACzD,KAAK;AAAA,MACL,UAAU;AAAA,MACV,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAChC,CAAC,EAAE,KAAK;AAGR,UAAM,SAASA,UAAS,sBAAsB,MAAM,iCAAiC;AAAA,MACnF,KAAK;AAAA,MACL,UAAU;AAAA,MACV,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAChC,CAAC;AAED,UAAM,MAAM,KAAK,MAAM,MAAM;AAC7B,QAAI,IAAI,SAAS,GAAG;AAClB,aAAO,EAAE,QAAQ,IAAI,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC,EAAE,IAAI;AAAA,IAClD;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,QAAQ,WAAmB,UAAwD;AAC1F,MAAI;AACF,IAAAA,UAAS,eAAe,QAAQ,6BAA6B;AAAA,MAC3D,KAAK;AAAA,MACL,UAAU;AAAA,MACV,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAChC,CAAC;AACD,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB,SAAS,OAAY;AACnB,WAAO,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ;AAAA,EAChD;AACF;AAEA,eAAe,mBAAmB,QAAgB,iBAA2C;AAC3F,MAAI;AACF,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,aAAa;AACnD,UAAM,SAAS,IAAI,aAAa,EAAE,OAAO,CAAC;AAG1C,UAAM,KAAK,MAAM,OAAO;AACxB,UAAM,QAAQ,MAAM,GAAG,MAAM;AAC7B,UAAM,OAAO,MAAM,MAAM,CAAC;AAE1B,QAAI,CAAC,KAAM,QAAO;AAGlB,UAAM,SAAS,MAAM,KAAK,OAAO,EAAE,OAAO,IAAI,CAAC;AAC/C,UAAM,QAAQ,OAAO,MAAM;AAAA,MACzB,CAAC,MAAM,EAAE,WAAW,YAAY,MAAM,gBAAgB,YAAY;AAAA,IACpE;AAEA,QAAI,CAAC,MAAO,QAAO;AAGnB,UAAM,SAAS,MAAM,KAAK,OAAO;AACjC,UAAM,YAAY,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,SAAS,MAAM;AAEtF,QAAI,CAAC,UAAW,QAAO;AAGvB,UAAM,MAAM,OAAO,EAAE,SAAS,UAAU,GAAG,CAAC;AAC5C,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,eAAe,IAAY,UAA0B,CAAC,GAAkB;AAC5F,QAAM,UAAU,GAAG,WAAW,QAAQ,IAAI,KAAK,SAAS,GAAG,YAAY,CAAC;AACxE,QAAM,QAAQ,cAAc,OAAO;AAEnC,MAAI,CAAC,OAAO;AACV,YAAQ,IAAIN,QAAM,OAAO,SAAS,OAAO,aAAa,CAAC;AACvD,YAAQ,IAAIA,QAAM,IAAI,8CAA8C,CAAC;AACrE;AAAA,EACF;AAEA,QAAM,UAAUC,KAAI,mBAAmB,EAAE,MAAM;AAE/C,MAAI;AACF,UAAM,YAAY,MAAM;AACxB,QAAI,WAAW;AACf,QAAI,gBAAgB;AAGpB,QAAI,QAAQ,UAAU,OAAO;AAC3B,UAAI,CAAC,WAAW,GAAG;AACjB,gBAAQ,KAAK,sCAAsC;AACnD,gBAAQ,IAAID,QAAM,IAAI,oCAAoC,CAAC;AAAA,MAC7D,OAAO;AACL,gBAAQ,OAAO;AACf,cAAM,KAAK,gBAAgB,SAAS;AAEpC,YAAI,IAAI;AACN,kBAAQ,OAAO,eAAe,GAAG,MAAM;AACvC,gBAAM,SAAS,QAAQ,WAAW,GAAG,MAAM;AAE3C,cAAI,OAAO,SAAS;AAClB,uBAAW;AACX,oBAAQ,IAAIA,QAAM,MAAM,uBAAkB,GAAG,MAAM,EAAE,CAAC;AAAA,UACxD,OAAO;AACL,oBAAQ,IAAIA,QAAM,OAAO,6BAAwB,OAAO,KAAK,EAAE,CAAC;AAChE,oBAAQ,IAAIA,QAAM,IAAI,mCAAmC,GAAG,MAAM,WAAW,CAAC;AAAA,UAChF;AAAA,QACF,OAAO;AACL,kBAAQ,IAAIA,QAAM,IAAI,+BAA+B,CAAC;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAGA,QAAI,QAAQ,aAAa,MAAM;AAC7B,YAAM,SAAS,gBAAgB;AAC/B,UAAI,QAAQ;AACV,gBAAQ,OAAO;AACf,wBAAgB,MAAM,mBAAmB,QAAQ,MAAM,OAAO;AAC9D,YAAI,eAAe;AACjB,kBAAQ,IAAIA,QAAM,MAAM,oBAAe,MAAM,OAAO,UAAU,CAAC;AAAA,QACjE,OAAO;AACL,kBAAQ,IAAIA,QAAM,OAAO,yCAAoC,CAAC;AAAA,QAChE;AAAA,MACF,OAAO;AACL,gBAAQ,IAAIA,QAAM,IAAI,mDAAmD,CAAC;AAAA,MAC5E;AAAA,IACF;AAGA,UAAM,SAAS;AACf,UAAM,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAC5C,mBAAe,KAAK;AAGpB,UAAM,eAAeK,MAAK,YAAY,SAAS,UAAU;AACzD,IAAAF,eAAc,cAAc,KAAK,UAAU;AAAA,MACzC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,MACA;AAAA,IACF,CAAC,CAAC;AAEF,YAAQ,QAAQ,aAAa,MAAM,OAAO,EAAE;AAC5C,YAAQ,IAAI,EAAE;AAGd,YAAQ,IAAIH,QAAM,KAAK,UAAU,CAAC;AAClC,YAAQ,IAAI,cAAcA,QAAM,KAAK,MAAM,OAAO,CAAC,EAAE;AACrD,YAAQ,IAAI,cAAc,WAAWA,QAAM,MAAM,QAAQ,IAAIA,QAAM,IAAI,YAAY,CAAC,EAAE;AACtF,YAAQ,IAAI,cAAc,gBAAgBA,QAAM,MAAM,iBAAiB,IAAIA,QAAM,IAAI,aAAa,CAAC,EAAE;AACrG,YAAQ,IAAI,EAAE;AAEd,YAAQ,IAAIA,QAAM,IAAI,mCAAmC,CAAC;AAC1D,YAAQ,IAAIA,QAAM,IAAI,2BAA2B,MAAM,OAAO,EAAE,CAAC;AAAA,EAEnE,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACnMA;AAAA,OAAOO,aAAW;AAClB,OAAOC,UAAS;AAChB,OAAOC,eAAc;AACrB,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,aAAAC,kBAAiB;AACnE,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,iBAAgB;AAwCzB,SAASC,mBAAiC;AACxC,QAAM,UAAUJ,MAAKE,SAAQ,GAAG,iBAAiB;AACjD,MAAIJ,YAAW,OAAO,GAAG;AACvB,UAAM,UAAUF,cAAa,SAAS,OAAO;AAC7C,UAAM,QAAQ,QAAQ,MAAM,qBAAqB;AACjD,QAAI,MAAO,QAAO,MAAM,CAAC,EAAE,KAAK;AAAA,EAClC;AACA,SAAO,QAAQ,IAAI,kBAAkB;AACvC;AAEA,SAAS,aAAa,SAA2B;AAC/C,QAAM,QAAkB,CAAC;AACzB,QAAM,MAAM,QAAQ,IAAI;AAExB,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,eAAe,QAAQ,YAAY;AAEzC,aAAW,cAAc,aAAa;AACpC,UAAM,WAAWI,MAAK,KAAK,UAAU;AACrC,QAAI,CAACF,YAAW,QAAQ,EAAG;AAE3B,QAAI;AACF,YAAM,SAASK;AAAA,QACb,SAAS,QAAQ,0DAA0D,YAAY;AAAA,QACvF,EAAE,UAAU,QAAQ;AAAA,MACtB;AAEA,YAAM,QAAQ,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,OAAK,CAAC;AACrD,YAAM,KAAK,GAAG,KAAK;AAAA,IACrB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAC3B;AAKA,SAAS,kBAAkB,OAAoB,UAAwC;AACrF,QAAM,UAAoB,CAAC;AAC3B,QAAM,aAAuB,CAAC;AAC9B,MAAI,iBAAiB;AAErB,QAAM,QAAQ,MAAM,eAAe,IAAI,YAAY;AACnD,QAAM,QAAQ,MAAM,MAAM,YAAY;AACtC,QAAM,WAAW,GAAG,KAAK,IAAI,IAAI;AAGjC,MAAI,SAAS,SAAS,UAAU,KAAK,SAAS,SAAS,IAAI,KAAK,SAAS,SAAS,WAAW,GAAG;AAC9F,eAAW,KAAK,UAAU;AAAA,EAC5B;AACA,MAAI,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,SAAS,UAAU,GAAG;AAC7F,eAAW,KAAK,SAAS;AAAA,EAC3B;AACA,MAAI,SAAS,SAAS,UAAU,KAAK,SAAS,SAAS,WAAW,KAAK,SAAS,SAAS,QAAQ,GAAG;AAClG,eAAW,KAAK,UAAU;AAAA,EAC5B;AACA,MAAI,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,SAAS,YAAY,GAAG;AAC5F,eAAW,KAAK,OAAO;AAAA,EACzB;AAEA,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,KAAK,iCAAiC,WAAW,KAAK,IAAI,CAAC,EAAE;AACrE,sBAAkB,WAAW;AAAA,EAC/B;AAGA,QAAM,oBAAoB;AAAA,IACxB;AAAA,IAAa;AAAA,IAAS;AAAA,IAAM;AAAA,IAAY;AAAA,IAAU;AAAA,IAClD;AAAA,IAAO;AAAA,IAAoB;AAAA,IAAoB;AAAA,EACjD;AACA,aAAW,WAAW,mBAAmB;AACvC,QAAI,SAAS,SAAS,OAAO,GAAG;AAC9B,cAAQ,KAAK,+BAA+B;AAC5C;AAAA,IACF;AAAA,EACF;AAGA,QAAM,uBAAuB;AAAA,IAC3B;AAAA,IAAY;AAAA,IAAgB;AAAA,IAAY;AAAA,IAAe;AAAA,IACvD;AAAA,IAAe;AAAA,IAAkB;AAAA,IAAiB;AAAA,EACpD;AACA,aAAW,WAAW,sBAAsB;AAC1C,QAAI,SAAS,SAAS,OAAO,GAAG;AAC9B,cAAQ,KAAK,iCAAiC,OAAO,EAAE;AACvD,wBAAkB;AAClB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,SAAS,KAAK;AACrB,YAAQ,KAAK,0CAA0C;AACvD,sBAAkB;AAAA,EACpB;AAGA,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,KAAK,4CAA4C;AAAA,EAC3D;AAGA,QAAM,gBAAgB,CAAC,WAAW,SAAS,QAAQ,eAAe,cAAc;AAChF,aAAW,SAAS,MAAM,UAAU,CAAC,GAAG;AACtC,QAAI,cAAc,KAAK,QAAM,MAAM,KAAK,YAAY,EAAE,SAAS,EAAE,CAAC,GAAG;AACnE,cAAQ,KAAK,+BAA+B,MAAM,IAAI,EAAE;AACxD,wBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,UAAU,KAAK,WAAW,SAAS,KAAK,kBAAkB;AAEpF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB,KAAK,IAAI,gBAAgB,WAAW,SAAS,CAAC;AAAA,EAChE;AACF;AAKA,eAAe,kBACb,OACA,YACA,YACgE;AAChE,QAAM,YAAiC,CAAC;AACxC,QAAM,QAAoB,CAAC;AAE3B,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIV,QAAM,KAAK,KAAK,oWAA6D,CAAC;AAC1F,UAAQ,IAAIA,QAAM,KAAK,KAAK,qCAAqC,CAAC;AAClE,UAAQ,IAAIA,QAAM,KAAK,KAAK,oWAA6D,CAAC;AAC1F,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,QAAM,IAAI,uDAAuD,CAAC;AAC9E,UAAQ,IAAIA,QAAM,IAAI,yCAAyC,CAAC;AAChE,UAAQ,IAAI,EAAE;AAGd,UAAQ,IAAIA,QAAM,KAAK,QAAQ,GAAG,GAAG,MAAM,UAAU,MAAM,MAAM,KAAK,EAAE;AACxE,MAAI,WAAW,WAAW,SAAS,GAAG;AACpC,YAAQ,IAAIA,QAAM,KAAK,sBAAsB,GAAG,WAAW,WAAW,KAAK,IAAI,CAAC;AAAA,EAClF;AACA,UAAQ,IAAI,EAAE;AAGd,QAAM,cAAc,MAAME,UAAS,OAAO,CAAC;AAAA,IACzC,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,MAAM,aAAa,MAAM,GAAG,GAAG,KAAK;AAAA,EAC/C,CAAC,CAAC;AACF,MAAI,YAAY,OAAO;AACrB,cAAU,KAAK,EAAE,UAAU,SAAS,QAAQ,YAAY,MAAM,CAAC;AAAA,EACjE;AAGA,QAAM,iBAAiB,MAAMA,UAAS,OAAO,CAAC;AAAA,IAC5C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC,CAAC;AACF,MAAI,eAAe,UAAU;AAC3B,cAAU,KAAK,EAAE,UAAU,sBAAsB,QAAQ,eAAe,SAAS,CAAC;AAAA,EACpF;AAGA,QAAM,kBAAkB,MAAMA,UAAS,OAAO,CAAC;AAAA,IAC7C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC,CAAC;AACF,MAAI,gBAAgB,WAAW;AAC7B,cAAU,KAAK,EAAE,UAAU,cAAc,QAAQ,gBAAgB,UAAU,CAAC;AAAA,EAC9E;AAGA,QAAM,gBAAgB,MAAMA,UAAS,OAAO,CAAC;AAAA,IAC3C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,MAAM,cAAc,OAAO,QAAQ,SAAS,KAAK;AAAA,MACnD,EAAE,MAAM,qBAAqB,OAAO,cAAc;AAAA,MAClD,EAAE,MAAM,0BAA0B,OAAO,MAAM;AAAA,MAC/C,EAAE,MAAM,uBAAuB,OAAO,SAAS;AAAA,IACjD;AAAA,EACF,CAAC,CAAC;AACF,MAAI,cAAc,QAAQ,SAAS,GAAG;AACpC,cAAU,KAAK,EAAE,UAAU,WAAW,QAAQ,cAAc,QAAQ,KAAK,IAAI,EAAE,CAAC;AAAA,EAClF;AAGA,QAAM,mBAAmB,MAAMA,UAAS,OAAO,CAAC;AAAA,IAC9C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC,CAAC;AACF,MAAI,iBAAiB,YAAY;AAC/B,cAAU,KAAK,EAAE,UAAU,gBAAgB,QAAQ,iBAAiB,WAAW,CAAC;AAAA,EAClF;AAGA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIF,QAAM,KAAK,yBAAyB,CAAC;AACjD,UAAQ,IAAIA,QAAM,IAAI,kDAAkD,CAAC;AACzE,UAAQ,IAAI,EAAE;AAGd,QAAM,iBAA6B;AAAA,IACjC,EAAE,MAAM,2BAA2B,aAAa,uCAAuC;AAAA,EACzF;AAEA,MAAI,WAAW,WAAW,SAAS,GAAG;AACpC,mBAAe,KAAK,EAAE,MAAM,mBAAmB,aAAa,mCAAmC,WAAW,0BAA0B,CAAC;AAAA,EACvI;AAEA,aAAW,aAAa,WAAW,YAAY;AAC7C,mBAAe,KAAK;AAAA,MAClB,MAAM,aAAa,SAAS;AAAA,MAC5B,aAAa,QAAQ,SAAS;AAAA,MAC9B,WAAW,WAAW,WAAW,SAAS,IAAI,oBAAoB;AAAA,IACpE,CAAC;AAAA,EACH;AAEA,MAAI,eAAe,WAAW,GAAG;AAC/B,mBAAe,KAAK,EAAE,MAAM,qBAAqB,aAAa,uBAAuB,WAAW,0BAA0B,CAAC;AAAA,EAC7H;AAEA,MAAI,cAAc,QAAQ,SAAS,MAAM,KAAK,cAAc,QAAQ,SAAS,aAAa,GAAG;AAC3F,mBAAe,KAAK,EAAE,MAAM,aAAa,aAAa,iCAAiC,WAAW,eAAe,eAAe,SAAS,CAAC,EAAE,KAAK,CAAC;AAAA,EACpJ;AAEA,MAAI,cAAc,QAAQ,SAAS,KAAK,GAAG;AACzC,mBAAe,KAAK,EAAE,MAAM,iBAAiB,aAAa,wBAAwB,WAAW,YAAY,CAAC;AAAA,EAC5G;AAEA,iBAAe,KAAK,EAAE,MAAM,sBAAsB,aAAa,kCAAkC,WAAW,eAAe,eAAe,SAAS,CAAC,EAAE,KAAK,CAAC;AAG5J,UAAQ,IAAIA,QAAM,KAAK,kBAAkB,CAAC;AAC1C,WAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,UAAM,OAAO,eAAe,CAAC;AAC7B,YAAQ,IAAI,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,GAAG,KAAK,YAAYA,QAAM,IAAI,YAAY,KAAK,SAAS,GAAG,IAAI,EAAE,EAAE;AAAA,EACzG;AACA,UAAQ,IAAI,EAAE;AAEd,QAAM,mBAAmB,MAAME,UAAS,OAAO,CAAC;AAAA,IAC9C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC,CAAC;AAEF,MAAI,iBAAiB,YAAY;AAC/B,UAAM,KAAK,GAAG,cAAc;AAAA,EAC9B,OAAO;AAEL,QAAI,YAAY;AAChB,QAAI,eAAe;AAEnB,WAAO,MAAM;AACX,YAAM,aAAa,MAAMA,UAAS,OAAO,CAAC;AAAA,QACxC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ,SAAS;AAAA,MAC5B,CAAC,CAAC;AAEF,UAAI,CAAC,WAAW,KAAM;AAEtB,YAAM,aAAa,MAAMA,UAAS,OAAO,CAAC;AAAA,QACxC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ,SAAS;AAAA,QAC1B,SAAS,WAAW;AAAA,MACtB,CAAC,CAAC;AAEF,YAAM,KAAK;AAAA,QACT,MAAM,WAAW;AAAA,QACjB,aAAa,WAAW;AAAA,QACxB,WAAW,gBAAgB;AAAA,MAC7B,CAAC;AAED,qBAAe,WAAW;AAC1B;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,UAAU;AAC5B;AAKA,SAAS,kBACP,OACA,WACA,OACQ;AACR,QAAM,QAAkB;AAAA,IACtB,kBAAkB,MAAM,UAAU;AAAA,IAClC;AAAA,IACA,sBAAqB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,IAC7C;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB,MAAM,UAAU;AAAA,IAChC,gBAAgB,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA,iBAAiB,MAAM,GAAG;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,UAAU,SAAS,GAAG;AACxB,eAAW,YAAY,WAAW;AAChC,YAAM,KAAK,OAAO,SAAS,QAAQ,OAAO,SAAS,MAAM,EAAE;AAAA,IAC7D;AAAA,EACF,OAAO;AACL,UAAM,KAAK,kCAAkC;AAAA,EAC/C;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,kBAAkB;AAC7B,QAAM,KAAK,EAAE;AAEb,aAAW,QAAQ,OAAO;AACxB,UAAM,KAAK,SAAS,KAAK,IAAI,GAAG,KAAK,YAAY,YAAY,KAAK,SAAS,MAAM,EAAE,EAAE;AAAA,EACvF;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,sBAAsB;AACjC,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,mCAAmC;AAC9C,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,UAAU;AACrB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,uCAAuC;AAClD,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,SAAS,sBAAsB,OAAoB,UAA4B;AAC7E,QAAM,QAAkB;AAAA,IACtB,gBAAgB,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,KAAK,MAAM,KAAK;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,MAAM,GAAG;AAAA,EAC/B;AAEA,aAAW,OAAO,UAAU;AAC1B,UAAM,eAAe,IAAI,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE;AACxD,UAAM,KAAK,WAAW,YAAY,GAAG;AAAA,EACvC;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,kBAAkB;AAC7B,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,+CAA+C;AAC1D,QAAM,KAAK,8BAA8B;AACzC,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,UAAU;AACrB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,4BAA4B;AACvC,QAAM,KAAK,SAAS;AACpB,QAAM,KAAK,kCAAkC;AAC7C,QAAM,KAAK,iBAAiB,MAAM,UAAU,8BAA8B;AAC1E,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,uBAAuB;AAClC,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oCAAoC;AAC/C,QAAM,KAAK,gDAAgD;AAC3D,QAAM,KAAK,0DAA0D;AACrE,QAAM,KAAK,kCAAkC;AAC7C,QAAM,KAAK,oCAAoC;AAC/C,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,2CAA2C;AACtD,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,mDAAmD;AAC9D,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,6CAA6C;AACxD,QAAM,KAAK,uEAAuE;AAClF,QAAM,KAAK,sCAAsC;AACjD,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,yCAAyC;AACpD,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,SAAS,iBAAiB,OAAoB,OAA8E;AAC1H,QAAM,UAAoB,CAAC;AAC3B,QAAM,SAAmB,CAAC;AAC1B,QAAM,UAA+B,oBAAI,IAAI;AAG7C,MAAI;AACF,IAAAQ,UAAS,YAAY,EAAE,UAAU,QAAQ,CAAC;AAAA,EAC5C,QAAQ;AACN,WAAO,EAAE,SAAS,OAAO,SAAS,CAAC,GAAG,QAAQ,CAAC,kCAAkC,EAAE;AAAA,EACrF;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,GAAG,MAAM,UAAU,KAAK,KAAK,IAAI;AAElD,QAAI;AAGF,YAAM,cAAc,SAAS,QAAQ,MAAM,KAAK;AAChD,UAAI,MAAM,cAAc,WAAW,qBAAqB,MAAM,UAAU;AAGxE,UAAI,KAAK,WAAW;AAClB,cAAM,UAAU,GAAG,MAAM,UAAU,KAAK,KAAK,SAAS;AACtD,cAAM,QAAQ,QAAQ,IAAI,OAAO;AACjC,YAAI,OAAO;AACT,iBAAO,mBAAmB,KAAK;AAAA,QACjC;AAAA,MACF;AAGA,UAAI,KAAK,aAAa;AACpB,cAAM,cAAc,KAAK,YAAY,QAAQ,MAAM,KAAK;AACxD,eAAO,QAAQ,WAAW;AAAA,MAC5B;AAEA,YAAM,SAASA,UAAS,KAAK,EAAE,UAAU,SAAS,KAAK,QAAQ,IAAI,EAAE,CAAC;AAGtE,YAAM,UAAU,OAAO,MAAM,eAAe,KAAK,OAAO,MAAM,kBAAkB;AAChF,UAAI,SAAS;AACX,gBAAQ,IAAI,UAAU,QAAQ,CAAC,CAAC;AAAA,MAClC;AAEA,cAAQ,KAAK,QAAQ;AAAA,IACvB,SAAS,OAAY;AAEnB,YAAM,SAAS,MAAM,QAAQ,SAAS,KAAK,MAAM;AACjD,aAAO,KAAK,qBAAqB,KAAK,IAAI,MAAM,OAAO,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE;AAAA,IACzE;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,QAAI;AACF,MAAAA,UAAS,YAAY,EAAE,UAAU,SAAS,KAAK,QAAQ,IAAI,EAAE,CAAC;AAAA,IAChE,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,SAAS,OAAO;AACzD;AAKA,SAAS,mBAAmB,OAAoB,cAAqC;AACnF,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAASH,MAAK,KAAK,QAAQ,QAAQ,QAAQ;AAEjD,MAAI;AACF,IAAAD,WAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAErC,UAAM,WAAW,GAAG,MAAM,WAAW,YAAY,CAAC;AAClD,UAAM,UAAUC,MAAK,QAAQ,QAAQ;AAErC,IAAAH,eAAc,SAAS,YAAY;AAEnC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,YAAY,IAAY,UAAuB,CAAC,GAAkB;AACtF,QAAM,UAAUH,KAAI,+BAA+B,EAAE,KAAK,EAAE,MAAM;AAElE,MAAI;AACF,UAAM,SAASU,iBAAgB;AAC/B,QAAI,CAAC,QAAQ;AACX,cAAQ,KAAK,0BAA0B;AACvC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIX,QAAM,IAAI,8BAA8B,CAAC;AACrD,cAAQ,IAAI,gCAAgC;AAC5C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,YAAQ,OAAO;AACf,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,aAAa;AACnD,UAAM,SAAS,IAAI,aAAa,EAAE,OAAO,CAAC;AAE1C,UAAM,KAAK,MAAM,OAAO;AACxB,UAAM,QAAQ,MAAM,GAAG,MAAM;AAC7B,UAAM,OAAO,MAAM,MAAM,CAAC;AAE1B,QAAI,CAAC,MAAM;AACT,cAAQ,KAAK,sBAAsB;AACnC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,eAAe,MAAM,KAAK,OAAO,EAAE,OAAO,IAAI,CAAC;AACrD,UAAM,QAAQ,aAAa,MAAM;AAAA,MAC/B,CAAC,MAAM,EAAE,WAAW,YAAY,MAAM,GAAG,YAAY;AAAA,IACvD;AAEA,QAAI,CAAC,OAAO;AACV,cAAQ,KAAK,oBAAoB,EAAE,EAAE;AACrC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,QAAQ,MAAM,MAAM;AAC1B,UAAM,WAAW,MAAM,MAAM;AAC7B,UAAMY,WAAU,MAAM,MAAM;AAC5B,UAAM,SAAS,MAAM,MAAM,OAAO;AAElC,UAAM,YAAyB;AAAA,MAC7B,IAAI,MAAM;AAAA,MACV,YAAY,MAAM;AAAA,MAClB,OAAO,MAAM;AAAA,MACb,aAAa,MAAM,eAAe;AAAA,MAClC,OAAO,EAAE,MAAM,OAAO,QAAQ,UAAU;AAAA,MACxC,UAAU,MAAM;AAAA,MAChB,KAAK,MAAM;AAAA,MACX,QAAQ,OAAO,MAAM,IAAI,QAAM,EAAE,MAAM,EAAE,KAAK,EAAE;AAAA,MAChD,UAAU,WAAW,EAAE,MAAM,SAAS,KAAK,IAAI;AAAA,MAC/C,SAASA,WAAU,EAAE,MAAMA,SAAQ,KAAK,IAAI;AAAA,IAC9C;AAGA,YAAQ,OAAO;AACf,UAAM,WAAW,aAAa,EAAE;AAGhC,YAAQ,OAAO;AACf,UAAM,aAAa,kBAAkB,WAAW,QAAQ;AAExD,YAAQ,KAAK;AAGb,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIZ,QAAM,KAAK,oWAA6D,CAAC;AACrF,YAAQ,IAAIA,QAAM,KAAK,KAAK,UAAU,UAAU,KAAK,UAAU,KAAK,EAAE,CAAC;AACvE,YAAQ,IAAIA,QAAM,KAAK,oWAA6D,CAAC;AACrF,YAAQ,IAAI,EAAE;AAEd,YAAQ,IAAIA,QAAM,KAAK,sBAAsB,CAAC;AAC9C,YAAQ,IAAI,YAAY,WAAW,YAAYA,QAAM,OAAO,SAAS,IAAIA,QAAM,MAAM,QAAQ,CAAC,EAAE;AAChG,YAAQ,IAAI,sBAAsB,WAAW,cAAc,EAAE;AAC7D,QAAI,WAAW,WAAW,SAAS,GAAG;AACpC,cAAQ,IAAI,iBAAiB,WAAW,WAAW,KAAK,IAAI,CAAC,EAAE;AAAA,IACjE;AACA,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,cAAQ,IAAI,YAAY;AACxB,iBAAW,UAAU,WAAW,SAAS;AACvC,gBAAQ,IAAI,SAAS,MAAM,EAAE;AAAA,MAC/B;AAAA,IACF;AACA,YAAQ,IAAI,EAAE;AAEd,QAAI,SAAS,SAAS,GAAG;AACvB,cAAQ,IAAIA,QAAM,KAAK,qBAAqB,CAAC;AAC7C,iBAAW,OAAO,UAAU;AAC1B,gBAAQ,IAAI,OAAO,IAAI,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE,CAAC,EAAE;AAAA,MAC3D;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,CAAC,WAAW,aAAa,CAAC,QAAQ,OAAO;AAC3C,YAAM,aAAa,MAAME,UAAS,OAAO,CAAC;AAAA,QACxC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC,CAAC;AAEF,UAAI,WAAW,MAAM;AACnB,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAIF,QAAM,KAAK,uBAAuB,EAAE,EAAE,CAAC;AACnD,gBAAQ,IAAI,EAAE;AACd;AAAA,MACF;AAAA,IACF;AAGA,QAAI;AACJ,QAAI;AAEJ,QAAI,QAAQ,eAAe;AAEzB,cAAQ;AAAA,QACN,EAAE,MAAM,2BAA2B,aAAa,iCAAiC;AAAA,QACjF,EAAE,MAAM,qBAAqB,aAAa,uBAAuB,WAAW,0BAA0B;AAAA,QACtG,EAAE,MAAM,aAAa,aAAa,0BAA0B,WAAW,oBAAoB;AAAA,QAC3F,EAAE,MAAM,sBAAsB,aAAa,kCAAkC,WAAW,YAAY;AAAA,MACtG;AACA,kBAAY,CAAC;AAAA,IACf,OAAO;AACL,YAAM,YAAY,MAAM,kBAAkB,WAAW,UAAU;AAC/D,cAAQ,UAAU;AAClB,kBAAY,UAAU;AAAA,IACxB;AAGA,UAAM,gBAAgBC,KAAI,2BAA2B,EAAE,MAAM;AAE7D,UAAM,eAAe,kBAAkB,WAAW,WAAW,KAAK;AAClE,UAAM,mBAAmB,sBAAsB,WAAW,QAAQ;AAGlE,UAAM,YAAY,QAAQ,SAASO,SAAQ,QAAQ,MAAM,IAAI,QAAQ,IAAI;AACzE,UAAM,cAAcD,MAAK,WAAW,WAAW;AAC/C,IAAAD,WAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAG1C,UAAM,YAAYC,MAAK,aAAa,UAAU;AAC9C,IAAAH,eAAc,WAAW,YAAY;AAGrC,UAAM,gBAAgBG,MAAK,aAAa,cAAc;AACtD,IAAAH,eAAc,eAAe,gBAAgB;AAE7C,kBAAc,QAAQ,uBAAuB;AAG7C,UAAM,eAAeH,KAAI,yBAAyB,EAAE,MAAM;AAC1D,UAAM,cAAc,iBAAiB,WAAW,KAAK;AAErD,QAAI,YAAY,SAAS;AACvB,mBAAa,QAAQ,WAAW,YAAY,QAAQ,MAAM,cAAc;AAAA,IAC1E,OAAO;AACL,mBAAa,KAAK,WAAW,YAAY,QAAQ,MAAM,oBAAoB;AAC3E,iBAAW,SAAS,YAAY,QAAQ;AACtC,gBAAQ,IAAID,QAAM,IAAI,OAAO,KAAK,EAAE,CAAC;AAAA,MACvC;AAAA,IACF;AAGA,UAAM,UAAU,mBAAmB,WAAW,YAAY;AAC1D,QAAI,SAAS;AACX,cAAQ,IAAIA,QAAM,IAAI,mBAAmB,QAAQ,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE,CAAC,EAAE,CAAC;AAAA,IACtF;AAGA,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU;AAAA,QACzB,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,UACL,OAAO;AAAA,UACP,WAAW;AAAA,UACX,KAAK;AAAA,QACP;AAAA,QACA,OAAO;AAAA,MACT,GAAG,MAAM,CAAC,CAAC;AACX;AAAA,IACF;AAGA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,QAAM,KAAK,MAAM,oWAA6D,CAAC;AAC3F,YAAQ,IAAIA,QAAM,KAAK,MAAM,mCAAmC,CAAC;AACjE,YAAQ,IAAIA,QAAM,KAAK,MAAM,oWAA6D,CAAC;AAC3F,YAAQ,IAAI,EAAE;AAEd,YAAQ,IAAIA,QAAM,KAAK,gBAAgB,CAAC;AACxC,YAAQ,IAAI,KAAKA,QAAM,KAAK,UAAU,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,EAAE;AACzE,YAAQ,IAAI,KAAKA,QAAM,KAAK,cAAc,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,EAAE;AAC7E,YAAQ,IAAI,EAAE;AAEd,YAAQ,IAAIA,QAAM,KAAK,cAAc,CAAC;AACtC,eAAW,QAAQ,OAAO;AACxB,cAAQ,IAAI,KAAKA,QAAM,IAAI,QAAG,CAAC,IAAI,UAAU,UAAU,KAAK,KAAK,IAAI,EAAE;AAAA,IACzE;AACA,YAAQ,IAAI,EAAE;AAEd,QAAI,UAAU,SAAS,GAAG;AACxB,cAAQ,IAAIA,QAAM,KAAK,qBAAqB,CAAC;AAC7C,iBAAW,YAAY,WAAW;AAChC,gBAAQ,IAAI,OAAO,SAAS,QAAQ,KAAKA,QAAM,IAAI,SAAS,OAAO,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,SAAS,OAAO,SAAS,KAAK,QAAQ,EAAE,EAAE;AAAA,MAC/H;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,YAAQ,IAAIA,QAAM,KAAK,aAAa,CAAC;AACrC,YAAQ,IAAI,eAAeA,QAAM,KAAK,oBAAoB,CAAC,EAAE;AAC7D,YAAQ,IAAI,YAAYA,QAAM,KAAK,kBAAkB,EAAE,EAAE,CAAC,iBAAiB;AAC3E,YAAQ,IAAI,uBAAuBA,QAAM,KAAK,UAAU,CAAC,eAAe;AACxE,YAAQ,IAAI,EAAE;AAAA,EAEhB,SAAS,OAAY;AACnB,YAAQ,MAAMA,QAAM,IAAI,UAAU,MAAM,OAAO,EAAE,CAAC;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACjwBA;AAMA,OAAOa,aAAW;AAClB,OAAOC,UAAS;AAahB,IAAM,kBAA0C;AAAA,EAC9C,GAAGC,QAAM,IAAI,MAAM;AAAA,EACnB,GAAGA,QAAM,IAAI,QAAQ;AAAA,EACrB,GAAGA,QAAM,OAAO,MAAM;AAAA,EACtB,GAAGA,QAAM,KAAK,QAAQ;AAAA,EACtB,GAAGA,QAAM,IAAI,KAAK;AACpB;AAEA,IAAM,eAAsD;AAAA,EAC1D,QAAQA,QAAM;AAAA,EACd,eAAeA,QAAM;AAAA,EACrB,UAAUA,QAAM;AAClB;AAKA,SAAS,iBAAiB,aAAgD;AACxE,QAAM,SAAS,WAAW;AAC1B,QAAM,gBAAgB,OAAO,SAAS,WAAW;AAEjD,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAY,cAAsB;AAAA,IAClC,MAAO,cAAsB;AAAA,IAC7B,UAAW,cAAsB;AAAA,IACjC,OAAQ,cAAsB;AAAA,IAC9B,MAAO,cAAsB;AAAA,IAC7B,WAAY,cAAsB;AAAA,IAClC,QAAS,cAAsB;AAAA,IAC/B,WAAY,cAAsB;AAAA,IAClC,SAAU,cAAsB;AAAA,EAClC;AACF;AAKA,SAAS,wBAAuC;AAC9C,QAAM,SAAS,WAAW;AAC1B,QAAM,WAA0B,CAAC;AAEjC,MAAI,OAAO,SAAS,OAAQ,UAAS,KAAK,QAAQ;AAClD,MAAI,OAAO,SAAS,OAAQ,UAAS,KAAK,QAAQ;AAClD,MAAI,OAAO,SAAS,OAAQ,UAAS,KAAK,QAAQ;AAClD,MAAI,OAAO,SAAS,MAAO,UAAS,KAAK,OAAO;AAEhD,SAAO;AACT;AAKA,SAAS,cAAc,QAAiB,aAA2B;AACjE,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAIA,QAAM,IAAI,wBAAwB,WAAW,EAAE,CAAC;AAC5D;AAAA,EACF;AAGA,QAAM,UAAmC,CAAC;AAC1C,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,QAAQ,MAAM,KAAK,EAAG,SAAQ,MAAM,KAAK,IAAI,CAAC;AACnD,YAAQ,MAAM,KAAK,EAAE,KAAK,KAAK;AAAA,EACjC;AAGA,QAAM,aAAa,CAAC,eAAe,QAAQ,QAAQ;AAEnD,aAAW,SAAS,YAAY;AAC9B,UAAM,cAAc,QAAQ,KAAK;AACjC,QAAI,CAAC,eAAe,YAAY,WAAW,EAAG;AAE9C,UAAM,UAAU,aAAa,KAAK,KAAKA,QAAM;AAC7C,UAAM,eAAe,MAAM,QAAQ,KAAK,GAAG,EAAE,QAAQ,SAAS,OAAK,EAAE,YAAY,CAAC;AAClF,YAAQ,IAAI,QAAQ,kBAAQ,YAAY,KAAK,YAAY,MAAM,gBAAM,CAAC;AAEtE,eAAW,SAAS,aAAa;AAC/B,YAAM,gBAAgB,MAAM,WAAW,gBAAgB,MAAM,QAAQ,KAAK,KAAK;AAC/E,YAAM,cAAc,MAAM,WAAWA,QAAM,IAAI,KAAK,MAAM,SAAS,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI;AACtF,YAAM,cAAc,MAAM,YAAY,MAAM,WAAW,IAAI,IAAI,aAAa,KAAK;AAEjF,cAAQ,IAAI,OAAOA,QAAM,KAAK,MAAM,GAAG,CAAC,IAAI,MAAM,KAAK,GAAG,WAAW,GAAG,WAAW,EAAE;AAAA,IACvF;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AACF;AAEA,eAAsB,YAAY,SAAqC;AACrE,QAAM,UAAUC,KAAI,oBAAoB,EAAE,MAAM;AAEhD,MAAI;AACF,UAAM,SAAS,WAAW;AAC1B,UAAM,kBAAiC,CAAC;AAGxC,QAAI,QAAQ,SAAS;AAEnB,YAAM,cAAc,QAAQ;AAC5B,UAAI,CAAC,CAAC,UAAU,UAAU,UAAU,OAAO,EAAE,SAAS,WAAW,GAAG;AAClE,gBAAQ,KAAK,oBAAoB,QAAQ,OAAO,EAAE;AAClD,gBAAQ,IAAID,QAAM,IAAI,+CAA+C,CAAC;AACtE,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,sBAAgB,KAAK,WAAW;AAAA,IAClC,WAAW,QAAQ,aAAa;AAE9B,sBAAgB,KAAK,GAAG,sBAAsB,CAAC;AAAA,IACjD,OAAO;AAEL,sBAAgB,KAAK,OAAO,SAAS,OAAO;AAAA,IAC9C;AAEA,QAAI,gBAAgB,WAAW,GAAG;AAChC,cAAQ,KAAK,wBAAwB;AACrC,cAAQ,IAAIA,QAAM,IAAI,iDAAiD,CAAC;AACxE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,YAAyD,CAAC;AAEhE,eAAW,eAAe,iBAAiB;AACzC,cAAQ,OAAO,iBAAiB,WAAW;AAE3C,YAAM,gBAAgB,iBAAiB,WAAW;AAClD,UAAI,CAAC,eAAe;AAClB,gBAAQ,IAAIA,QAAM,OAAO;AAAA,WAAc,WAAW,2BAA2B,CAAC;AAC9E;AAAA,MACF;AAEA,UAAI;AACF,cAAM,UAAU,cAAc,aAAa;AAC3C,cAAM,SAAS,MAAM,QAAQ,WAAW;AAAA,UACtC,eAAe,QAAQ;AAAA,UACvB,UAAU,QAAQ,OAAO,OAAO;AAAA,QAClC,CAAC;AACD,kBAAU,KAAK,EAAE,SAAS,aAAa,OAAO,CAAC;AAAA,MACjD,SAAS,OAAY;AACnB,gBAAQ,IAAIA,QAAM,OAAO;AAAA,gCAAmC,WAAW,KAAK,MAAM,OAAO,EAAE,CAAC;AAAA,MAC9F;AAAA,IACF;AAEA,YAAQ,KAAK;AAGb,QAAI,QAAQ,MAAM;AAChB,YAAM,SAAS,UAAU;AAAA,QAAQ,CAAC,EAAE,SAAS,OAAO,MAClD,OAAO,IAAI,YAAU,EAAE,GAAG,OAAO,QAAQ,QAAQ,EAAE;AAAA,MACrD;AACA,cAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,IACF;AAGA,UAAM,cAAc,UAAU,OAAO,CAAC,KAAK,EAAE,OAAO,MAAM,MAAM,OAAO,QAAQ,CAAC;AAEhF,QAAI,gBAAgB,GAAG;AACrB,cAAQ,IAAIA,QAAM,IAAI,oBAAoB,CAAC;AAC3C;AAAA,IACF;AAEA,eAAW,EAAE,SAAS,OAAO,KAAK,WAAW;AAC3C,cAAQ,IAAIA,QAAM,KAAK;AAAA,EAAK,QAAQ,YAAY,CAAC,KAAK,OAAO,MAAM;AAAA,CAAY,CAAC;AAChF,oBAAc,QAAQ,OAAO;AAAA,IAC/B;AAGA,UAAM,eAAe,gBAAgB,KAAK,IAAI;AAC9C,YAAQ,IAAIA,QAAM,IAAI,WAAW,WAAW,gBAAgB,YAAY,GAAG,CAAC;AAC5E,QAAI,CAAC,QAAQ,KAAK;AAChB,cAAQ,IAAIA,QAAM,IAAI,qCAAqC,CAAC;AAAA,IAC9D;AACA,QAAI,CAAC,QAAQ,eAAe,gBAAgB,WAAW,GAAG;AACxD,cAAQ,IAAIA,QAAM,IAAI,sDAAsD,CAAC;AAAA,IAC/E;AAAA,EAEF,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AC7MA;AAMA,OAAOE,aAAW;AAClB,OAAOC,UAAS;AAChB,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,cAAY,aAAAC,kBAAiB;AACnE,SAAS,QAAAC,cAAY;AACrB,SAAS,WAAAC,gBAAe;AAkBxB,SAASC,kBAAiB,aAAgD;AACxE,QAAM,SAAS,WAAW;AAC1B,QAAM,gBAAgB,OAAO,SAAS,WAAW;AAEjD,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAY,cAAsB;AAAA,IAClC,MAAO,cAAsB;AAAA,IAC7B,UAAW,cAAsB;AAAA,IACjC,OAAQ,cAAsB;AAAA,IAC9B,MAAO,cAAsB;AAAA,IAC7B,WAAY,cAAsB;AAAA,EACpC;AACF;AAEA,SAAS,qBAA6B;AACpC,SAAOC,OAAKC,SAAQ,GAAG,eAAe,mBAAmB;AAC3D;AAEA,SAAS,kBAA+B;AACtC,QAAM,OAAO,mBAAmB;AAChC,MAAIC,aAAW,IAAI,GAAG;AACpB,QAAI;AACF,aAAO,KAAK,MAAMC,cAAa,MAAM,OAAO,CAAC;AAAA,IAC/C,QAAQ;AACN,aAAO,EAAE,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAAA,IACtC;AAAA,EACF;AACA,SAAO,EAAE,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AACtC;AAEA,SAAS,gBAAgB,OAA0B;AACjD,QAAM,MAAMH,OAAKC,SAAQ,GAAG,aAAa;AACzC,MAAI,CAACC,aAAW,GAAG,GAAG;AACpB,IAAAE,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACpC;AACA,QAAM,OAAO,mBAAmB;AAChC,EAAAC,eAAc,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AACpD;AAEA,eAAsB,cAAc,IAAa,UAAyB,CAAC,GAAkB;AAC3F,QAAM,UAAUC,KAAI,yBAAyB,EAAE,MAAM;AAErD,MAAI;AACF,UAAM,SAAS,WAAW;AAC1B,UAAM,cAAc,OAAO,SAAS;AACpC,UAAM,gBAAgB,OAAO,SAAS;AAGtC,QAAI,CAAC,eAAe;AAClB,cAAQ,KAAK,iCAAiC;AAC9C,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIC,QAAM,KAAK,qBAAqB,CAAC;AAC7C,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,qDAAqD;AACjE,cAAQ,IAAIA,QAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAU3B,CAAC;AACI;AAAA,IACF;AAEA,UAAM,gBAAgBR,kBAAiB,WAAW;AAClD,UAAM,kBAAkBA,kBAAiB,aAAa;AAEtD,QAAI,CAAC,eAAe;AAClB,cAAQ,KAAK,oBAAoB,WAAW,kBAAkB;AAC9D;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB;AACpB,cAAQ,KAAK,sBAAsB,aAAa,kBAAkB;AAClE;AAAA,IACF;AAEA,UAAM,cAAc,gBAAgB;AAGpC,QAAI,IAAI;AAEN,YAAM,WAAW,GAAG,WAAW,GAAG,IAAI,KAAK,IAAI,EAAE;AAEjD,UAAI,QAAQ,SAAS;AACnB,YAAI,CAAC,YAAY,UAAU,SAAS,QAAQ,GAAG;AAC7C,sBAAY,UAAU,KAAK,QAAQ;AACnC,0BAAgB,WAAW;AAAA,QAC7B;AACA,gBAAQ,QAAQ,aAAa,QAAQ,KAAK,QAAQ,OAAO,EAAE;AAC3D;AAAA,MACF;AAEA,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,OAAO,YAAY,aAAa,UAAU,QAAQ;AAE1D,YAAIS;AACJ,YAAI;AACF,UAAAA,oBAAmB,cAAc,eAAe;AAAA,QAClD,SAAS,OAAY;AACnB,kBAAQ,KAAK,wBAAwB,aAAa,KAAK,MAAM,OAAO,EAAE;AACtE;AAAA,QACF;AAEA,YAAI;AACJ,YAAI;AACF,wBAAc,MAAMA,kBAAiB,SAAS,EAAE;AAAA,QAClD,SAAS,OAAY;AACnB,kBAAQ,KAAK,SAAS,QAAQ,iBAAiB,aAAa,EAAE;AAC9D;AAAA,QACF;AAEA,gBAAQ,OAAO,YAAY,WAAW;AAEtC,YAAI;AACJ,YAAI;AACF,2BAAiB,cAAc,aAAa;AAAA,QAC9C,SAAS,OAAY;AACnB,kBAAQ,KAAK,wBAAwB,WAAW,KAAK,MAAM,OAAO,EAAE;AACpE;AAAA,QACF;AAGA,cAAM,WAAW,MAAM,eAAe,YAAY;AAAA,UAChD,OAAO,YAAY;AAAA,UACnB,aAAa,GAAG,YAAY,WAAW;AAAA;AAAA;AAAA;AAAA,SAAqB,aAAa,OAAO,YAAY,GAAG;AAAA,UAC/F,MAAM,cAAc;AAAA,QACtB,CAAC;AAGD,YAAI;AACF,gBAAMA,kBAAiB;AAAA,YACrB;AAAA,YACA,sBAAsB,SAAS,GAAG,KAAK,WAAW;AAAA,UACpD;AAAA,QACF,QAAQ;AAEN,kBAAQ,IAAID,QAAM,OAAO,oDAAoD,CAAC;AAAA,QAChF;AAEA,oBAAY,QAAQ,YAAY,GAAG,IAAI,SAAS;AAChD,wBAAgB,WAAW;AAE3B,gBAAQ,QAAQ,WAAW,SAAS,GAAG,SAAS,YAAY,GAAG,EAAE;AACjE,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAI,KAAK,aAAa,KAAKA,QAAM,IAAI,YAAY,GAAG,CAAC,EAAE;AAC/D,gBAAQ,IAAI,KAAK,WAAW,KAAKA,QAAM,KAAK,SAAS,GAAG,CAAC,EAAE;AAC3D;AAAA,MACF;AAAA,IACF;AAGA,YAAQ,OAAO,YAAY,aAAa;AAExC,QAAI;AACJ,QAAI;AACF,yBAAmB,cAAc,eAAe;AAAA,IAClD,SAAS,OAAY;AACnB,cAAQ,KAAK,wBAAwB,aAAa,KAAK,MAAM,OAAO,EAAE;AACtE;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,iBAAiB,WAAW,EAAE,eAAe,MAAM,CAAC;AAGzE,UAAM,UAAU,OAAO;AAAA,MACrB,CAAC,MAAM,CAAC,YAAY,UAAU,SAAS,EAAE,GAAG,KAAK,CAAC,YAAY,QAAQ,EAAE,GAAG;AAAA,IAC7E;AAEA,YAAQ,KAAK;AAEb,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,IAAIA,QAAM,MAAM,2BAA2B,CAAC;AACpD,cAAQ,IAAIA,QAAM,IAAI,GAAG,OAAO,MAAM,gBAAgB,YAAY,UAAU,MAAM,eAAe,OAAO,KAAK,YAAY,OAAO,EAAE,MAAM,UAAU,CAAC;AACnJ;AAAA,IACF;AAEA,YAAQ,IAAIA,QAAM,KAAK;AAAA,EAAK,cAAc,YAAY,CAAC,2BAA2B,QAAQ,MAAM;AAAA,CAAK,CAAC;AAEtG,eAAW,SAAS,SAAS;AAC3B,YAAM,SAAS,MAAM,OAAO,IAAI,CAAC,MAAMA,QAAM,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG;AACpE,cAAQ,IAAI,KAAKA,QAAM,KAAK,MAAM,GAAG,CAAC,IAAI,MAAM,KAAK,IAAI,MAAM,EAAE;AACjE,cAAQ,IAAI,OAAOA,QAAM,IAAI,MAAM,GAAG,CAAC,EAAE;AAAA,IAC3C;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,QAAM,KAAK,WAAW,CAAC;AACnC,YAAQ,IAAI,KAAKA,QAAM,IAAI,UAAU,WAAW,SAAS,CAAC,gCAAgC;AAC1F,YAAQ,IAAI,KAAKA,QAAM,IAAI,qBAAqB,CAAC,2CAA2C;AAC5F,YAAQ,IAAI,EAAE;AAAA,EAEhB,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACxOA;AACA;AADA,OAAOE,aAAW;AAelB,eAAsB,YACpB,QACA,aACA,UAAuB,CAAC,GACT;AAEf,QAAM,UAAU,QAAQ,IAAI,uBAAuB;AAEnD,UAAQ,QAAQ;AAAA,IACd,KAAK,SAAS;AACZ,YAAM,SAAS,UAAU,eAAe,OAAO;AAE/C,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,MACF;AAEA,UAAI,CAAC,OAAO,SAAS;AACnB,gBAAQ,IAAIA,QAAM,MAAM,gCAA2B,CAAC;AACpD;AAAA,MACF;AAEA,cAAQ,IAAIA,QAAM,OAAO,UAAK,OAAO,MAAM,MAAM,kBAAkB,CAAC;AACpE,UAAI,OAAO,cAAc,GAAG;AAC1B,gBAAQ,IAAIA,QAAM,IAAI,KAAK,OAAO,WAAW,SAAS,CAAC;AAAA,MACzD;AACA,cAAQ,IAAI,EAAE;AAEd,iBAAW,QAAQ,OAAO,OAAO;AAC/B,cAAM,gBAAgB;AAAA,UACpB,QAAQA,QAAM;AAAA,UACd,MAAMA,QAAM;AAAA,UACZ,QAAQA,QAAM;AAAA,UACd,KAAKA,QAAM;AAAA,QACb,EAAE,KAAK,QAAQ;AAEf,gBAAQ,IAAI,GAAG,cAAc,IAAI,KAAK,SAAS,YAAY,CAAC,GAAG,CAAC,IAAI,KAAK,EAAE,EAAE;AAC7E,gBAAQ,IAAI,WAAW,KAAK,IAAI,EAAE;AAClC,gBAAQ,IAAI,WAAW,KAAK,MAAM,EAAE;AACpC,YAAI,KAAK,QAAQ,SAAS;AACxB,kBAAQ,IAAI,cAAc,KAAK,QAAQ,OAAO,EAAE;AAAA,QAClD;AACA,gBAAQ,IAAI,EAAE;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,UAAI,CAAC,aAAa;AAChB,gBAAQ,IAAIA,QAAM,IAAI,gDAAgD,CAAC;AACvE,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,CAAC,aAAa,GAAG,YAAY,IAAI,YAAY,MAAM,GAAG;AAC5D,YAAM,UAAU,aAAa,KAAK,GAAG;AAErC,UAAI,CAAC,SAAS;AACZ,gBAAQ,IAAIA,QAAM,IAAI,kBAAkB,CAAC;AACzC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,OAAO,WAAW,YAAY,WAAW,QAAQ,IAAI,cAAc,SAAS,WAAW,IAAI;AAAA,QAC/F,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,EAAE,QAAQ;AAAA,MACrB,CAAC;AAED,cAAQ,IAAIA,QAAM,MAAM,0BAAqB,KAAK,EAAE,EAAE,CAAC;AACvD;AAAA,IACF;AAAA,IAEA,KAAK,OAAO;AACV,UAAI,CAAC,aAAa;AAChB,gBAAQ,IAAIA,QAAM,IAAI,oCAAoC,CAAC;AAC3D,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,UAAU,YAAY,SAAS,WAAW;AAChD,UAAI,SAAS;AACX,gBAAQ,IAAIA,QAAM,MAAM,kBAAa,WAAW,EAAE,CAAC;AAAA,MACrD,OAAO;AACL,gBAAQ,IAAIA,QAAM,OAAO,mBAAmB,WAAW,EAAE,CAAC;AAAA,MAC5D;AACA;AAAA,IACF;AAAA,IAEA,KAAK,SAAS;AACZ,gBAAU,eAAe,OAAO;AAChC,cAAQ,IAAIA,QAAM,MAAM,qBAAgB,CAAC;AACzC;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,UAAI,CAAC,aAAa;AAChB,gBAAQ,IAAIA,QAAM,IAAI,gDAAgD,CAAC;AACvE,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,CAAC,aAAa,GAAG,YAAY,IAAI,YAAY,MAAM,GAAG;AAC5D,YAAM,UAAU,aAAa,KAAK,GAAG;AAErC,UAAI,CAAC,SAAS;AACZ,gBAAQ,IAAIA,QAAM,IAAI,kBAAkB,CAAC;AACzC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA;AAAA,QACE,YAAY,WAAW,QAAQ,IAAI,cAAc,SAAS,WAAW;AAAA,QACrE;AAAA,QACA;AAAA,MACF;AAEA,cAAQ,IAAIA,QAAM,MAAM,uBAAkB,WAAW,EAAE,CAAC;AACxD;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAAS,mBAAmB,eAAe,OAAO;AAExD,UAAI,CAAC,QAAQ;AACX,gBAAQ,IAAIA,QAAM,MAAM,oBAAoB,CAAC;AAC7C;AAAA,MACF;AAEA,cAAQ,IAAI,MAAM;AAClB;AAAA,IACF;AAAA,IAEA;AACE,cAAQ,IAAIA,QAAM,KAAK,gBAAgB,CAAC;AACxC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,KAAKA,QAAM,KAAK,gCAAgC,CAAC,4BAA4B;AACzF,cAAQ,IAAI,KAAKA,QAAM,KAAK,qCAAqC,CAAC,uBAAuB;AACzF,cAAQ,IAAI,KAAKA,QAAM,KAAK,6BAA6B,CAAC,2BAA2B;AACrF,cAAQ,IAAI,KAAKA,QAAM,KAAK,gCAAgC,CAAC,0BAA0B;AACvF,cAAQ,IAAI,KAAKA,QAAM,KAAK,qCAAqC,CAAC,wBAAwB;AAC1F,cAAQ,IAAI,KAAKA,QAAM,KAAK,+BAA+B,CAAC,0BAA0B;AAAA,EAC1F;AACF;;;AC1JA;AAEA;AAFA,OAAOC,aAAW;AAClB,OAAOC,UAAS;AAYhB,eAAsB,eAAe,IAAa,UAA0B,CAAC,GAAkB;AAC7F,QAAM,UAAUA,KAAI,gCAAgC,EAAE,MAAM;AAE5D,MAAI;AAEF,QAAI,QAAQ,OAAO,CAAC,IAAI;AACtB,YAAM,UAAU,oBAAoB;AAEpC,UAAI,QAAQ,WAAW,GAAG;AACxB,gBAAQ,QAAQ,yBAAyB;AACzC;AAAA,MACF;AAEA,UAAI,QAAQ,MAAM;AAChB,gBAAQ,KAAK;AACb,gBAAQ,IAAI,KAAK,UAAU,EAAE,SAAS,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC;AAE1E,YAAI,CAAC,QAAQ,KAAK;AAChB,kBAAQ,IAAID,QAAM,IAAI,gDAAgD,CAAC;AACvE;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,QAAQ,KAAK;AAChB,gBAAQ,KAAK,SAAS,QAAQ,MAAM,mBAAmB;AACvD,gBAAQ,IAAI,EAAE;AAEd,mBAAW,SAAS,SAAS;AAC3B,kBAAQ,IAAI,KAAKA,QAAM,IAAI,QAAG,CAAC,IAAIA,QAAM,KAAK,MAAM,EAAE,CAAC,EAAE;AACzD,kBAAQ,IAAI,cAAc,MAAM,OAAO,EAAE;AACzC,kBAAQ,IAAI,gBAAgB,MAAM,SAAS,EAAE;AAC7C,kBAAQ,IAAI,EAAE;AAAA,QAChB;AAEA,gBAAQ,IAAIA,QAAM,IAAI,mDAAmD,CAAC;AAC1E;AAAA,MACF;AAEA,cAAQ,OAAO;AACf,YAAM,SAAS,kBAAkB;AAEjC,cAAQ,KAAK;AAEb,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,MACF;AAEA,UAAI,OAAO,UAAU,SAAS,GAAG;AAC/B,gBAAQ,IAAIA,QAAM,MAAM,oBAAe,OAAO,UAAU,MAAM,YAAY,CAAC;AAC3E,mBAAWE,YAAW,OAAO,WAAW;AACtC,kBAAQ,IAAI,KAAKF,QAAM,KAAKE,QAAO,CAAC,EAAE;AAAA,QACxC;AAAA,MACF;AAEA,UAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,gBAAQ,IAAIF,QAAM,IAAI,4BAAuB,OAAO,OAAO,MAAM,YAAY,CAAC;AAC9E,mBAAWE,YAAW,OAAO,QAAQ;AACnC,kBAAQ,IAAI,KAAKF,QAAM,IAAIE,QAAO,CAAC,EAAE;AAAA,QACvC;AAAA,MACF;AAEA;AAAA,IACF;AAGA,UAAM,UAAU,GAAG,WAAW,QAAQ,IAAI,KAAK,SAAS,GAAG,YAAY,CAAC;AACxE,YAAQ,OAAO,cAAc,OAAO;AAEpC,UAAM,QAAQ,aAAa,OAAO;AAElC,QAAI,CAAC,OAAO;AACV,cAAQ,KAAK,oBAAoB,OAAO,EAAE;AAC1C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,QAAQ,cAAc,OAAO,EAAE;AACvC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIF,QAAM,KAAK,gBAAgB,CAAC;AACxC,YAAQ,IAAI,gBAAgBA,QAAM,KAAK,MAAM,OAAO,CAAC,EAAE;AACvD,YAAQ,IAAI,gBAAgBA,QAAM,IAAI,MAAM,SAAS,CAAC,EAAE;AACxD,YAAQ,IAAI,gBAAgB,MAAM,KAAK,EAAE;AACzC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,QAAM,IAAI,WAAW,CAAC;AAClC,YAAQ,IAAI,6BAA6B,MAAM,EAAE,EAAE;AACnD,YAAQ,IAAI,4BAA4B,MAAM,OAAO,iBAAiB;AAAA,EAExE,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ACxGA;AACA;AADA,OAAOG,aAAW;AAclB,eAAsB,UAAU,SAAkB,UAAqB,CAAC,GAAkB;AAExF,MAAI,QAAQ,YAAY,CAAC,SAAS;AAChC,UAAM,WAAW,iBAAiB;AAElC,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC7C;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,cAAQ,IAAIA,QAAM,IAAI,4BAA4B,CAAC;AACnD,cAAQ,IAAIA,QAAM,IAAI,0CAA0C,CAAC;AACjE;AAAA,IACF;AAEA,YAAQ,IAAIA,QAAM,KAAK,oBAAoB,CAAC;AAG5C,YAAQ;AAAA,MACN,GAAG,QAAQ,OAAO,EAAE,CAAC,IAAI,UAAU,SAAS,CAAC,CAAC,IAAI,QAAQ,SAAS,CAAC,CAAC,IAAI,WAAW,SAAS,EAAE,CAAC;AAAA,IAClG;AACA,YAAQ,IAAIA,QAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAErC,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,IAAI,SAAS,CAAC;AACpB,YAAM,QAAQ,MAAM,IAAI,cAAO,MAAM,IAAI,cAAO,MAAM,IAAI,cAAO;AACjE,YAAM,aAAa,IAAI,EAAE,cAAc,KAAK,QAAQ,CAAC,CAAC;AACtD,YAAM,UAAU,EAAE,cAAc,IAAI,GAAG,EAAE,WAAW,MAAM;AAE1D,cAAQ;AAAA,QACN,GAAG,KAAK,IAAI,EAAE,QAAQ,OAAO,EAAE,CAAC,IAAI,WAAW,SAAS,CAAC,CAAC,IAAI,EAAE,YAC7D,SAAS,EACT,SAAS,CAAC,CAAC,IAAI,QAAQ,SAAS,EAAE,CAAC;AAAA,MACxC;AAAA,IACF;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,QAAM,IAAI,yCAAyC,CAAC;AAChE;AAAA,EACF;AAGA,QAAM,eAAe,QAAQ,WAAW,QAAQ,IAAI,UAAU,SAAS,QAAQ,YAAY,CAAC;AAC5F,QAAM,KAAK,WAAW,YAAY;AAElC,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,CAAC;AACvC;AAAA,EACF;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,SAAS,EAAE,CAAC;AAC1B;;;ACnEA;AAAA,OAAOC,aAAW;;;ACAlB;AAYA;AAFA,SAAS,cAAAC,cAAY,aAAAC,YAAW,gBAAAC,gBAAc,iBAAAC,gBAAe,gBAAgB,eAAAC,oBAAmB;AAChG,SAAS,QAAAC,cAAsB;AAoC/B,SAAS,aAAa,SAAyB;AAC7C,SAAOA,OAAK,YAAY,SAAS,UAAU;AAC7C;AAKO,SAAS,eAAe,SAA2C;AACxE,QAAM,YAAY,aAAa,OAAO;AACtC,MAAI,CAACL,aAAW,SAAS,EAAG,QAAO;AAEnC,MAAI;AACF,UAAM,UAAUE,eAAa,WAAW,OAAO;AAC/C,WAAO,aAAa,OAAO;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,gBAAgB,SAAiB,OAAgC;AAC/E,QAAM,MAAMG,OAAK,YAAY,OAAO;AACpC,EAAAJ,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,QAAM,UAAU,gBAAgB,KAAK;AACrC,EAAAE,eAAc,aAAa,OAAO,GAAG,OAAO;AAC9C;AAKO,SAAS,iBAAiB,SAAiB,YAAoB,aAA4B;AAChG,QAAM,QAAQ,eAAe,OAAO;AACpC,MAAI,CAAC,MAAO;AAEZ,QAAM,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAC5C,QAAM,iBAAiB;AACvB,MAAI,aAAa;AACf,UAAM,cAAc;AAAA,EACtB;AAEA,kBAAgB,SAAS,KAAK;AAChC;AAEA,SAAS,gBAAgB,OAAkC;AACzD,QAAM,QAAkB;AAAA,IACtB,kBAAkB,MAAM,OAAO;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,MAAM,OAAO;AAAA,IACvB,WAAW,MAAM,MAAM;AAAA,IACvB,kBAAkB,MAAM,YAAY;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,MAAM,gBAAgB;AACxB,UAAM,KAAK,uBAAuB;AAClC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,qBAAqB,MAAM,cAAc,GAAG;AACvD,QAAI,MAAM,aAAa;AACrB,YAAM,KAAK,kBAAkB,MAAM,WAAW,GAAG;AAAA,IACnD;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,MAAM,YAAY,aAAa,MAAM,YAAY,OAAO,MAAM,YAAY,OAAO;AACnF,UAAM,KAAK,uBAAuB;AAClC,UAAM,KAAK,EAAE;AACb,QAAI,MAAM,YAAY,WAAW;AAC/B,YAAM,KAAK,gBAAgB,MAAM,YAAY,SAAS,EAAE;AAAA,IAC1D;AACA,QAAI,MAAM,YAAY,KAAK;AACzB,YAAM,KAAK,UAAU,MAAM,YAAY,GAAG,EAAE;AAAA,IAC9C;AACA,QAAI,MAAM,YAAY,OAAO;AAC3B,YAAM,KAAK,YAAY,MAAM,YAAY,KAAK,EAAE;AAAA,IAClD;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAa,SAAoC;AACxD,QAAM,QAA2B;AAAA,IAC/B,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,aAAa,CAAC;AAAA,EAChB;AAGA,QAAM,aAAa,QAAQ,MAAM,qBAAqB;AACtD,MAAI,WAAY,OAAM,UAAU,WAAW,CAAC,EAAE,KAAK;AAGnD,QAAM,cAAc,QAAQ,MAAM,cAAc;AAChD,MAAI,YAAa,OAAM,SAAS,YAAY,CAAC,EAAE,KAAK;AAGpD,QAAM,gBAAgB,QAAQ,MAAM,qBAAqB;AACzD,MAAI,cAAe,OAAM,eAAe,cAAc,CAAC,EAAE,KAAK;AAG9D,QAAM,kBAAkB,QAAQ,MAAM,yBAAyB;AAC/D,MAAI,gBAAiB,OAAM,iBAAiB,gBAAgB,CAAC;AAG7D,QAAM,cAAc,QAAQ,MAAM,sBAAsB;AACxD,MAAI,YAAa,OAAM,cAAc,YAAY,CAAC;AAGlD,QAAM,iBAAiB,QAAQ,MAAM,mBAAmB;AACxD,MAAI,eAAgB,OAAM,YAAY,YAAY,eAAe,CAAC,EAAE,KAAK;AAEzE,QAAM,WAAW,QAAQ,MAAM,aAAa;AAC5C,MAAI,SAAU,OAAM,YAAY,MAAM,SAAS,CAAC,EAAE,KAAK;AAEvD,QAAM,aAAa,QAAQ,MAAM,eAAe;AAChD,MAAI,WAAY,OAAM,YAAY,QAAQ,WAAW,CAAC,EAAE,KAAK;AAE7D,SAAO;AACT;AA6CA,SAAS,eAAe,SAAyB;AAC/C,SAAOG,OAAK,YAAY,SAAS,YAAY;AAC/C;AAKO,SAAS,cAAc,SAAiB,SAA6B;AAC1E,QAAM,MAAMA,OAAK,YAAY,OAAO;AACpC,EAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,QAAM,cAAc,eAAe,OAAO;AAC1C,QAAM,UAAU,qBAAqB,OAAO;AAE5C,MAAIC,aAAW,WAAW,GAAG;AAC3B,mBAAe,aAAa,cAAc,OAAO;AAAA,EACnD,OAAO;AACL,IAAAC,eAAc,aAAa,yBAAyB,OAAO;AAAA,EAC7D;AACF;AAEA,SAAS,qBAAqB,SAA+B;AAC3D,QAAM,QAAkB;AAAA,IACtB,MAAM,QAAQ,KAAK;AAAA,IACnB;AAAA,IACA,kBAAkB,QAAQ,WAAW;AAAA,EACvC;AAEA,MAAI,QAAQ,UAAU;AACpB,UAAM,KAAK,iBAAiB,QAAQ,QAAQ,UAAU;AAAA,EACxD;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,mBAAmB;AAC9B,QAAM,KAAK,EAAE;AAEb,WAAS,IAAI,GAAG,IAAI,QAAQ,YAAY,QAAQ,KAAK;AACnD,UAAM,KAAK,GAAG,IAAI,CAAC,KAAK,QAAQ,YAAY,CAAC,CAAC,EAAE;AAAA,EAClD;AAEA,MAAI,QAAQ,eAAe,QAAQ,YAAY,SAAS,GAAG;AACzD,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,kBAAkB;AAC7B,UAAM,KAAK,EAAE;AACb,aAAS,IAAI,GAAG,IAAI,QAAQ,YAAY,QAAQ,KAAK;AACnD,YAAM,KAAK,GAAG,IAAI,CAAC,KAAK,QAAQ,YAAY,CAAC,CAAC,EAAE;AAAA,IAClD;AAAA,EACF;AAEA,MAAI,QAAQ,iBAAiB,QAAQ,cAAc,SAAS,GAAG;AAC7D,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,oBAAoB;AAC/B,UAAM,KAAK,EAAE;AACb,eAAW,QAAQ,QAAQ,eAAe;AACxC,YAAM,KAAK,KAAK,IAAI,EAAE;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,KAAK,EAAE;AACb,SAAO,MAAM,KAAK,IAAI;AACxB;AAIA,SAAS,cAAc,SAAyB;AAC9C,SAAOH,OAAK,YAAY,SAAS,SAAS;AAC5C;AAKO,SAAS,WACd,SACA,QACA,SACM;AACN,QAAM,aAAa,cAAc,OAAO;AACxC,EAAAC,WAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAEzC,QAAM,OAAO,oBAAI,KAAK;AACtB,QAAM,UAAU,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAC/C,QAAM,cAAcD,OAAK,YAAY,GAAG,OAAO,MAAM;AAErD,QAAM,YAAY,KAAK,YAAY;AACnC,QAAM,aAAa,UAAU,IAAI,KAAK,UAAU,OAAO,CAAC,KAAK;AAC7D,QAAM,UAAU,IAAI,SAAS,KAAK,MAAM,GAAG,UAAU;AAAA;AAErD,iBAAe,aAAa,OAAO;AACrC;AAKO,SAAS,cAAc,SAAiB,SAA2B;AACxE,QAAM,aAAa,cAAc,OAAO;AACxC,MAAI,CAACE,aAAW,UAAU,EAAG,QAAO,CAAC;AAErC,QAAM,UAAoB,CAAC;AAC3B,QAAM,QAAQ,IAAI,OAAO,SAAS,GAAG;AAErC,QAAM,QAAQE,aAAY,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,CAAC;AACtE,QAAM,KAAK,EAAE,QAAQ;AAErB,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAUC,eAAaL,OAAK,YAAY,IAAI,GAAG,OAAO;AAC5D,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,eAAW,QAAQ,OAAO;AACxB,UAAI,MAAM,KAAK,IAAI,GAAG;AACpB,gBAAQ,KAAK,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,iBAAiB,SAAiB,QAAgB,IAAc;AAC9E,QAAM,aAAa,cAAc,OAAO;AACxC,MAAI,CAACE,aAAW,UAAU,EAAG,QAAO,CAAC;AAErC,QAAM,UAAoB,CAAC;AAE3B,QAAM,QAAQE,aAAY,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,CAAC;AACtE,QAAM,KAAK,EAAE,QAAQ;AAErB,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAQ,UAAU,MAAO;AAE7B,UAAM,UAAUC,eAAaL,OAAK,YAAY,IAAI,GAAG,OAAO;AAC5D,UAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;AAExD,eAAW,QAAQ,MAAM,QAAQ,GAAG;AAClC,UAAI,QAAQ,UAAU,MAAO;AAC7B,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;AAaO,SAAS,eAAe,MAAsB;AACnD,SAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAClC;AAkCA,SAAS,mBAAmB,SAAyB;AACnD,SAAOM,OAAK,YAAY,SAAS,cAAc;AACjD;AAiDO,SAAS,iBAAiB,SAI9B;AACD,QAAM,MAAM,mBAAmB,OAAO;AACtC,MAAI,CAACC,aAAW,GAAG,EAAG,QAAO,CAAC;AAE9B,SAAOC,aAAY,GAAG,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,EAC/B,IAAI,CAAC,MAAM;AACV,UAAM,QAAQ,EAAE,MAAM,kBAAkB;AACxC,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO;AAAA,MACL,MAAM,MAAM,CAAC;AAAA,MACb,WAAW,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,MAChC,MAAMC,OAAK,KAAK,CAAC;AAAA,IACnB;AAAA,EACF,CAAC,EACA,OAAO,OAAO;AACnB;AAKO,SAAS,iBAAiB,UAAiC;AAChE,MAAI,CAACF,aAAW,QAAQ,EAAG,QAAO;AAClC,SAAOG,eAAa,UAAU,OAAO;AACvC;;;ADxdA,SAAS,gBAAAC,gBAAc,cAAAC,oBAAkB;AAQzC,eAAsB,eACpB,QACA,MACA,MACA,UAA0B,CAAC,GACZ;AAEf,QAAM,UAAU,QAAQ,IAAI,uBAAuB,QAAQ;AAE3D,UAAQ,QAAQ;AAAA,IACd,KAAK,SAAS;AAEZ,YAAM,QAAQ,eAAe,OAAO;AAEpC,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAC1C;AAAA,MACF;AAEA,UAAI,CAAC,OAAO;AACV,gBAAQ,IAAIC,QAAM,IAAI,2BAA2B,CAAC;AAClD,gBAAQ,IAAIA,QAAM,IAAI,8DAA8D,CAAC;AACrF;AAAA,MACF;AAEA,cAAQ,IAAIA,QAAM,KAAK;AAAA,eAAkB,MAAM,OAAO;AAAA,CAAI,CAAC;AAC3D,cAAQ,IAAI,WAAWA,QAAM,KAAK,MAAM,MAAM,CAAC,EAAE;AACjD,cAAQ,IAAI,kBAAkBA,QAAM,IAAI,MAAM,YAAY,CAAC,EAAE;AAE7D,UAAI,MAAM,gBAAgB;AACxB,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAIA,QAAM,KAAK,qBAAqB,CAAC;AAC7C,gBAAQ,IAAI,iBAAiBA,QAAM,OAAO,MAAM,cAAc,CAAC,EAAE;AACjE,YAAI,MAAM,aAAa;AACrB,kBAAQ,IAAI,aAAaA,QAAM,MAAM,MAAM,WAAW,CAAC,EAAE;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI,MAAM,YAAY,aAAa,MAAM,YAAY,KAAK;AACxD,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAIA,QAAM,KAAK,qBAAqB,CAAC;AAC7C,YAAI,MAAM,YAAY,WAAW;AAC/B,kBAAQ,IAAI,gBAAgBA,QAAM,IAAI,MAAM,YAAY,SAAS,CAAC,EAAE;AAAA,QACtE;AACA,YAAI,MAAM,YAAY,KAAK;AACzB,kBAAQ,IAAI,UAAUA,QAAM,IAAI,MAAM,YAAY,GAAG,CAAC,EAAE;AAAA,QAC1D;AACA,YAAI,MAAM,YAAY,OAAO;AAC3B,kBAAQ,IAAI,YAAYA,QAAM,IAAI,MAAM,YAAY,KAAK,CAAC,EAAE;AAAA,QAC9D;AAAA,MACF;AACA,cAAQ,IAAI,EAAE;AACd;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AAEX,YAAM,UAAU,QAAQ,QAAQ;AAChC,YAAM,cAAc,OAAO,OAAO;AAElC,YAAM,QAA2B;AAAA,QAC/B,SAAS,QAAQ,YAAY;AAAA,QAC7B,QAAQ;AAAA,QACR,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,aAAa,CAAC;AAAA,MAChB;AAEA,sBAAgB,aAAc,KAAK;AACnC,iBAAW,aAAc,gBAAgB,EAAE,QAAQ,CAAC;AAEpD,cAAQ,IAAIA,QAAM,MAAM,gCAA2B,WAAW,EAAE,CAAC;AACjE;AAAA,IACF;AAAA,IAEA,KAAK,cAAc;AAEjB,YAAM,aAAa;AACnB,YAAM,SAAS;AAEf,UAAI,CAAC,YAAY;AACf,gBAAQ,IAAIA,QAAM,IAAI,6BAA6B,CAAC;AACpD,gBAAQ,IAAIA,QAAM,IAAI,+DAA+D,CAAC;AACtF;AAAA,MACF;AAEA,uBAAiB,SAAS,YAAY,MAAM;AAC5C,iBAAW,SAAS,sBAAsB,EAAE,YAAY,OAAO,CAAC;AAEhE,cAAQ,IAAIA,QAAM,MAAM,6BAAwB,UAAU,GAAG,CAAC;AAC9D,UAAI,QAAQ;AACV,gBAAQ,IAAIA,QAAM,IAAI,oBAAoB,MAAM,GAAG,CAAC;AAAA,MACtD;AACA;AAAA,IACF;AAAA,IAEA,KAAK,WAAW;AAEd,YAAM,QAAQ,QAAQ;AAGtB,YAAM,UAAU;AAAA,QACd;AAAA,QACA,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC,aAAa,CAAC,yBAAyB;AAAA,MACzC;AAEA,oBAAc,SAAS,OAAO;AAC9B,iBAAW,SAAS,mBAAmB,EAAE,MAAM,CAAC;AAEhD,cAAQ,IAAIA,QAAM,MAAM,0BAAqB,KAAK,GAAG,CAAC;AACtD;AAAA,IACF;AAAA,IAEA,KAAK,WAAW;AAEd,YAAM,UAAU;AAEhB,UAAI,SAAS;AACX,cAAM,UAAU,cAAc,SAAS,OAAO;AAC9C,YAAI,QAAQ,WAAW,GAAG;AACxB,kBAAQ,IAAIA,QAAM,IAAI,mBAAmB,CAAC;AAC1C;AAAA,QACF;AAEA,gBAAQ,IAAIA,QAAM,KAAK;AAAA,uBAA0B,OAAO;AAAA,CAAM,CAAC;AAC/D,mBAAW,QAAQ,QAAQ,MAAM,GAAG,EAAE,GAAG;AACvC,kBAAQ,IAAI,IAAI;AAAA,QAClB;AAAA,MACF,OAAO;AACL,cAAM,SAAS,iBAAiB,SAAS,EAAE;AAC3C,YAAI,OAAO,WAAW,GAAG;AACvB,kBAAQ,IAAIA,QAAM,IAAI,iBAAiB,CAAC;AACxC;AAAA,QACF;AAEA,gBAAQ,IAAIA,QAAM,KAAK,qBAAqB,CAAC;AAC7C,mBAAW,QAAQ,QAAQ;AACzB,kBAAQ,IAAI,IAAI;AAAA,QAClB;AAAA,MACF;AACA,cAAQ,IAAI,EAAE;AACd;AAAA,IACF;AAAA,IAEA,KAAK,eAAe;AAElB,YAAM,WAAW;AAEjB,UAAI,YAAYD,aAAW,QAAQ,GAAG;AACpC,cAAM,UAAU,iBAAiB,QAAQ;AACzC,YAAI,SAAS;AACX,kBAAQ,IAAI,OAAO;AAAA,QACrB;AACA;AAAA,MACF;AAEA,YAAM,UAAU,iBAAiB,OAAO;AACxC,UAAI,QAAQ,WAAW,GAAG;AACxB,gBAAQ,IAAIC,QAAM,IAAI,0BAA0B,CAAC;AACjD;AAAA,MACF;AAEA,cAAQ,IAAIA,QAAM,KAAK,2BAA2B,CAAC;AACnD,iBAAW,OAAO,SAAS;AACzB,cAAM,OAAO,IAAI,KAAK,IAAI,SAAS,EAAE,eAAe;AACpD,gBAAQ,IAAI,KAAKA,QAAM,KAAK,IAAI,IAAI,CAAC,IAAIA,QAAM,IAAI,IAAI,CAAC,EAAE;AAC1D,gBAAQ,IAAI,OAAOA,QAAM,IAAI,IAAI,IAAI,CAAC,EAAE;AAAA,MAC1C;AACA,cAAQ,IAAI,EAAE;AACd;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AAEb,YAAM,SAAS;AAEf,UAAI,CAAC,QAAQ;AACX,gBAAQ,IAAIA,QAAM,IAAI,+CAA+C,CAAC;AACtE;AAAA,MACF;AAEA,UAAI,OAAO;AACX,UAAID,aAAW,MAAM,GAAG;AACtB,eAAOD,eAAa,QAAQ,OAAO;AAAA,MACrC;AAEA,YAAM,SAAS,eAAe,IAAI;AAClC,cAAQ,IAAI,qBAAqBE,QAAM,KAAK,OAAO,eAAe,CAAC,CAAC,EAAE;AACtE;AAAA,IACF;AAAA,IAEA;AACE,cAAQ,IAAIA,QAAM,KAAK,mBAAmB,CAAC;AAC3C,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,KAAKA,QAAM,KAAK,mCAAmC,CAAC,2BAA2B;AAC3F,cAAQ,IAAI,KAAKA,QAAM,KAAK,uCAAuC,CAAC,qBAAqB;AACzF,cAAQ,IAAI,KAAKA,QAAM,KAAK,mCAAmC,CAAC,wBAAwB;AACxF,cAAQ,IAAI,KAAKA,QAAM,KAAK,kCAAkC,CAAC,0BAA0B;AACzF,cAAQ,IAAI,KAAKA,QAAM,KAAK,oCAAoC,CAAC,sBAAsB;AACvF,cAAQ,IAAI,KAAKA,QAAM,KAAK,qCAAqC,CAAC,wBAAwB;AAC1F,cAAQ,IAAI,KAAKA,QAAM,KAAK,gCAAgC,CAAC,gCAAgC;AAC7F,cAAQ,IAAI,EAAE;AAAA,EAClB;AACF;;;AElOA;AAAA,OAAOC,aAAW;;;ACAlB;AAYA;AACA;AAJA,SAAS,cAAAC,cAAY,aAAAC,YAAW,gBAAAC,gBAAc,iBAAAC,sBAAqB;AACnE,SAAS,QAAAC,cAAY;AACrB,SAAS,YAAAC,iBAAgB;AAKlB,IAAM,0BAA0B,KAAK;AACrC,IAAM,+BAA+B;AACrC,IAAM,sBAAsB,IAAI,KAAK;AACrC,IAAM,4BAA4B,KAAK;AAsB9C,SAAS,cAAc,SAAyB;AAC9C,SAAOD,OAAK,YAAY,SAAS,aAAa;AAChD;AAKO,SAAS,eAAe,SAA8B;AAC3D,QAAM,aAAa,cAAc,OAAO;AAExC,QAAM,gBAA6B;AAAA,IACjC;AAAA,IACA,QAAQ;AAAA,IACR,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,YAAY;AAAA,EACd;AAEA,MAAIJ,aAAW,UAAU,GAAG;AAC1B,QAAI;AACF,YAAM,SAAS,KAAK,MAAME,eAAa,YAAY,OAAO,CAAC;AAC3D,aAAO,EAAE,GAAG,eAAe,GAAG,OAAO;AAAA,IACvC,QAAQ;AAAA,IAAC;AAAA,EACX;AAEA,SAAO;AACT;AAKO,SAAS,gBAAgB,QAA2B;AACzD,QAAM,MAAME,OAAK,YAAY,OAAO,OAAO;AAC3C,EAAAH,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,EAAAE,eAAc,cAAc,OAAO,OAAO,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC9E;AAKO,SAAS,aAAa,SAA0B;AACrD,MAAI;AACF,IAAAE,UAAS,wBAAwB,OAAO,iBAAiB,EAAE,UAAU,QAAQ,CAAC;AAC9E,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AA2CO,SAAS,UACd,SACA,SAAuB;AAAA,EACrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,iBAAiB;AACnB,GACa;AACb,QAAM,SAAS,eAAe,OAAO;AACrC,SAAO,YAAW,oBAAI,KAAK,GAAE,YAAY;AAGzC,QAAM,QAAQ,aAAa,OAAO;AAElC,MAAI,CAAC,OAAO;AAEV,WAAO,SAAS;AAChB,WAAO;AAAA,EACT,OAAO;AAEL,UAAM,QAAQ,cAAc,OAAO;AACnC,UAAM,eAAe,OAAO,eAAe,IAAI,KAAK,MAAM,YAAY,IAAI;AAE1E,QAAI,cAAc;AAChB,YAAM,QAAQ,KAAK,IAAI,IAAI,aAAa,QAAQ;AAChD,YAAM,aAAa,SAAS,MAAO;AAEnC,UAAI,aAAa,IAAI;AACnB,eAAO,SAAS;AAChB,eAAO;AAAA,MACT,WAAW,aAAa,IAAI;AAC1B,eAAO,SAAS;AAAA,MAElB,OAAO;AACL,eAAO,SAAS;AAChB,eAAO,sBAAsB;AAAA,MAC/B;AAAA,IACF,OAAO;AAEL,aAAO,SAAS;AAChB,aAAO,sBAAsB;AAAA,IAC/B;AAEA,WAAO,oBAAmB,oBAAI,KAAK,GAAE,YAAY;AAAA,EACnD;AAGA,MAAI,OAAO,eAAe;AACxB,UAAM,gBAAgB,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,aAAa,EAAE,QAAQ;AAC1E,WAAO,aAAa,gBAAgB,OAAO;AAAA,EAC7C,OAAO;AACL,WAAO,aAAa;AAAA,EACtB;AAEA,kBAAgB,MAAM;AACtB,SAAO;AACT;AAKA,eAAsB,iBACpB,SACA,SAAuB;AAAA,EACrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,iBAAiB;AACnB,GAC2E;AAC3E,QAAM,SAAS,eAAe,OAAO;AAGrC,MAAI,OAAO,sBAAsB,OAAO,qBAAqB;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ,QAAQ,OAAO,mBAAmB,mBAAmB,OAAO,mBAAmB;AAAA,IACzF;AAAA,EACF;AAGA,MAAI,OAAO,eAAe;AACxB,UAAM,gBAAgB,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,aAAa,EAAE,QAAQ;AAC1E,QAAI,gBAAgB,OAAO,YAAY;AACrC,YAAM,cAAc,OAAO,aAAa;AACxC,YAAM,eAAe,KAAK,KAAK,eAAe,MAAO,GAAG;AACxD,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ,gBAAgB,YAAY;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,cAAU,OAAO;AAAA,EACnB,QAAQ;AAAA,EAAC;AAGT,SAAO,iBAAgB,oBAAI,KAAK,GAAE,YAAY;AAC9C,SAAO;AACP,SAAO,sBAAsB;AAC7B,SAAO,SAAS;AAChB,SAAO,aAAa;AACpB,kBAAgB,MAAM;AAGtB,MAAI;AACF,UAAM,YAAY,aAAa,OAAO;AACtC,QAAI,WAAW;AACb,aAAO,SAAS;AAChB,aAAO;AACP,sBAAgB,MAAM;AACtB,aAAO,EAAE,QAAQ,aAAa,QAAQ,6BAA6B;AAAA,IACrE;AAAA,EACF,QAAQ;AAAA,EAAC;AAET,SAAO,EAAE,QAAQ,aAAa,QAAQ,gCAAgC;AACxE;AAKA,eAAsB,eACpB,SAAuB;AAAA,EACrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,iBAAiB;AACnB,GAQC;AACD,QAAM,UAAU;AAAA,IACd,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,IACN,WAAW,CAAC;AAAA,EACd;AAGA,MAAI,WAAqB,CAAC;AAC1B,MAAI;AACF,UAAM,SAASC;AAAA,MACb;AAAA,MACA,EAAE,UAAU,QAAQ;AAAA,IACtB;AACA,eAAW,OACR,KAAK,EACL,MAAM,IAAI,EACV,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,CAAC;AAAA,EACzC,QAAQ;AAAA,EAAC;AAGT,MAAIC,aAAW,UAAU,GAAG;AAC1B,UAAM,EAAE,aAAAC,cAAY,IAAI,MAAM,OAAO,IAAI;AACzC,UAAM,OAAOA,cAAY,YAAY,EAAE,eAAe,KAAK,CAAC,EACzD,OAAO,CAAC,MAAM,EAAE,YAAY,KAAK,EAAE,KAAK,WAAW,QAAQ,CAAC,EAC5D,IAAI,CAAC,MAAM,EAAE,IAAI;AAEpB,eAAW,OAAO,MAAM;AACtB,UAAI,CAAC,SAAS,SAAS,GAAG,GAAG;AAC3B,iBAAS,KAAK,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAGA,aAAW,WAAW,UAAU;AAC9B,YAAQ;AAER,UAAM,SAAS,UAAU,SAAS,MAAM;AAExC,YAAQ,OAAO,QAAQ;AAAA,MACrB,KAAK;AACH,gBAAQ;AACR;AAAA,MACF,KAAK;AACH,gBAAQ;AACR;AAAA,MACF,KAAK;AACH,gBAAQ;AAER,cAAM,SAAS,MAAM,iBAAiB,SAAS,MAAM;AACrD,YAAI,OAAO,WAAW,aAAa;AACjC,kBAAQ,UAAU,KAAK,OAAO;AAAA,QAChC;AACA;AAAA,MACF,KAAK;AACH,gBAAQ;AAER,cAAM,aAAa,MAAM,iBAAiB,SAAS,MAAM;AACzD,YAAI,WAAW,WAAW,aAAa;AACrC,kBAAQ,UAAU,KAAK,OAAO;AAAA,QAChC;AACA;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AACT;AAMO,SAAS,kBACd,SAAuB;AAAA,EACrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,iBAAiB;AACnB,GACA,SACY;AACZ,MAAI,UAAU;AAEd,QAAM,UAAU,YAAY;AAC1B,WAAO,SAAS;AACd,UAAI;AACF,cAAM,UAAU,MAAM,eAAe,MAAM;AAC3C,YAAI,SAAS;AACX,kBAAQ,OAAO;AAAA,QACjB;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,uBAAuB,KAAK;AAAA,MAC5C;AAGA,YAAM,IAAI,QAAQ,CAACC,aAAY,WAAWA,UAAS,OAAO,eAAe,CAAC;AAAA,IAC5E;AAAA,EACF;AAGA,UAAQ;AAGR,SAAO,MAAM;AACX,cAAU;AAAA,EACZ;AACF;AAKO,SAAS,mBAAmB,QAA6B;AAC9D,QAAM,cAAc;AAAA,IAClB,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAEA,QAAM,QAAkB;AAAA,IACtB,GAAG,YAAY,OAAO,MAAM,CAAC,IAAI,OAAO,OAAO,KAAK,OAAO,OAAO,YAAY,CAAC;AAAA,EACjF;AAEA,MAAI,OAAO,UAAU;AACnB,UAAM,KAAK,gBAAgB,OAAO,QAAQ,EAAE;AAAA,EAC9C;AAEA,MAAI,OAAO,sBAAsB,GAAG;AAClC,UAAM,KAAK,2BAA2B,OAAO,mBAAmB,EAAE;AAAA,EACpE;AAEA,MAAI,OAAO,iBAAiB,GAAG;AAC7B,UAAM,KAAK,kBAAkB,OAAO,cAAc,EAAE;AAAA,EACtD;AAEA,MAAI,OAAO,gBAAgB,GAAG;AAC5B,UAAM,KAAK,iBAAiB,OAAO,aAAa,EAAE;AAAA,EACpD;AAEA,MAAI,OAAO,YAAY;AACrB,UAAM,KAAK,uBAAuB;AAAA,EACpC;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ADpZA;AAQA,eAAsB,cACpB,QACA,KACA,UAAyB,CAAC,GACX;AACf,QAAM,SAAuB;AAAA,IAC3B,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,YAAY;AAAA,IACZ,iBAAiB,QAAQ,WAAW,QAAQ,WAAW,MAAO;AAAA,EAChE;AAEA,UAAQ,QAAQ;AAAA,IACd,KAAK,SAAS;AAEZ,cAAQ,IAAIC,QAAM,KAAK,2BAA2B,CAAC;AAEnD,YAAM,UAAU,MAAM,eAAe,MAAM;AAE3C,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC5C;AAAA,MACF;AAEA,cAAQ,IAAI,YAAY,QAAQ,OAAO,SAAS;AAChD,cAAQ,IAAI,KAAKA,QAAM,MAAM,iBAAiB,CAAC,IAAI,QAAQ,OAAO,EAAE;AACpE,cAAQ,IAAI,KAAKA,QAAM,OAAO,uBAAuB,CAAC,IAAI,QAAQ,OAAO,EAAE;AAC3E,cAAQ,IAAI,KAAKA,QAAM,IAAI,SAAS,EAAE,kBAAkB,CAAC,IAAI,QAAQ,KAAK,EAAE;AAC5E,cAAQ,IAAI,KAAKA,QAAM,IAAI,cAAc,CAAC,IAAI,QAAQ,IAAI,EAAE;AAE5D,UAAI,QAAQ,UAAU,SAAS,GAAG;AAChC,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAIA,QAAM,MAAM,mBAAmB,CAAC;AAC5C,mBAAW,WAAW,QAAQ,WAAW;AACvC,kBAAQ,IAAI,OAAO,OAAO,EAAE;AAAA,QAC9B;AAAA,MACF;AACA;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AAEb,YAAM,SAAS,kBAAkB;AAEjC,UAAI,OAAO,WAAW,GAAG;AACvB,gBAAQ,IAAIA,QAAM,IAAI,kBAAkB,CAAC;AACzC;AAAA,MACF;AAEA,YAAM,aAAa,OAAO,IAAI,CAAC,UAAU;AACvC,cAAM,SAAS,eAAe,MAAM,EAAE;AACtC,eAAO,EAAE,OAAO,OAAO;AAAA,MACzB,CAAC;AAED,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,WAAW,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AACpE;AAAA,MACF;AAEA,cAAQ,IAAIA,QAAM,KAAK,wBAAwB,CAAC;AAEhD,iBAAW,EAAE,OAAO,KAAK,YAAY;AACnC,gBAAQ,IAAI,mBAAmB,MAAM,CAAC;AACtC,gBAAQ,IAAI,EAAE;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AAEX,UAAI,CAAC,KAAK;AACR,gBAAQ,IAAIA,QAAM,IAAI,mBAAmB,CAAC;AAC1C,gBAAQ,IAAIA,QAAM,IAAI,wCAAwC,CAAC;AAC/D;AAAA,MACF;AAEA,YAAM,UAAU,IAAI,WAAW,QAAQ,IAAI,MAAM,SAAS,IAAI,YAAY,CAAC;AAC3E,cAAQ,IAAIA,QAAM,IAAI,WAAW,OAAO,KAAK,CAAC;AAE9C,YAAM,SAAS,UAAU,SAAS,MAAM;AAExC,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,MACF;AAEA,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,mBAAmB,MAAM,CAAC;AACtC;AAAA,IACF;AAAA,IAEA,KAAK,WAAW;AAEd,UAAI,CAAC,KAAK;AACR,gBAAQ,IAAIA,QAAM,IAAI,mBAAmB,CAAC;AAC1C,gBAAQ,IAAIA,QAAM,IAAI,2CAA2C,CAAC;AAClE;AAAA,MACF;AAEA,YAAM,UAAU,IAAI,WAAW,QAAQ,IAAI,MAAM,SAAS,IAAI,YAAY,CAAC;AAC3E,cAAQ,IAAIA,QAAM,IAAI,0BAA0B,OAAO,KAAK,CAAC;AAG7D,YAAM,cAAc,EAAE,GAAG,QAAQ,qBAAqB,EAAE;AACxD,YAAM,SAAS,MAAM,iBAAiB,SAAS,WAAW;AAE1D,UAAI,QAAQ,MAAM;AAChB,gBAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,MACF;AAEA,UAAI,OAAO,WAAW,aAAa;AACjC,gBAAQ,IAAIA,QAAM,MAAM,UAAU,OAAO,MAAM,EAAE,CAAC;AAAA,MACpD,WAAW,OAAO,WAAW,YAAY;AACvC,gBAAQ,IAAIA,QAAM,OAAO,gBAAgB,OAAO,MAAM,EAAE,CAAC;AAAA,MAC3D,OAAO;AACL,gBAAQ,IAAIA,QAAM,IAAI,OAAO,MAAM,CAAC;AAAA,MACtC;AACA;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AAEb,cAAQ,IAAIA,QAAM,KAAK,mCAAmC,CAAC;AAC3D,cAAQ,IAAIA,QAAM,IAAI,mBAAmB,OAAO,kBAAkB,GAAI,GAAG,CAAC;AAC1E,cAAQ,IAAIA,QAAM,IAAI,sBAAsB,OAAO,mBAAmB,EAAE,CAAC;AACzE,cAAQ,IAAIA,QAAM,IAAI,aAAa,OAAO,cAAc,MAAO,GAAG,GAAG,CAAC;AACtE,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,QAAM,IAAI,2BAA2B,CAAC;AAElD,YAAM,OAAO,kBAAkB,QAAQ,CAAC,YAAY;AAClD,cAAM,aAAY,oBAAI,KAAK,GAAE,mBAAmB;AAChD,cAAM,cAAc;AAAA,UAClB,IAAI,SAAS;AAAA,UACb,SAAS,QAAQ,OAAO;AAAA,UACxB,eAAe,QAAQ,OAAO;AAAA,UAC9B,YAAY,QAAQ,KAAK;AAAA,UACzB,SAAS,QAAQ,IAAI;AAAA,QACvB;AAEA,YAAI,QAAQ,UAAU,SAAS,GAAG;AAChC,sBAAY,KAAKA,QAAM,MAAM,IAAI,QAAQ,UAAU,MAAM,YAAY,CAAC;AAAA,QACxE;AAEA,gBAAQ,IAAI,YAAY,KAAK,GAAG,CAAC;AAAA,MACnC,CAAC;AAGD,cAAQ,GAAG,UAAU,MAAM;AACzB,gBAAQ,IAAI,OAAOA,QAAM,IAAI,2BAA2B,CAAC;AACzD,aAAK;AACL,gBAAQ,KAAK,CAAC;AAAA,MAChB,CAAC;AAGD,YAAM,IAAI,QAAQ,MAAM;AAAA,MAAC,CAAC;AAC1B;AAAA,IACF;AAAA,IAEA;AACE,cAAQ,IAAIA,QAAM,KAAK,6BAA6B,CAAC;AACrD,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,KAAKA,QAAM,KAAK,uBAAuB,CAAC,oCAAoC;AACxF,cAAQ,IAAI,KAAKA,QAAM,KAAK,wBAAwB,CAAC,iCAAiC;AACtF,cAAQ,IAAI,KAAKA,QAAM,KAAK,2BAA2B,CAAC,4BAA4B;AACpF,cAAQ,IAAI,KAAKA,QAAM,KAAK,8BAA8B,CAAC,yBAAyB;AACpF,cAAQ,IAAI,KAAKA,QAAM,KAAK,wBAAwB,CAAC,+BAA+B;AACpF,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,QAAM,KAAK,UAAU,CAAC;AAClC,cAAQ,IAAI,KAAKA,QAAM,IAAI,QAAQ,CAAC,+BAA+B;AACnE,cAAQ,IAAI,KAAKA,QAAM,IAAI,kBAAkB,CAAC,8CAA8C;AAC5F,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,QAAM,KAAK,0BAA0B,CAAC;AAClD,cAAQ,IAAI,mBAAmB,0BAA0B,GAAI,GAAG;AAChE,cAAQ,IAAI,2BAA2B,4BAA4B,EAAE;AACrE,cAAQ,IAAI,0BAA0B,uBAAuB,MAAO,GAAG,GAAG;AAC1E,cAAQ,IAAI,EAAE;AAAA,EAClB;AACF;;;AfxLO,SAAS,qBAAqBC,UAAwB;AAC3D,QAAM,OAAOA,SACV,QAAQ,MAAM,EACd,YAAY,2BAA2B;AAE1C,OACG,QAAQ,YAAY,EACpB,YAAY,8BAA8B,EAC1C,OAAO,mBAAmB,oCAAoC,QAAQ,EACtE,OAAO,uBAAuB,6BAA6B,QAAQ,EACnE,OAAO,aAAa,4BAA4B,EAChD,OAAO,YAAY;AAEtB,OACG,QAAQ,QAAQ,EAChB,YAAY,yBAAyB,EACrC,OAAO,UAAU,gBAAgB,EACjC,OAAO,aAAa;AAEvB,OACG,QAAQ,qBAAqB,EAC7B,YAAY,+BAA+B,EAC3C,OAAO,WAAW;AAErB,OACG,QAAQ,WAAW,EACnB,YAAY,eAAe,EAC3B,OAAO,WAAW,2BAA2B,EAC7C,OAAO,WAAW;AAErB,OACG,QAAQ,SAAS,EACjB,YAAY,qCAAqC,EACjD,OAAO,cAAc;AAExB,OACG,QAAQ,cAAc,EACtB,YAAY,6CAA6C,EACzD,OAAO,cAAc,eAAe,EACpC,OAAO,eAAe,2BAA2B,EACjD,OAAO,cAAc;AAExB,OACG,QAAQ,WAAW,EACnB,YAAY,uCAAuC,EACnD,OAAO,uBAAuB,kBAAkB,EAChD,OAAO,UAAU,gBAAgB,EACjC,OAAO,oBAAoB,kCAAkC,EAC7D,OAAO,WAAW,uCAAuC,EACzD,OAAO,WAAW;AAErB,OACG,QAAQ,MAAM,EACd,YAAY,sCAAsC,EAClD,OAAO,SAAS,uBAAuB,EACvC,OAAO,UAAU,8BAA8B,EAC/C,OAAO,UAAU,gBAAgB,EACjC,OAAO,oBAAoB,+CAA+C,EAC1E,OAAO,kBAAkB,+BAA+B,EACxD,OAAO,WAAW;AAErB,OACG,QAAQ,aAAa,EACrB,YAAY,iCAAiC,EAC7C,OAAO,YAAY,qCAAqC,EACxD,OAAO,sBAAsB,qBAAqB,EAClD,OAAO,aAAa;AAEvB,OACG,QAAQ,gCAAgC,EACxC,YAAY,iDAAiD,EAC7D,OAAO,UAAU,gBAAgB,EACjC,OAAO,CAAC,QAAQ,aAAa,YAAY;AACxC,gBAAY,UAAU,QAAQ,aAAa,KAAK,GAAG,GAAG,OAAO;AAAA,EAC/D,CAAC;AAEH,OACG,QAAQ,cAAc,EACtB,YAAY,wBAAwB,EACpC,OAAO,SAAS,iCAAiC,EACjD,OAAO,UAAU,gBAAgB,EACjC,OAAO,cAAc;AAExB,OACG,QAAQ,cAAc,EACtB,YAAY,4CAA4C,EACxD,OAAO,UAAU,gBAAgB,EACjC,OAAO,cAAc,qBAAqB,EAC1C,OAAO,SAAS;AAEnB,OACG,QAAQ,gCAAgC,EACxC,YAAY,8DAA8D,EAC1E,OAAO,UAAU,gBAAgB,EACjC,OAAO,CAAC,QAAQ,MAAM,MAAM,YAAY;AACvC,mBAAe,UAAU,QAAQ,MAAM,MAAM,OAAO;AAAA,EACtD,CAAC;AAEH,OACG,QAAQ,sBAAsB,EAC9B,YAAY,yDAAyD,EACrE,OAAO,UAAU,gBAAgB,EACjC,OAAO,wBAAwB,yBAAyB,IAAI,EAC5D,OAAO,CAAC,QAAQ,IAAI,YAAY;AAC/B,kBAAc,UAAU,QAAQ,IAAI;AAAA,MAClC,MAAM,QAAQ;AAAA,MACd,UAAU,SAAS,QAAQ,UAAU,EAAE;AAAA,IACzC,CAAC;AAAA,EACH,CAAC;AACL;;;AiB7HA;AACA,OAAOC,aAAW;AAClB,OAAOC,WAAS;AAChB,SAAS,cAAAC,cAAY,aAAAC,aAAW,iBAAAC,sBAAqB;AACrD,SAAS,QAAAC,QAAM,YAAAC,iBAAgB;;;ACJ/B;AAAA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,WAAAC,gBAAe;AASjB,SAAS,cAAc,UAAkC;AAC9D,QAAM,SAASF,UAAS,iCAAiC;AAAA,IACvD,KAAK;AAAA,IACL,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,YAA4B,CAAC;AACnC,MAAI,UAAiC,CAAC;AAEtC,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,KAAK,WAAW,WAAW,GAAG;AAChC,UAAI,QAAQ,KAAM,WAAU,KAAK,OAAuB;AACxD,gBAAU,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,UAAU,MAAM;AAAA,IACnD,WAAW,KAAK,WAAW,OAAO,GAAG;AACnC,cAAQ,OAAO,KAAK,MAAM,CAAC;AAAA,IAC7B,WAAW,KAAK,WAAW,SAAS,GAAG;AACrC,cAAQ,SAAS,KAAK,MAAM,CAAC,EAAE,QAAQ,eAAe,EAAE;AAAA,IAC1D,WAAW,SAAS,YAAY;AAC9B,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AACA,MAAI,QAAQ,KAAM,WAAU,KAAK,OAAuB;AAExD,SAAO;AACT;AAEO,SAAS,eACd,UACA,YACA,YACM;AAEN,EAAAC,WAAUC,SAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAGlD,MAAI;AACF,IAAAF,UAAS,4CAA4C,UAAU,IAAI;AAAA,MACjE,KAAK;AAAA,IACP,CAAC;AAED,IAAAA,UAAS,qBAAqB,UAAU,MAAM,UAAU,KAAK;AAAA,MAC3D,KAAK;AAAA,MACL,OAAO;AAAA,IACT,CAAC;AAAA,EACH,QAAQ;AAEN,IAAAA,UAAS,wBAAwB,UAAU,MAAM,UAAU,KAAK;AAAA,MAC9D,KAAK;AAAA,MACL,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAEO,SAAS,eAAe,UAAkB,cAA4B;AAC3E,EAAAA,UAAS,wBAAwB,YAAY,aAAa;AAAA,IACxD,KAAK;AAAA,IACL,OAAO;AAAA,EACT,CAAC;AACH;;;ACrEA;AAEA;AAFA,SAAS,gBAAAG,gBAAc,cAAAC,cAAY,eAAAC,oBAAmB;AACtD,SAAS,QAAAC,cAAY;AAed,SAAS,aAAa,cAA8B;AACzD,MAAI,CAACF,aAAW,YAAY,GAAG;AAC7B,UAAM,IAAI,MAAM,uBAAuB,YAAY,EAAE;AAAA,EACvD;AACA,SAAOD,eAAa,cAAc,MAAM;AAC1C;AAEO,SAAS,oBACd,UACA,WACQ;AACR,MAAI,SAAS;AAEb,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACpD,QAAI,UAAU,QAAW;AAEvB,eAAS,OAAO,QAAQ,IAAI,OAAO,SAAS,GAAG,UAAU,GAAG,GAAG,KAAK;AACpE,eAAS,OAAO,QAAQ,IAAI,OAAO,SAAS,GAAG,OAAO,GAAG,GAAG,KAAK;AAAA,IACnE;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iBACd,aACA,WACQ;AACR,QAAM,WAAqB,CAAC;AAG5B,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,aAAW,WAAW,cAAc;AAClC,UAAM,cAAcG,OAAK,qBAAqB,OAAO;AACrD,QAAIF,aAAW,WAAW,GAAG;AAC3B,YAAM,UAAU,aAAa,WAAW;AACxC,eAAS,KAAK,oBAAoB,SAAS,SAAS,CAAC;AAAA,IACvD;AAAA,EACF;AAGA,QAAM,kBAAkBE,OAAK,aAAa,eAAe,aAAa,UAAU;AAChF,MAAIF,aAAW,eAAe,GAAG;AAC/B,UAAM,eAAeC,aAAY,eAAe,EAC7C,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,EAC/B,KAAK;AAER,eAAW,QAAQ,cAAc;AAC/B,YAAM,UAAU,aAAaC,OAAK,iBAAiB,IAAI,CAAC;AACxD,eAAS,KAAK,oBAAoB,SAAS,SAAS,CAAC;AAAA,IACvD;AAAA,EACF;AAGA,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO,gBAAgB,UAAU,cAAc;AAAA;AAAA,aAEtC,UAAU,QAAQ;AAAA,cACjB,UAAU,WAAW;AAAA,YACvB,UAAU,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlC;AAEA,SAAO,SAAS,KAAK,aAAa;AACpC;;;AC1FA;AAWA;AAXA;AAAA,EACE,cAAAC;AAAA,EACA,eAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,EACA,kBAAAC;AAAA,OACK;AACP,SAAS,QAAAC,cAAY;AACrB,SAAS,YAAAC,iBAAgB;AAKzB,SAAS,oBAAoB,MAAc,UAAiC;AAC1E,MAAI;AACF,UAAM,OAAO,UAAU,IAAI;AAG3B,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,SAAS,aAAa,IAAI;AAChC,UAAI,OAAO,SAAS,aAAa,GAAG;AAClC,eAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI;AACF,MAAAA,UAAS,iCAAiC,IAAI,iBAAiB;AAAA,QAC7D,KAAK;AAAA,QACL,OAAO;AAAA,MACT,CAAC;AACD,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,yBAAyB,eAGvC;AACA,QAAM,eAAeD,OAAK,eAAe,WAAW,QAAQ;AAC5D,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAoB,CAAC;AAG3B,EAAAF,YAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAG3C,QAAM,iBAAiB,oBAAI,IAAY;AACvC,MAAIF,aAAW,YAAY,GAAG;AAC5B,eAAW,QAAQC,cAAY,YAAY,GAAG;AAC5C,qBAAe,IAAI,IAAI;AAAA,IACzB;AAAA,EACF;AAGA,MAAI,CAACD,aAAW,UAAU,EAAG,QAAO,EAAE,OAAO,QAAQ;AAErD,QAAM,mBAAmBC,cAAY,YAAY,EAAE,eAAe,KAAK,CAAC,EACrE,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7B,IAAI,CAAC,MAAM,EAAE,IAAI;AAEpB,aAAW,SAAS,kBAAkB;AACpC,UAAM,aAAaG,OAAK,cAAc,KAAK;AAC3C,UAAM,aAAaA,OAAK,YAAY,KAAK;AAGzC,QAAI,eAAe,IAAI,KAAK,GAAG;AAC7B,YAAM,SAAS,oBAAoB,YAAY,aAAa;AAC5D,UAAI,WAAW,eAAe;AAC5B,gBAAQ,KAAK,GAAG,KAAK,gBAAgB;AACrC;AAAA,MACF;AACA,UAAI,WAAW,cAAc;AAE3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI;AACF,kBAAY,YAAY,UAAU;AAClC,YAAM,KAAK,KAAK;AAAA,IAClB,SAAS,OAAY;AACnB,UAAI,MAAM,SAAS,UAAU;AAE3B,gBAAQ,KAAK,GAAG,KAAK,WAAW;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,SAAS,GAAG;AACpB,oBAAgB,cAAc,KAAK;AAAA,EACrC;AAEA,SAAO,EAAE,OAAO,QAAQ;AAC1B;AAEA,SAAS,gBAAgB,WAAmB,QAAwB;AAClE,QAAM,gBAAgBA,OAAK,WAAW,YAAY;AAElD,QAAM,UAAU;AAAA,EAChB,OAAO,KAAK,IAAI,CAAC;AAAA;AAGjB,MAAI;AACF,IAAAD,gBAAe,eAAe,OAAO;AAAA,EACvC,QAAQ;AAAA,EAER;AACF;;;AHvGO,SAAS,0BAA0BG,UAAwB;AAChE,QAAM,YAAYA,SAAQ,QAAQ,WAAW,EAAE,YAAY,sBAAsB;AAEjF,YACG,QAAQ,kBAAkB,EAC1B,YAAY,4BAA4B,EACxC,OAAO,aAAa,4BAA4B,EAChD,OAAO,eAAe,2BAA2B,EACjD,OAAO,qBAAqB,2DAA2D,EACvF,OAAO,oBAAoB,4CAA4C,EACvE,OAAO,aAAa;AAEvB,YACG,QAAQ,MAAM,EACd,YAAY,qBAAqB,EACjC,OAAO,UAAU,gBAAgB,EACjC,OAAO,SAAS,gDAAgD,EAChE,OAAOC,YAAW;AAErB,YACG,QAAQ,mBAAmB,EAC3B,YAAY,mBAAmB,EAC/B,OAAO,WAAW,6CAA6C,EAC/D,OAAO,oBAAoB,4CAA4C,EACvE,OAAO,cAAc;AAC1B;AASA,eAAe,cAAc,SAAiB,SAAuC;AACnF,QAAM,UAAUC,MAAI,uBAAuB,EAAE,MAAM;AAEnD,MAAI;AAEF,UAAM,eAAe,QAAQ,YAAY,EAAE,QAAQ,eAAe,GAAG;AACrE,UAAM,aAAa,WAAW,YAAY;AAC1C,UAAM,aAAa,WAAW,YAAY;AAG1C,UAAM,SAAS,QAAQ,SACnB,QAAQ,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAC7C,CAAC;AAGL,QAAI;AACJ,QAAI;AAEJ,QAAI,QAAQ,SAAS;AAEnB,oBAAc,QAAQ;AAAA,IACxB,OAAO;AAEL,YAAM,WAAW,wBAAwB,SAAS,MAAM;AACxD,UAAI,UAAU;AACZ,sBAAc,SAAS;AACvB,sBAAc,SAAS;AACvB,gBAAQ,OAAO,qBAAqB,WAAW,KAAK,WAAW;AAAA,MACjE,WAAW,YAAY,GAAG;AAExB,gBAAQ,KAAK,wBAAwB,OAAO,wCAAwC;AACpF,gBAAQ,MAAM,uBAAuB;AACrC,sBAAc,QAAQ,IAAI;AAAA,MAC5B,OAAO;AAEL,sBAAc,QAAQ,IAAI;AAAA,MAC5B;AAAA,IACF;AAEA,UAAM,gBAAgBC,OAAK,aAAa,YAAY;AACpD,UAAM,gBAAgBA,OAAK,eAAe,UAAU;AAEpD,QAAI,QAAQ,QAAQ;AAClB,cAAQ,KAAK,cAAc;AAC3B,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIC,QAAM,KAAK,eAAe,CAAC;AACvC,UAAI,aAAa;AACf,gBAAQ,IAAI,gBAAgBA,QAAM,MAAM,WAAW,CAAC,EAAE;AAAA,MACxD;AACA,cAAQ,IAAI,gBAAgBA,QAAM,IAAI,WAAW,CAAC,EAAE;AACpD,cAAQ,IAAI,gBAAgBA,QAAM,KAAK,aAAa,CAAC,EAAE;AACvD,cAAQ,IAAI,gBAAgBA,QAAM,KAAK,UAAU,CAAC,EAAE;AACpD,cAAQ,IAAI,gBAAgBA,QAAM,IAAID,OAAK,eAAe,WAAW,CAAC,CAAC,EAAE;AACzE,UAAI,QAAQ,WAAW,OAAO;AAC5B,gBAAQ,IAAI,gBAAgBC,QAAM,IAAID,OAAK,eAAe,WAAW,QAAQ,CAAC,CAAC,EAAE;AAAA,MACnF;AACA;AAAA,IACF;AAGA,QAAIE,aAAW,aAAa,GAAG;AAC7B,cAAQ,KAAK,6BAA6B,aAAa,EAAE;AACzD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,CAACA,aAAWF,OAAK,aAAa,MAAM,CAAC,GAAG;AAC1C,cAAQ,KAAK,uDAAuD;AACpE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,YAAQ,OAAO;AACf,mBAAe,aAAa,eAAe,UAAU;AAGrD,YAAQ,OAAO;AACf,UAAM,YAA+B;AAAA,MACnC,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,UAAU,QAAQ,YAAY;AAAA,MAC9B,gBAAgB;AAAA,MAChB,cAAc,WAAW,UAAU;AAAA,MACnC,SAAS,eAAe,UAAU;AAAA,MAClC,cAAc;AAAA,IAChB;AAEA,UAAM,WAAW,iBAAiB,aAAa,SAAS;AACxD,IAAAG,eAAcH,OAAK,eAAe,WAAW,GAAG,QAAQ;AAGxD,QAAI,eAAe,EAAE,OAAO,CAAC,GAAe,SAAS,CAAC,EAAc;AACpE,QAAI,QAAQ,WAAW,OAAO;AAC5B,cAAQ,OAAO;AACf,MAAAI,YAAUJ,OAAK,eAAe,WAAW,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACvE,qBAAe,yBAAyB,aAAa;AAAA,IACvD;AAEA,YAAQ,QAAQ,oBAAoB;AAEpC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIC,QAAM,KAAK,oBAAoB,CAAC;AAC5C,QAAI,aAAa;AACf,cAAQ,IAAI,cAAcA,QAAM,MAAM,WAAW,CAAC,EAAE;AAAA,IACtD;AACA,YAAQ,IAAI,aAAaA,QAAM,KAAK,aAAa,CAAC,EAAE;AACpD,YAAQ,IAAI,aAAaA,QAAM,IAAI,UAAU,CAAC,EAAE;AAChD,YAAQ,IAAI,EAAE;AAEd,QAAI,QAAQ,WAAW,OAAO;AAC5B,cAAQ,IAAIA,QAAM,KAAK,SAAS,CAAC;AACjC,cAAQ,IAAI,cAAc,aAAa,MAAM,MAAM,oBAAoB;AACvE,UAAI,aAAa,QAAQ,SAAS,GAAG;AACnC,gBAAQ,IAAI,cAAcA,QAAM,IAAI,aAAa,QAAQ,KAAK,IAAI,CAAC,CAAC,EAAE;AAAA,MACxE;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,YAAQ,IAAIA,QAAM,IAAI,YAAY,aAAa,EAAE,CAAC;AAAA,EAEpD,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAOA,eAAeH,aAAY,SAAqC;AAC9D,QAAM,EAAE,cAAAO,cAAa,IAAI,MAAM,OAAO,yBAAuB;AAC7D,QAAM,WAAWA,cAAa;AAG9B,MAAI,SAAS,SAAS,KAAK,QAAQ,KAAK;AACtC,UAAM,gBAID,CAAC;AAEN,eAAW,EAAE,KAAK,OAAO,KAAK,UAAU;AACtC,UAAI,CAACH,aAAWF,OAAK,OAAO,MAAM,MAAM,CAAC,GAAG;AAC1C;AAAA,MACF;AAEA,YAAMM,aAAY,cAAc,OAAO,IAAI;AAC3C,YAAMC,cAAaD,WAAU;AAAA,QAC3B,CAAC,MAAM,EAAE,KAAK,SAAS,cAAc,KAAK,EAAE,KAAK,SAAS,gBAAgB;AAAA,MAC5E;AAEA,UAAIC,YAAW,SAAS,GAAG;AACzB,sBAAc,KAAK;AAAA,UACjB,aAAa,OAAO;AAAA,UACpB,aAAa,OAAO;AAAA,UACpB,YAAAA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,eAAe,MAAM,CAAC,CAAC;AAClD;AAAA,IACF;AAEA,QAAI,cAAc,WAAW,GAAG;AAC9B,cAAQ,IAAIN,QAAM,IAAI,gDAAgD,CAAC;AACvE,cAAQ,IAAIA,QAAM,IAAI,kDAAkD,CAAC;AACzE;AAAA,IACF;AAEA,eAAW,QAAQ,eAAe;AAChC,cAAQ,IAAIA,QAAM,KAAK;AAAA,EAAK,KAAK,WAAW;AAAA,CAAI,CAAC;AACjD,iBAAW,MAAM,KAAK,YAAY;AAChC,cAAM,OAAOO,UAAS,GAAG,IAAI;AAC7B,cAAM,SAAS,GAAG,WAAWP,QAAM,OAAO,aAAa,IAAI;AAC3D,gBAAQ,IAAI,KAAKA,QAAM,KAAK,IAAI,CAAC,GAAG,MAAM,EAAE;AAC5C,gBAAQ,IAAI,eAAe,GAAG,UAAUA,QAAM,IAAI,YAAY,CAAC,EAAE;AACjE,gBAAQ,IAAI,eAAeA,QAAM,IAAI,GAAG,IAAI,CAAC,EAAE;AAAA,MACjD;AAAA,IACF;AACA;AAAA,EACF;AAGA,QAAM,cAAc,QAAQ,IAAI;AAGhC,MAAI,CAACC,aAAWF,OAAK,aAAa,MAAM,CAAC,GAAG;AAC1C,YAAQ,MAAMC,QAAM,IAAI,uBAAuB,CAAC;AAChD,QAAI,SAAS,SAAS,GAAG;AACvB,cAAQ,IAAIA,QAAM,IAAI,mEAAmE,CAAC;AAAA,IAC5F;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,cAAc,WAAW;AAG3C,QAAM,aAAa,UAAU;AAAA,IAAO,CAAC,MACnC,EAAE,KAAK,SAAS,cAAc,KAAK,EAAE,KAAK,SAAS,gBAAgB;AAAA,EACrE;AAEA,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAC/C;AAAA,EACF;AAEA,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,IAAIA,QAAM,IAAI,sBAAsB,CAAC;AAC7C,YAAQ,IAAIA,QAAM,IAAI,kDAAkD,CAAC;AACzE,QAAI,SAAS,SAAS,GAAG;AACvB,cAAQ,IAAIA,QAAM,IAAI,mEAAmE,CAAC;AAAA,IAC5F;AACA;AAAA,EACF;AAEA,UAAQ,IAAIA,QAAM,KAAK,gBAAgB,CAAC;AAExC,aAAW,MAAM,YAAY;AAC3B,UAAM,OAAOO,UAAS,GAAG,IAAI;AAC7B,UAAM,SAAS,GAAG,WAAWP,QAAM,OAAO,aAAa,IAAI;AAC3D,YAAQ,IAAI,GAAGA,QAAM,KAAK,IAAI,CAAC,GAAG,MAAM,EAAE;AAC1C,YAAQ,IAAI,aAAa,GAAG,UAAUA,QAAM,IAAI,YAAY,CAAC,EAAE;AAC/D,YAAQ,IAAI,aAAaA,QAAM,IAAI,GAAG,IAAI,CAAC,EAAE;AAC7C,YAAQ,IAAI,EAAE;AAAA,EAChB;AACF;AAOA,eAAe,eAAe,SAAiB,SAAwC;AACrF,QAAM,UAAUF,MAAI,yBAAyB,EAAE,MAAM;AAErD,MAAI;AACF,UAAM,eAAe,QAAQ,YAAY,EAAE,QAAQ,eAAe,GAAG;AACrE,UAAM,aAAa,WAAW,YAAY;AAG1C,QAAI;AAEJ,QAAI,QAAQ,SAAS;AACnB,oBAAc,QAAQ;AAAA,IACxB,OAAO;AAEL,YAAM,WAAW,wBAAwB,OAAO;AAChD,UAAI,UAAU;AACZ,sBAAc,SAAS;AAAA,MACzB,OAAO;AACL,sBAAc,QAAQ,IAAI;AAAA,MAC5B;AAAA,IACF;AAEA,UAAM,gBAAgBC,OAAK,aAAa,cAAc,UAAU;AAEhE,QAAI,CAACE,aAAW,aAAa,GAAG;AAE9B,YAAM,UAAUF,OAAK,QAAQ,IAAI,GAAG,cAAc,UAAU;AAC5D,UAAI,gBAAgB,QAAQ,IAAI,KAAKE,aAAW,OAAO,GAAG;AACxD,sBAAc,QAAQ,IAAI;AAAA,MAC5B,OAAO;AACL,gBAAQ,KAAK,wBAAwB,aAAa,EAAE;AACpD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAEA,UAAM,qBAAqBF,OAAK,aAAa,cAAc,UAAU;AAErE,YAAQ,OAAO;AACf,mBAAe,aAAa,kBAAkB;AAE9C,YAAQ,QAAQ,wBAAwB,UAAU,EAAE;AAAA,EACtD,SAAS,OAAY;AACnB,YAAQ,KAAK,MAAM,OAAO;AAC1B,QAAI,CAAC,QAAQ,OAAO;AAClB,cAAQ,IAAIC,QAAM,IAAI,0DAA0D,CAAC;AAAA,IACnF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AI5UA;AAOA;AANA,OAAOQ,aAAW;AAClB,OAAOC,WAAS;AAChB,SAAS,YAAAC,iBAAgB;AACzB,SAAS,cAAAC,cAAY,aAAAC,aAA0B,gBAAAC,gBAAc,cAAc,eAAAC,eAAa,gBAAgB;AACxG,SAAS,QAAAC,cAAY;AACrB,SAAS,WAAAC,UAAS,gBAAgB;AAY3B,SAAS,uBAAuBC,UAAwB;AAC7D,EAAAA,SACG,QAAQ,SAAS,EACjB,YAAY,kCAAkC,EAC9C,OAAO,WAAW,0BAA0B,EAC5C,OAAO,aAAa,kDAAkD,EACtE,OAAO,iBAAiB,yBAAyB,EACjD,OAAO,iBAAiB,2BAA2B,EACnD,OAAO,cAAc;AAC1B;AAgBA,SAAS,iBAAuD;AAC9D,QAAM,KAAK,SAAS;AACpB,MAAI,OAAO,SAAS;AAElB,QAAI;AACF,YAAM,UAAUC,eAAa,iBAAiB,MAAM,EAAE,YAAY;AAClE,UAAI,QAAQ,SAAS,WAAW,KAAK,QAAQ,SAAS,KAAK,GAAG;AAC5D,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAAC;AACT,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKA,SAAS,uBAAuB,QAAgB,MAAoB;AAClE,MAAI,CAACC,aAAW,MAAM,GAAG;AACvB,UAAM,IAAI,MAAM,+BAA+B,MAAM,EAAE;AAAA,EACzD;AAEA,EAAAC,YAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AAEnC,QAAM,UAAUC,cAAY,MAAM;AAClC,aAAW,SAAS,SAAS;AAC3B,UAAM,aAAaC,OAAK,QAAQ,KAAK;AACrC,UAAM,WAAWA,OAAK,MAAM,KAAK;AACjC,UAAM,OAAO,SAAS,UAAU;AAEhC,QAAI,KAAK,YAAY,GAAG;AACtB,6BAAuB,YAAY,QAAQ;AAAA,IAC7C,OAAO;AACL,mBAAa,YAAY,QAAQ;AAAA,IACnC;AAAA,EACF;AACF;AAEA,SAAS,aAAa,KAAsB;AAC1C,MAAI;AACF,IAAAC,UAAS,SAAS,GAAG,IAAI,EAAE,OAAO,OAAO,CAAC;AAC1C,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAsE;AAC7E,QAAM,UAA0B,CAAC;AAGjC,QAAM,cAAc,QAAQ;AAC5B,QAAM,YAAY,SAAS,YAAY,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;AAC7D,UAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,aAAa;AAAA,IACrB,SAAS,aAAa,KAAK,IAAI,WAAW,KAAK,IAAI,WAAW;AAAA,IAC9D,KAAK;AAAA,EACP,CAAC;AAGD,QAAM,SAAS,aAAa,KAAK;AACjC,UAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,SAAS,cAAc;AAAA,IAChC,KAAK;AAAA,EACP,CAAC;AAGD,QAAM,YAAY,aAAa,QAAQ;AACvC,MAAI,gBAAgB;AACpB,MAAI,WAAW;AACb,QAAI;AACF,MAAAA,UAAS,eAAe,EAAE,OAAO,OAAO,CAAC;AACzC,sBAAgB;AAAA,IAClB,QAAQ;AAAA,IAAC;AAAA,EACX;AACA,UAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,gBAAgB,YAAY,YAAY,gBAAgB;AAAA,IACjE,KAAK,YAAY,2CAA2C;AAAA,EAC9D,CAAC;AAGD,QAAM,UAAU,aAAa,MAAM;AACnC,UAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,UAAU,cAAc;AAAA,IACjC,KAAK;AAAA,EACP,CAAC;AAGD,QAAM,YAAY,aAAa,QAAQ;AACvC,UAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,YAAY,cAAc;AAAA,IACnC,KAAK;AAAA,EACP,CAAC;AAGD,QAAM,WAAW,aAAa,IAAI;AAClC,UAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,WAAW,cAAc;AAAA,IAClC,KAAK;AAAA,EACP,CAAC;AAGD,QAAM,UAAU,aAAa,MAAM,KAAKJ,aAAWG,OAAKE,SAAQ,GAAG,OAAO,MAAM,CAAC;AACjF,UAAQ,KAAK;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,UAAU,cAAc;AAAA,IACjC,KAAK;AAAA,EACP,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA,WAAW,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM;AAAA,EAClG;AACF;AAEA,SAAS,kBAAkB,SAAgE;AACzF,UAAQ,IAAIC,QAAM,KAAK,kBAAkB,CAAC;AAE1C,aAAW,UAAU,QAAQ,SAAS;AACpC,UAAM,OAAO,OAAO,SAASA,QAAM,MAAM,QAAG,IAAIA,QAAM,IAAI,QAAG;AAC7D,UAAM,MAAM,OAAO,SAASA,QAAM,IAAI,OAAO,OAAO,IAAIA,QAAM,OAAO,OAAO,OAAO;AACnF,YAAQ,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,GAAG,EAAE;AAC9C,QAAI,CAAC,OAAO,UAAU,OAAO,KAAK;AAChC,cAAQ,IAAI,OAAOA,QAAM,IAAI,YAAO,OAAO,GAAG,CAAC,EAAE;AAAA,IACnD;AAAA,EACF;AACA,UAAQ,IAAI,EAAE;AAChB;AAEA,eAAe,eAAe,SAAwC;AACpE,UAAQ,IAAIA,QAAM,KAAK,6BAA6B,CAAC;AAErD,QAAM,OAAO,eAAe;AAC5B,UAAQ,IAAI,aAAaA,QAAM,KAAK,IAAI,CAAC;AAAA,CAAI;AAG7C,QAAM,UAAU,mBAAmB;AAEnC,MAAI,QAAQ,OAAO;AACjB,sBAAkB,OAAO;AACzB,YAAQ,KAAK,QAAQ,YAAY,IAAI,CAAC;AAAA,EACxC;AAEA,oBAAkB,OAAO;AAEzB,MAAI,CAAC,QAAQ,WAAW;AACtB,YAAQ,IAAIA,QAAM,IAAI,4CAA4C,CAAC;AACnE,YAAQ,IAAIA,QAAM,IAAI,qDAAqD,CAAC;AAC5E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,UAAUC,MAAI,wCAAwC,EAAE,MAAM;AACpE,aAAW,OAAO,WAAW;AAC3B,IAAAN,YAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACpC;AACA,UAAQ,QAAQ,yBAAyB;AAGzC,MAAI,CAAC,QAAQ,YAAY;AACvB,YAAQ,MAAM,4BAA4B;AAC1C,QAAI;AACF,MAAAG,UAAS,wDAAwD,EAAE,OAAO,OAAO,CAAC;AAClF,cAAQ,QAAQ,sBAAsB;AAAA,IACxC,SAAS,OAAO;AACd,cAAQ,KAAK,iDAAiD;AAAA,IAChE;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,cAAc,CAAC,QAAQ,SAAS;AAC3C,UAAM,YAAY,aAAa,QAAQ;AACvC,QAAI,WAAW;AACb,cAAQ,MAAM,yBAAyB;AACvC,UAAI;AACF,QAAAA,UAAS,mBAAmB,EAAE,OAAO,OAAO,CAAC;AAC7C,gBAAQ,QAAQ,qBAAqB;AAGrC,gBAAQ,MAAM,qCAAqC;AACnD,cAAM,kBAAkBD,OAAK,mBAAmB,6BAA6B;AAC7E,cAAM,iBAAiBA,OAAK,mBAAmB,iCAAiC;AAEhF,QAAAC;AAAA,UACE,sBAAsB,eAAe,gBAAgB,cAAc;AAAA,UACnE,EAAE,OAAO,OAAO;AAAA,QAClB;AAGA,cAAM,iBAAiBD,OAAK,WAAW,eAAe;AACtD,cAAM,gBAAgBA,OAAK,WAAW,mBAAmB;AACzD,qBAAa,iBAAiB,cAAc;AAC5C,qBAAa,gBAAgB,aAAa;AAE1C,gBAAQ,QAAQ,gEAAgE;AAAA,MAClF,SAAS,OAAO;AACd,gBAAQ,KAAK,0CAA0C;AAAA,MACzD;AAAA,IACF,OAAO;AACL,cAAQ,KAAK,iCAAiC;AAAA,IAChD;AAAA,EACF;AAGA,QAAM,UAAU,aAAa,MAAM,KAAKH,aAAWG,OAAKE,SAAQ,GAAG,OAAO,MAAM,CAAC;AACjF,MAAI,CAAC,SAAS;AACZ,YAAQ,MAAM,mCAAmC;AACjD,QAAI;AACF,YAAM,SAASF,OAAKE,SAAQ,GAAG,KAAK;AACpC,MAAAJ,YAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,YAAM,WAAWE,OAAK,QAAQ,MAAM;AAGpC,YAAMK,QAAO,eAAe;AAC5B,UAAI,cAAc;AAClB,UAAIA,UAAS,UAAU;AAErB,YAAI;AACF,UAAAJ,UAAS,qBAAqB,EAAE,OAAO,OAAO,CAAC;AAC/C,kBAAQ,QAAQ,6BAA6B;AAAA,QAC/C,QAAQ;AACN,kBAAQ,KAAK,gEAAgE;AAAA,QAC/E;AAAA,MACF,OAAO;AAEL,sBAAc;AACd,YAAI;AACF,UAAAA,UAAS,aAAa,WAAW,SAAS,QAAQ,kBAAkB,QAAQ,KAAK;AAAA,YAC/E,OAAO;AAAA,YACP,SAAS;AAAA,UACX,CAAC;AACD,kBAAQ,QAAQ,qBAAqB,QAAQ,EAAE;AAAA,QACjD,SAAS,OAAO;AACd,kBAAQ,KAAK,uFAAuF;AAAA,QACtG;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,4DAA4D;AAAA,IAC3E;AAAA,EACF,OAAO;AACL,YAAQ,KAAK,wBAAwB;AAAA,EACvC;AAGA,MAAI,CAAC,QAAQ,SAAS;AACpB,YAAQ,MAAM,qCAAqC;AAEnD,QAAI;AAGF,UAAI,CAACJ,aAAWG,OAAK,aAAa,oBAAoB,CAAC,GAAG;AACxD,+BAAuB,0BAA0B,WAAW;AAC5D,gBAAQ,QAAQ,8CAA8C;AAAA,MAChE,OAAO;AACL,gBAAQ,KAAK,iDAAiD;AAAA,MAChE;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,2CAA2C,KAAK,EAAE;AAC/D,cAAQ,IAAIG,QAAM,OAAO,uCAAuC,CAAC;AAAA,IACnE;AAAA,EACF;AAGA,QAAM,aAAaH,OAAK,iBAAiB,aAAa;AACtD,MAAI,CAACH,aAAW,UAAU,GAAG;AAC3B,YAAQ,MAAM,4BAA4B;AAG1C,UAAM,SAAS,iBAAiB;AAGhC,QAAI,QAAQ,SAAS;AACnB,aAAO,UAAU;AAAA,QACf,SAAS;AAAA,MACX;AAAA,IACF,OAAO;AACL,aAAO,UAAU;AAAA,QACf,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,eAAW,MAAM;AACjB,YAAQ,QAAQ,gBAAgB;AAAA,EAClC;AAGA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIM,QAAM,MAAM,KAAK,wBAAwB,CAAC;AACtD,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,QAAM,KAAK,aAAa,CAAC;AACrC,UAAQ,IAAI,YAAYA,QAAM,KAAK,UAAU,CAAC,+BAA+B;AAE7E,MAAI,CAAC,QAAQ,SAAS;AACpB,YAAQ,IAAI,eAAeA,QAAM,OAAO,YAAY,CAAC,KAAKA,QAAM,KAAK,yBAAyB,CAAC,EAAE;AACjG,YAAQ,IAAI,YAAYA,QAAM,KAAK,QAAQ,CAAC,iCAAiC;AAC7E,YAAQ,IAAI,4BAA4BA,QAAM,KAAK,uBAAuB,CAAC,EAAE;AAAA,EAC/E,OAAO;AACL,YAAQ,IAAI,YAAYA,QAAM,KAAK,QAAQ,CAAC,yBAAyB;AACrE,YAAQ,IAAI,4BAA4BA,QAAM,KAAK,uBAAuB,CAAC,EAAE;AAAA,EAC/E;AAEA,UAAQ,IAAI,KAAK,CAAC,QAAQ,UAAU,MAAM,GAAG,6BAA6BA,QAAM,KAAK,iCAAiC,CAAC,EAAE;AACzH,UAAQ,IAAI,EAAE;AAChB;;;ACzWA;;;ACAA;AAMA,OAAOG,aAAW;;;ACNlB;;;ACAA;AASA;AAHA,SAAS,gBAAAC,gBAAc,iBAAAC,iBAAe,cAAAC,cAAY,aAAAC,mBAAiB;AACnE,SAAS,OAAO,iBAAiB;AACjC,SAAS,QAAAC,cAAY;AAGrB,IAAM,uBAAuBA,OAAK,iBAAiB,eAAe;AA2I3D,IAAM,0BAA0C;AAAA,EACrD,SAAS;AAAA,IACP,YAAY;AAAA,EACd;AAAA,EACA,YAAY;AAAA,IACV,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AAAA,EACA,cAAc;AAAA,IACZ,iBAAiB;AAAA,IACjB,eAAe;AAAA;AAAA,IACf,iBAAiB;AAAA,EACnB;AAAA,EACA,YAAY;AAAA,IACV,gBAAgB;AAAA;AAAA,IAChB,mBAAmB,CAAC,eAAe,iBAAiB,cAAc;AAAA,EACpE;AAAA,EACA,eAAe;AAAA,IACb,eAAe;AAAA,IACf,OAAO;AAAA,EACT;AAAA,EACA,aAAa;AAAA,IACX,aAAa;AAAA,MACX,SAAS;AAAA,MACT,WAAW;AAAA;AAAA,IACb;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,WAAW;AAAA;AAAA,IACb;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA;AAAA,MACT,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,eAAe;AAAA,IACf,oBAAoB;AAAA,MAClB,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,mBAAmB;AAAA,MACjB,aAAa;AAAA,MACb,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR,eAAe;AAAA,MACb,mBAAmB;AAAA,QACjB,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,UAAU;AAAA,MACZ;AAAA,MACA,kBAAkB;AAAA,QAChB,SAAS;AAAA,QACT,yBAAyB;AAAA,QACzB,wBAAwB;AAAA,MAC1B;AAAA,MACA,cAAc;AAAA,QACZ,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA,MACA,yBAAyB;AAAA,QACvB,SAAS;AAAA;AAAA,QACT,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AACF;AAQA,SAAS,UAA4B,UAAa,WAA0B;AAC1E,QAAM,SAAS,EAAE,GAAG,SAAS;AAE7B,aAAW,OAAO,OAAO,KAAK,SAAS,GAAkB;AACvD,UAAM,aAAa,SAAS,GAAG;AAC/B,UAAM,cAAc,UAAU,GAAG;AAGjC,QAAI,gBAAgB,OAAW;AAG/B,QACE,OAAO,eAAe,YACtB,eAAe,QACf,CAAC,MAAM,QAAQ,UAAU,KACzB,OAAO,gBAAgB,YACvB,gBAAgB,QAChB,CAAC,MAAM,QAAQ,WAAW,GAC1B;AACA,aAAO,GAAG,IAAI,UAAU,YAAmB,WAAkB;AAAA,IAC/D,OAAO;AAEL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAQO,SAAS,qBAAqC;AAEnD,MAAI,CAACF,aAAW,eAAe,GAAG;AAChC,IAAAC,YAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AAGA,MAAI,CAACD,aAAW,oBAAoB,GAAG;AACrC,uBAAmB,uBAAuB;AAC1C,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAUF,eAAa,sBAAsB,OAAO;AAC1D,UAAM,SAAS,MAAM,OAAO;AAG5B,WAAO,UAAU,yBAAyB,MAAM;AAAA,EAClD,SAAS,OAAO;AACd,YAAQ,MAAM,mCAAmC,KAAK;AACtD,YAAQ,MAAM,6BAA6B;AAC3C,WAAO;AAAA,EACT;AACF;AAOO,SAAS,mBAAmB,QAA8B;AAE/D,MAAI,CAACE,aAAW,eAAe,GAAG;AAChC,IAAAC,YAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AAEA,MAAI;AACF,UAAM,UAAU,UAAU,MAAa;AACvC,IAAAF,gBAAc,sBAAsB,SAAS,OAAO;AAAA,EACtD,SAAS,OAAO;AACd,YAAQ,MAAM,mCAAmC,KAAK;AACtD,UAAM;AAAA,EACR;AACF;AAgCO,SAAS,wBAId;AACA,QAAM,SAAS,mBAAmB;AAClC,SAAO;AAAA,IACL,OAAO,OAAO,WAAW,QAAQ,KAAK;AAAA,IACtC,SAAS,OAAO,WAAW,UAAU,KAAK;AAAA,IAC1C,OAAO,OAAO,WAAW,QAAQ,KAAK;AAAA,EACxC;AACF;;;ACvWA;AAwCO,SAAS,oBACd,qBACA,YACa;AACb,MAAI,sBAAsB,WAAW,OAAO;AAC1C,WAAO;AAAA,EACT,WAAW,sBAAsB,WAAW,SAAS;AACnD,WAAO;AAAA,EACT,WAAW,sBAAsB,WAAW,OAAO;AACjD,WAAO;AAAA,EACT,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAUO,SAASI,gBACd,SACA,SACA,YACa;AACb,QAAM,eAAe,cAAc,sBAAsB;AAGzD,QAAMC,aAAY,QAAQ,UAAU,OAAO;AAE3C,MAAI,CAACA,YAAW;AACd,WAAO;AAAA,MACL;AAAA,MACA,OAAO;AAAA,MACP,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,aAAa,OAAO;AAE9C,MAAI,CAAC,WAAW;AAEd,WAAO;AAAA,MACL;AAAA,MACA,OAAO;AAAA;AAAA,MACP,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,EACF;AAGA,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,oBAAoB,IAAI,QAAQ,IAAI,UAAU,UAAU,QAAQ;AAGtE,QAAM,QAAQ,oBAAoB,mBAAmB,YAAY;AAEjE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,cAAc,UAAU;AAAA,IACxB;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAwBO,SAAS,sBAAsB,cAA4C;AAChF,QAAM,UAAyB;AAAA,IAC7B,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,IACP,OAAO,aAAa;AAAA,EACtB;AAEA,aAAW,UAAU,cAAc;AACjC,YAAQ,OAAO,KAAK;AAAA,EACtB;AAEA,SAAO;AACT;AAQO,SAAS,eAAe,QAA8B;AAC3D,SAAO,OAAO,UAAU,aAAa,OAAO,UAAU;AACxD;AA4BO,SAAS,0BAA0B,cAA4C;AACpF,SAAO,aAAa,OAAO,cAAc;AAC3C;AAuDO,SAAS,eAAe,OAA4B;AACzD,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAQO,SAAS,eAAe,OAA4B;AACzD,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;;;ACrRA;AAUA;AAHA,OAAO,cAAc;AACrB,SAAS,QAAAC,cAAY;AACrB,SAAS,cAAAC,cAAY,aAAAC,mBAAiB;AAItC,IAAM,mBAAmBF,OAAK,iBAAiB,aAAa;AAC5D,IAAM,iBAAiB;AAsBvB,IAAI,KAA+B;AAQ5B,SAAS,qBAAwC;AAEtD,MAAI,CAACC,aAAW,eAAe,GAAG;AAChC,IAAAC,YAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AAGA,OAAK,IAAI,SAAS,gBAAgB;AAGlC,KAAG,OAAO,oBAAoB;AAG9B,KAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAgBP;AAGD,mBAAiB,EAAE;AAEnB,SAAO;AACT;AAKO,SAAS,oBAAuC;AACrD,MAAI,CAAC,IAAI;AACP,WAAO,mBAAmB;AAAA,EAC5B;AACA,SAAO;AACT;AAKO,SAAS,sBAA4B;AAC1C,MAAI,IAAI;AACN,OAAG,MAAM;AACT,SAAK;AAAA,EACP;AACF;AAQO,SAAS,iBAAiB,OAAwC;AACvE,QAAM,WAAW,kBAAkB;AAEnC,QAAM,OAAO,SAAS,QAAQ;AAAA;AAAA;AAAA,GAG7B;AAED,QAAM,SAAS,KAAK;AAAA,IAClB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM,iBAAiB;AAAA,IACvB,MAAM,UAAU;AAAA,IAChB,MAAM,YAAY;AAAA,EACpB;AAEA,SAAO,OAAO;AAChB;AAuLO,SAAS,iBACd,WAA8B,kBAAkB,GAChD,gBAAwB,gBAChB;AACR,QAAM,aAAa,oBAAI,KAAK;AAC5B,aAAW,QAAQ,WAAW,QAAQ,IAAI,aAAa;AACvD,QAAM,kBAAkB,WAAW,YAAY;AAE/C,QAAM,OAAO,SAAS,QAAQ;AAAA;AAAA;AAAA,GAG7B;AAED,QAAM,SAAS,KAAK,IAAI,eAAe;AACvC,SAAO,OAAO;AAChB;;;ACnUA;AAUA;AAHA,SAAS,gBAAAC,gBAAc,iBAAAC,iBAAe,cAAAC,cAAY,aAAAC,aAAW,eAAAC,eAAa,cAAAC,mBAAkB;AAC5F,SAAS,QAAAC,QAAM,YAAAC,iBAAgB;AAC/B,SAAS,YAAAC,iBAAgB;;;ACTzB;AAOA,SAAS,cAAAC,cAAY,gBAAAC,gBAAc,eAAAC,eAAa,YAAAC,iBAAgB;AAChE,SAAS,QAAAC,QAAM,YAAAC,iBAAgB;AAC/B,SAAS,WAAAC,gBAAe;;;ACTxB;AASA;AADA,SAAS,QAAAC,cAAY;AAuEd,IAAM,kBAAkC;AAAA;AAAA,EAE7C,EAAE,UAAU,aAAa,OAAO,iBAAiB,YAAY,OAAO,aAAa,OAAO,gBAAgB,QAAS,iBAAiB,SAAS,UAAU,MAAM;AAAA,EAC3J,EAAE,UAAU,aAAa,OAAO,mBAAmB,YAAY,MAAO,aAAa,OAAO,gBAAgB,MAAQ,iBAAiB,QAAS,UAAU,MAAM;AAAA,EAC5J,EAAE,UAAU,aAAa,OAAO,oBAAoB,YAAY,MAAQ,aAAa,MAAO,gBAAgB,MAAS,iBAAiB,MAAO,UAAU,MAAM;AAAA;AAAA,EAE7J,EAAE,UAAU,UAAU,OAAO,eAAe,YAAY,MAAM,aAAa,MAAM,UAAU,MAAM;AAAA,EACjG,EAAE,UAAU,UAAU,OAAO,UAAU,YAAY,MAAO,aAAa,OAAO,UAAU,MAAM;AAAA,EAC9F,EAAE,UAAU,UAAU,OAAO,eAAe,YAAY,OAAS,aAAa,MAAQ,UAAU,MAAM;AAAA;AAAA,EAEtG,EAAE,UAAU,UAAU,OAAO,kBAAkB,YAAY,QAAS,aAAa,MAAO,UAAU,MAAM;AAAA,EACxG,EAAE,UAAU,UAAU,OAAO,oBAAoB,YAAY,OAAU,aAAa,MAAQ,UAAU,MAAM;AAC9G;AAOO,SAAS,cAAc,OAAmB,SAA+B;AAC9E,MAAI,OAAO;AAGX,UAAS,MAAM,cAAc,MAAQ,QAAQ;AAG7C,UAAS,MAAM,eAAe,MAAQ,QAAQ;AAG9C,MAAI,MAAM,mBAAmB,QAAQ,gBAAgB;AACnD,YAAS,MAAM,kBAAkB,MAAQ,QAAQ;AAAA,EACnD;AACA,MAAI,MAAM,oBAAoB,QAAQ,iBAAiB;AACrD,YAAS,MAAM,mBAAmB,MAAQ,QAAQ;AAAA,EACpD;AAEA,SAAO,KAAK,MAAM,OAAO,GAAO,IAAI;AACtC;AAKO,SAAS,WAAW,UAAsB,OAAoC;AAEnF,MAAI,UAAU,gBAAgB;AAAA,IAC5B,OAAK,EAAE,aAAa,YAAY,EAAE,UAAU;AAAA,EAC9C;AAEA,MAAI,CAAC,SAAS;AAEZ,cAAU,gBAAgB;AAAA,MACxB,OAAK,EAAE,aAAa,YAAY,MAAM,WAAW,EAAE,KAAK;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO,WAAW;AACpB;AAiOA,IAAM,eAAeC,OAAK,WAAW,cAAc;;;ADrTnD,IAAM,sBAAsBC,OAAKC,SAAQ,GAAG,WAAW,UAAU;AAK1D,SAAS,iBAA2B;AACzC,MAAI,CAACC,aAAW,mBAAmB,GAAG;AACpC,WAAO,CAAC;AAAA,EACV;AAEA,SAAOC,cAAY,mBAAmB,EACnC,IAAI,UAAQH,OAAK,qBAAqB,IAAI,CAAC,EAC3C,OAAO,UAAQ;AACd,QAAI;AACF,aAAOI,UAAS,IAAI,EAAE,YAAY;AAAA,IACpC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACL;AAKO,SAAS,gBAAgB,YAA8B;AAC5D,MAAI,CAACF,aAAW,UAAU,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,SAAOC,cAAY,UAAU,EAC1B,OAAO,UAAQ,KAAK,SAAS,QAAQ,CAAC,EACtC,IAAI,UAAQH,OAAK,YAAY,IAAI,CAAC,EAClC,KAAK,CAAC,GAAG,MAAM;AACd,QAAI;AACF,aAAOI,UAAS,CAAC,EAAE,MAAM,QAAQ,IAAIA,UAAS,CAAC,EAAE,MAAM,QAAQ;AAAA,IACjE,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACL;AAwBA,SAAS,mBAAmB,OAAwD;AAElF,MAAI,MAAM,SAAS,QAAQ,GAAG;AAC5B,QAAI,kBAAkB;AAGtB,QAAI,MAAM,SAAS,UAAU,KAAK,MAAM,SAAS,UAAU,GAAG;AAC5D,wBAAkB;AAAA,IACpB,WAAW,MAAM,SAAS,QAAQ,KAAK,MAAM,SAAS,MAAM,GAAG;AAC7D,wBAAkB;AAAA,IACpB,WAAW,MAAM,SAAS,UAAU,KAAK,MAAM,SAAS,QAAQ,GAAG;AACjE,wBAAkB;AAAA,IACpB,WAAW,MAAM,SAAS,OAAO,GAAG;AAClC,wBAAkB;AAAA,IACpB;AAEA,WAAO,EAAE,UAAU,aAAa,OAAO,gBAAgB;AAAA,EACzD;AAGA,MAAI,MAAM,SAAS,KAAK,GAAG;AACzB,WAAO,EAAE,UAAU,UAAU,MAAM;AAAA,EACrC;AAGA,MAAI,MAAM,SAAS,QAAQ,GAAG;AAC5B,WAAO,EAAE,UAAU,UAAU,MAAM;AAAA,EACrC;AAGA,SAAO,EAAE,UAAU,aAAa,OAAO,kBAAkB;AAC3D;AAKO,SAAS,mBAAmB,aAA0C;AAC3E,MAAI,CAACC,aAAW,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,UAAUC,eAAa,aAAa,OAAO;AACjD,QAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,KAAK,CAAC;AAE5D,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,MAAI,UAAU;AACd,MAAI,eAAe;AACnB,MAAI,eAAe;AAEnB,QAAM,aAAyB;AAAA,IAC7B,aAAa;AAAA,IACb,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,EACpB;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,MAAqB,KAAK,MAAM,IAAI;AAG1C,UAAI,IAAI,aAAa,CAAC,WAAW;AAC/B,oBAAY,IAAI;AAAA,MAClB;AAGA,UAAI,IAAI,WAAW;AACjB,YAAI,CAAC,aAAa,IAAI,YAAY,WAAW;AAC3C,sBAAY,IAAI;AAAA,QAClB;AACA,YAAI,CAAC,WAAW,IAAI,YAAY,SAAS;AACvC,oBAAU,IAAI;AAAA,QAChB;AAAA,MACF;AAGA,YAAM,QAAQ,IAAI,SAAS,SAAS,IAAI;AACxC,YAAMC,SAAQ,IAAI,SAAS,SAAS,IAAI;AAExC,UAAI,OAAO;AACT,mBAAW,eAAe,MAAM,gBAAgB;AAChD,mBAAW,gBAAgB,MAAM,iBAAiB;AAClD,mBAAW,mBAAmB,WAAW,mBAAmB,MAAM,MAAM,2BAA2B;AACnG,mBAAW,oBAAoB,WAAW,oBAAoB,MAAM,MAAM,+BAA+B;AACzG;AAAA,MACF;AAGA,UAAIA,UAAS,CAAC,cAAc;AAC1B,uBAAeA;AAAA,MACjB;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,MAAI,WAAW,gBAAgB,KAAK,WAAW,iBAAiB,GAAG;AACjE,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,WAAW;AACd,gBAAYC,UAAS,aAAa,QAAQ;AAAA,EAC5C;AAGA,MAAI,CAAC,cAAc;AACjB,mBAAe;AAAA,EACjB;AAGA,QAAM,EAAE,UAAU,MAAM,IAAI,mBAAmB,YAAY;AAC3D,QAAM,UAAU,WAAW,UAAU,KAAK;AAC1C,QAAM,OAAO,UAAU,cAAc,YAAY,OAAO,IAAI;AAE5D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC/C,SAAS,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC3C,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACF;AACF;;;ADpOA,IAAM,kBAAkBC,OAAK,iBAAiB,aAAa;AAC3D,IAAM,gBAAgBA,OAAK,iBAAiB,eAAe;AA+C3D,IAAM,sBAA4C;AAAA,EAChD;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AACF;AAQO,SAAS,2BAAiC;AAE/C,MAAI,CAACC,aAAW,eAAe,GAAG;AAChC,IAAAC,YAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AAGA,MAAI,CAACD,aAAW,aAAa,GAAG;AAC9B,UAAM,WAA+B;AAAA,MACnC,SAAS;AAAA,MACT,aAAa;AAAA,MACb,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACtC;AACA,iBAAa,QAAQ;AAAA,EACvB;AACF;AAOO,SAAS,eAAmC;AACjD,2BAAyB;AAEzB,MAAI;AACF,UAAM,UAAUE,eAAa,eAAe,OAAO;AACnD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,SAAS,OAAO;AACd,YAAQ,MAAM,uCAAuC,KAAK;AAE1D,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa;AAAA,MACb,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACtC;AAAA,EACF;AACF;AAOO,SAAS,aAAa,UAAoC;AAE/D,MAAI,CAACF,aAAW,eAAe,GAAG;AAChC,IAAAC,YAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AAEA,WAAS,eAAc,oBAAI,KAAK,GAAE,YAAY;AAE9C,MAAI;AACF,UAAM,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC;AAChD,IAAAE,gBAAc,eAAe,SAAS,OAAO;AAAA,EAC/C,SAAS,OAAO;AACd,YAAQ,MAAM,uCAAuC,KAAK;AAC1D,UAAM;AAAA,EACR;AACF;AAQO,SAAS,mBAAmB,MAA8B;AAC/D,SAAOJ,OAAK,iBAAiB,GAAG,IAAI,UAAU;AAChD;AAQO,SAAS,aAAa,MAAqC;AAChE,QAAM,cAAc,mBAAmB,IAAI;AAE3C,MAAI,CAACC,aAAW,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAOE,eAAa,aAAa,OAAO,EAAE,KAAK;AAAA,EACjD,SAAS,OAAO;AACd,YAAQ,MAAM,mCAAmC,IAAI,KAAK,KAAK;AAC/D,WAAO;AAAA,EACT;AACF;AA4DO,SAAS,yBACd,MACA,SACM;AACN,QAAM,WAAW,aAAa;AAE9B,QAAM,QAAQ,SAAS,YAAY,UAAU,CAAC,MAAM,EAAE,SAAS,IAAI;AAEnE,MAAI,UAAU,IAAI;AAChB,UAAM,IAAI,MAAM,cAAc,IAAI,wBAAwB;AAAA,EAC5D;AAEA,WAAS,YAAY,KAAK,IAAI;AAAA,IAC5B,GAAG,SAAS,YAAY,KAAK;AAAA,IAC7B,GAAG;AAAA,IACH;AAAA;AAAA,EACF;AAEA,eAAa,QAAQ;AACvB;AAOO,SAAS,oBAA0C;AACxD,QAAM,WAAW,aAAa;AAC9B,SAAO,SAAS;AAClB;AA+BO,SAAS,mBAAmB,MAA8B;AAC/D,SAAO,cAAc,IAAI;AAC3B;AAQO,SAAS,WAAW,MAAsB,WAA0B;AACzE,QAAM,UAAuC;AAAA,IAC3C,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,EACnC;AAEA,MAAI,WAAW;AACb,YAAQ,YAAY;AAAA,EACtB;AAEA,2BAAyB,MAAM,OAAO;AACxC;AAiEO,SAAS,wBAA8C;AAC5D,SAAO,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO;AACpD;AAsEO,SAAS,UAAU,MAA+B;AACvD,QAAM,cAAc,mBAAmB,IAAI;AAE3C,MAAI;AACF,IAAAE,UAAS,uBAAuB,WAAW,IAAI,EAAE,OAAO,SAAS,CAAC;AAClE,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AA6DA,eAAsB,qBAAqB,MAKxC;AAED,MAAI,UAAU,IAAI,GAAG;AACnB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,cAAc,IAAI;AAAA,MAC3B,OAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,aAAa,IAAI,GAAG;AACtB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,cAAc,IAAI;AAAA,MAC3B,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,cAAc,mBAAmB,IAAI;AAC3C,QAAM,MAAM,QAAQ,IAAI,QAAQ;AAGhC,QAAM,iBAAiB,eAAe,IAAI;AAAA,aAC/B,SAAS,gBAAgB,0DACzB,SAAS,iBAAiB,qDAC1B,SAAS,eAAe,qCAAqC,+BAA+B;AAAA;AAAA;AAAA,iBAGxF,IAAI;AAEnB,MAAI;AAEF,IAAAC;AAAA,MACE,2BAA2B,WAAW,SAAS,GAAG;AAAA,MAClD,EAAE,UAAU,QAAQ;AAAA,IACtB;AAGA,UAAM,IAAI,QAAQ,CAAAC,aAAW,WAAWA,UAAS,GAAI,CAAC;AAEtD,UAAM,gBAAgB,eAAe,QAAQ,MAAM,OAAO;AAE1D,IAAAD,UAAS,sBAAsB,WAAW,MAAM,aAAa,KAAK,EAAE,UAAU,QAAQ,CAAC;AACvF,UAAM,IAAI,QAAQ,CAAAC,aAAW,WAAWA,UAAS,GAAG,CAAC;AACrD,IAAAD,UAAS,sBAAsB,WAAW,SAAS,EAAE,UAAU,QAAQ,CAAC;AAGxE,eAAW,IAAI;AAEf,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,cAAc,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,SAAS,OAAY;AACnB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,mCAAmC,IAAI,KAAK,MAAM,OAAO;AAAA,MAClE,OAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;AASA,eAAsB,+BAIlB;AACF,QAAM,UAAU,sBAAsB;AACtC,QAAM,UAA8E,CAAC;AAErF,aAAW,cAAc,SAAS;AAChC,UAAM,YAAY,aAAa,WAAW,IAAI;AAE9C,QAAI,CAAC,WAAW;AAEd,cAAQ,IAAI,0CAAqC,WAAW,IAAI,EAAE;AAClE,YAAM,SAAS,MAAM,qBAAqB,WAAW,IAAI;AACzD,cAAQ,KAAK;AAAA,QACX,MAAM,WAAW;AAAA,QACjB,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,MAClB,CAAC;AAGD,UAAI,QAAQ,SAAS,QAAQ,QAAQ;AACnC,cAAM,IAAI,QAAQ,CAAAC,aAAW,WAAWA,UAAS,GAAI,CAAC;AAAA,MACxD;AAAA,IACF,OAAO;AACL,cAAQ,KAAK;AAAA,QACX,MAAM,WAAW;AAAA,QACjB,SAAS;AAAA,QACT,SAAS,oCAAoC,UAAU,UAAU,GAAG,CAAC,CAAC;AAAA,MACxE,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;;;AG/nBA;;;ACAA;;;ACAA;AAsBA;AACA;AAdA,SAAS,cAAAC,cAAY,gBAAAC,gBAA2B,YAAAC,WAAU,aAAAC,mBAAiB;AAC3E,SAAS,QAAAC,cAAsB;AAC/B,SAAS,WAAAC,gBAAe;AAexB,IAAMC,uBAAsBC,OAAKC,SAAQ,GAAG,WAAW,UAAU;AAe1D,IAAM,oBAAN,MAAgD;AAAA,EAC5C,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQR,0BAA0B,WAAkC;AAClE,QAAI,CAACC,aAAWH,oBAAmB,GAAG;AACpC,aAAO;AAAA,IACT;AAGA,UAAM,cAAc,eAAe;AAEnC,eAAW,cAAc,aAAa;AAEpC,YAAM,YAAYC,OAAK,YAAY,qBAAqB;AACxD,UAAIE,aAAW,SAAS,GAAG;AACzB,YAAI;AACF,gBAAM,eAAeC,eAAa,WAAW,OAAO;AAEpD,cAAI,aAAa,SAAS,SAAS,GAAG;AACpC,mBAAO;AAAA,UACT;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,YAAmC;AAC5D,UAAM,YAAYH,OAAK,YAAY,qBAAqB;AACxD,QAAI,CAACE,aAAW,SAAS,GAAG;AAC1B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,eAAeC,eAAa,WAAW,OAAO;AACpD,YAAM,QAAQ,KAAK,MAAM,YAAY;AAKrC,UAAI,MAAM,YAAY,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACnD,cAAM,WAAW,MAAM;AACvB,YAAI,SAAS,WAAW,EAAG,QAAO;AAGlC,cAAM,SAAS,SAAS,KAAK,CAAC,GAAG,MAAM;AACrC,iBAAO,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ;AAAA,QACzE,CAAC;AAED,eAAO,OAAO,CAAC,EAAE;AAAA,MACnB;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,YAAmC;AAC5D,UAAM,QAAQ,gBAAgB,UAAU;AACxC,WAAO,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,SAAgC;AAC7C,UAAM,QAAQ,cAAc,OAAO;AACnC,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,KAAK,0BAA0B,MAAM,SAAS;AACjE,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAGA,UAAM,YAAY,KAAK,mBAAmB,UAAU;AACpD,QAAI,WAAW;AACb,YAAM,cAAcH,OAAK,YAAY,GAAG,SAAS,QAAQ;AACzD,UAAIE,aAAW,WAAW,GAAG;AAC3B,eAAO;AAAA,MACT;AAAA,IACF;AAGA,WAAO,KAAK,mBAAmB,UAAU;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,SAA8B;AAC5C,UAAM,cAAc,KAAK,eAAe,OAAO;AAC/C,QAAI,CAAC,eAAe,CAACA,aAAW,WAAW,GAAG;AAC5C,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,OAAOE,UAAS,WAAW;AACjC,aAAO,KAAK;AAAA,IACd,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,SAAmC;AAE5D,UAAM,gBAAgBJ,OAAKC,SAAQ,GAAG,eAAe,cAAc,GAAG,OAAO,OAAO;AACpF,QAAI,CAACC,aAAW,aAAa,GAAG;AAC9B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,UAAUC,eAAa,eAAe,OAAO;AACnD,YAAM,OAAO,KAAK,MAAM,OAAO;AAG/B,YAAM,YAAY,IAAI,KAAK,KAAK,SAAS;AACzC,YAAM,MAAM,oBAAI,KAAK;AACrB,YAAM,QAAQ,IAAI,QAAQ,IAAI,UAAU,QAAQ;AAChD,UAAI,QAAQ,IAAI,KAAK,KAAM;AAEzB,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL;AAAA,QACA,SAAS,KAAK,YAAY;AAAA,QAC1B,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,aAAa,KAAK;AAAA,QAClB,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,KAAK,KAAK;AAAA,QACV,WAAW,KAAK;AAAA,MAClB;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,SAAmC;AAC7D,UAAM,eAAe,KAAK,gBAAgB,OAAO;AACjD,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,SAAmC;AAE9C,UAAM,kBAAkB,KAAK,mBAAmB,OAAO;AACvD,QAAI,iBAAiB;AACnB,aAAO;AAAA,IACT;AAGA,WAAO,KAAK,oBAAoB,OAAO;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAoC;AAChD,UAAM,cAAc,KAAK,eAAe,OAAO;AAC/C,QAAI,CAAC,aAAa;AAChB,aAAO;AAAA,IACT;AAEA,UAAM,eAAe,mBAAmB,WAAW;AACnD,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,IACT;AAEA,WAAO,aAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,SAAuC;AACpD,UAAM,cAAc,KAAK,eAAe,OAAO;AAC/C,QAAI,CAAC,aAAa;AAChB,aAAO;AAAA,IACT;AAEA,UAAM,eAAe,mBAAmB,WAAW;AACnD,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,IACT;AAKA,UAAM,aAAa,IAAM;AACzB,UAAM,cAAc,KAAO;AAC3B,UAAM,iBAAiB,MAAM;AAC7B,UAAM,kBAAkB,OAAO;AAE/B,UAAM,QAAQ,aAAa;AAC3B,UAAM,YAAY,MAAM,cAAc;AACtC,UAAM,aAAa,MAAM,eAAe;AACxC,UAAM,iBAAiB,MAAM,mBAAmB,KAAK;AACrD,UAAM,kBAAkB,MAAM,oBAAoB,KAAK;AAEvD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,YAAY,aAAa,gBAAgB;AAAA,MACpD,UAAU;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAiB,SAAuB;AAClD,QAAI,CAAC,cAAc,OAAO,GAAG;AAC3B,YAAM,IAAI,MAAM,SAAS,OAAO,iBAAiB;AAAA,IACnD;AAEA,aAAS,SAAS,OAAO;AAGzB,UAAM,UAAUH,OAAK,YAAY,OAAO,GAAG,MAAM;AACjD,IAAAK,YAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAEtC,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC/D,UAAM,KAAK,UAAQ,IAAI;AACvB,OAAG;AAAA,MACDL,OAAK,SAAS,GAAG,SAAS,KAAK;AAAA,MAC/B;AAAA;AAAA,EAAgB,OAAO;AAAA;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAAuB;AAC/B,QAAI,CAAC,cAAc,OAAO,GAAG;AAC3B,YAAM,IAAI,MAAM,SAAS,OAAO,iBAAiB;AAAA,IACnD;AAEA,gBAAY,OAAO;AAGnB,UAAM,QAAQ,cAAc,OAAO;AACnC,QAAI,OAAO;AACT,YAAM,SAAS;AACf,YAAM,EAAE,gBAAAM,gBAAe,IAAI;AAC3B,MAAAA,gBAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,QAA4B;AAErC,UAAM,QAAQ,WAAe;AAAA,MAC3B,SAAS,OAAO,QAAQ,QAAQ,WAAW,EAAE;AAAA,MAC7C,WAAW,OAAO;AAAA,MAClB,SAAS;AAAA,MACT,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO;AAAA,IACjB,CAAC;AAGD,UAAM,aAAa,KAAK,0BAA0B,OAAO,SAAS;AAClE,UAAM,YAAY,aAAa,KAAK,mBAAmB,UAAU,IAAI;AAErE,WAAO;AAAA,MACL,IAAI,MAAM;AAAA,MACV,WAAW,aAAa;AAAA,MACxB,SAAS;AAAA,MACT,OAAO,MAAM;AAAA,MACb,WAAW,MAAM;AAAA,MACjB,WAAW,IAAI,KAAK,MAAM,SAAS;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAA+B;AAC1C,UAAM,WAAsB,CAAC;AAE7B,QAAI,WAAW;AAEb,YAAM,aAAa,KAAK,0BAA0B,SAAS;AAC3D,UAAI,YAAY;AACd,cAAM,QAAQ,gBAAgB,UAAU;AACxC,mBAAW,QAAQ,OAAO;AACxB,gBAAM,UAAU,KAAK,iBAAiB,MAAM,SAAS;AACrD,cAAI,SAAS;AACX,qBAAS,KAAK,OAAO;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AAEL,YAAM,cAAc,eAAe;AACnC,iBAAW,cAAc,aAAa;AACpC,cAAM,QAAQ,gBAAgB,UAAU;AACxC,mBAAW,QAAQ,OAAO;AACxB,gBAAM,UAAU,KAAK,iBAAiB,IAAI;AAC1C,cAAI,SAAS;AACX,qBAAS,KAAK,OAAO;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,MAAc,WAAoC;AACzE,UAAM,eAAe,mBAAmB,IAAI;AAC5C,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,IACT;AAEA,UAAM,OAAOF,UAAS,IAAI;AAE1B,WAAO;AAAA,MACL,IAAI,aAAa;AAAA,MACjB,SAAS;AAAA;AAAA,MACT,WAAW,aAAa;AAAA,MACxB,OAAO,aAAa;AAAA,MACpB,WAAW,IAAI,KAAK,aAAa,SAAS;AAAA,MAC1C,cAAc,KAAK;AAAA,MACnB,YAAY,aAAa;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAA0B;AAClC,WAAO,cAAc,OAAO;AAAA,EAC9B;AACF;AAKO,SAAS,0BAA6C;AAC3D,SAAO,IAAI,kBAAkB;AAC/B;;;AFjaA;AAQO,IAAM,kBAAN,MAA0D;AAAA,EACvD,WAA2C,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA,EAK3D,SAAS,SAA6B;AACpC,SAAK,SAAS,IAAI,QAAQ,MAAM,OAAO;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAA6C;AAC/C,WAAO,KAAK,SAAS,IAAI,IAAI;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAyB;AACvB,WAAO,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,SAAsC;AACvD,UAAM,QAAQ,cAAc,OAAO;AACnC,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAIA,QAAI;AAEJ,YAAQ,MAAM,SAAS;AAAA,MACrB,KAAK;AAAA,MACL,KAAK;AACH,sBAAc;AACd;AAAA,MACF,KAAK;AACH,sBAAc;AACd;AAAA,MACF,KAAK;AACH,sBAAc;AACd;AAAA,MACF;AAEE,sBAAc;AAAA,IAClB;AAEA,WAAO,KAAK,IAAI,WAAW,KAAK;AAAA,EAClC;AACF;AAKA,IAAI,iBAAyC;AAQtC,SAAS,oBAAqC;AACnD,MAAI,CAAC,gBAAgB;AACnB,qBAAiB,IAAI,gBAAgB;AAGrC,mBAAe,SAAS,wBAAwB,CAAC;AAAA,EAGnD;AACA,SAAO;AACT;AAqBO,SAAS,mBAAmB,SAAsC;AACvE,SAAO,kBAAkB,EAAE,mBAAmB,OAAO;AACvD;;;APnGA;;;AU3BA;AAUA,SAAS,cAAAG,oBAAkB;AAC3B,SAAS,QAAAC,cAAY;AACrB,SAAS,YAAAC,kBAAgB;AAuClB,SAAS,qBACd,QACA,cACA,QACkB;AAClB,QAAM,OAAO,UAAU,mBAAmB;AAG1C,QAAM,cAAc,KAAK,UAAU,eAAe;AAClD,MAAI,CAAC,aAAa,SAAS;AACzB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAGA,MAAI,OAAO,UAAU,SAAS;AAC5B,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,YAAY,OAAO,KAAK;AAAA,MAChC,YAAY;AAAA,IACd;AAAA,EACF;AAGA,MAAI,CAAC,OAAO,cAAc;AACxB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AACA,QAAM,wBAAwB,KAAK,IAAI,IAAI,OAAO,aAAa,QAAQ,MAAM,MAAO;AAGpF,MAAI,iBAAiB,WAAW,wBAAwB,YAAY,yBAAyB;AAC3F,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,yBAAyB,KAAK,MAAM,oBAAoB,CAAC;AAAA,MACjE,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd;AAAA,EACF;AAEA,MAAI,iBAAiB,YAAY,wBAAwB,YAAY,wBAAwB;AAC3F,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,0BAA0B,KAAK,MAAM,oBAAoB,CAAC;AAAA,MAClE,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd;AAAA,EACF;AAEA,MAAI,iBAAiB,QAAQ;AAC3B,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,0CAA0C,KAAK,MAAM,oBAAoB,CAAC;AAAA,IAClF,YAAY;AAAA,EACd;AACF;AAgBO,SAAS,sBACd,SACA,WACA,SACA,QACkB;AAClB,QAAM,OAAO,UAAU,mBAAmB;AAG1C,QAAM,iBAAiB,KAAK,UAAU,eAAe;AACrD,MAAI,CAAC,gBAAgB,SAAS;AAC5B,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAEA,QAAM,UAAoB,CAAC;AAC3B,MAAI,cAAc;AAGlB,MAAI;AACF,UAAM,SAASC,WAAS,qBAAqB,QAAQ,YAAY,CAAC,oBAAoB;AAAA,MACpF,UAAU;AAAA,IACZ,CAAC;AACD,UAAM,QAAQ,KAAK,MAAM,MAAM;AAC/B,UAAM,WAAW,MAAM;AAAA,MAAK,CAAC,MAC3B,EAAE,MAAM,YAAY,EAAE,SAAS,MAAM,KACrC,EAAE,QAAQ,SAAS,UAAU;AAAA,IAC/B;AACA,QAAI,UAAU;AACZ,cAAQ,KAAK,+BAA+B,SAAS,EAAE,EAAE;AACzD;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAAA,EAEhB;AAGA,QAAM,UAAUC,OAAK,WAAW,oBAAoB,QAAQ,YAAY,CAAC,UAAU;AACnF,MAAIC,aAAW,OAAO,GAAG;AACvB,YAAQ,KAAK,iBAAiB;AAC9B;AAAA,EACF;AAOA,MAAI,eAAe,GAAG;AACpB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,+BAA+B,QAAQ,KAAK,IAAI,CAAC;AAAA,MACzD,gBAAgB,eAAe;AAAA,MAC/B,YAAY;AAAA,IACd;AAAA,EACF;AAEA,MAAI,gBAAgB,GAAG;AACrB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,+BAA+B,QAAQ,KAAK,IAAI,CAAC;AAAA,MACzD,YAAY;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AACF;AAaO,SAAS,iBACd,WACA,cACA,QACkB;AAClB,QAAM,OAAO,UAAU,mBAAmB;AAG1C,QAAM,aAAa,KAAK,UAAU,eAAe;AACjD,MAAI,CAAC,YAAY,SAAS;AACxB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAGA,MAAI,iBAAiB,WAAW,YAAY;AAC1C,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,2CAA2C,WAAW,UAAU;AAAA,MACxE,YAAY;AAAA,IACd;AAAA,EACF;AAIA,QAAM,cAAc,kBAAkB,SAAS;AAE/C,MAAI,YAAY,QAAQ;AACtB,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,2BAA2B,YAAY,MAAM;AAAA,MACrD,gBAAgB,WAAW;AAAA,MAC3B,YAAY,YAAY;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AACF;AAcA,SAAS,kBAAkB,WAIzB;AAKA,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AACF;AAaO,SAAS,oBACd,SACA,QACkB;AAClB,QAAM,OAAO,UAAU,mBAAmB;AAG1C,QAAM,mBAAmB,KAAK,UAAU,eAAe;AACvD,MAAI,CAAC,kBAAkB,SAAS;AAC9B,WAAO;AAAA,MACL,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAGA,MAAI;AACF,UAAM,SAASF,WAAS,qBAAqB,QAAQ,YAAY,CAAC,oBAAoB;AAAA,MACpF,UAAU;AAAA,IACZ,CAAC;AACD,UAAM,QAAQ,KAAK,MAAM,MAAM;AAC/B,UAAM,gBAAgB,MAAM;AAAA,MAAK,CAAC,MAChC,EAAE,MAAM,YAAY,EAAE,SAAS,WAAW,KAC1C,EAAE,QAAQ,SAAS,gBAAgB;AAAA,IACrC;AAEA,QAAI,eAAe;AAEjB,YAAM,aAAaA,WAAS,qBAAqB,QAAQ,YAAY,CAAC,kBAAkB;AAAA,QACtF,UAAU;AAAA,MACZ,CAAC;AACD,YAAM,YAAY,KAAK,MAAM,UAAU;AAEvC,UAAI,UAAU,WAAW,GAAG;AAC1B,eAAO;AAAA,UACL,WAAW;AAAA,UACX,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,gBAAgB,iBAAiB;AAAA,UACjC,YAAY;AAAA,QACd;AAAA,MACF,OAAO;AACL,eAAO;AAAA,UACL,WAAW;AAAA,UACX,MAAM;AAAA,UACN,QAAQ,kCAAkC,UAAU,MAAM;AAAA,UAC1D,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAAA,EAEhB;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AACF;AAaO,SAAS,iBACd,SACA,WACA,SACA,cACA,QACA,QACoB;AACpB,QAAM,WAA+B,CAAC;AAGtC,QAAM,aAAa,qBAAqB,QAAQ,cAAc,MAAM;AACpE,MAAI,WAAW,UAAW,UAAS,KAAK,UAAU;AAElD,QAAM,gBAAgB,sBAAsB,SAAS,WAAW,SAAS,MAAM;AAC/E,MAAI,cAAc,UAAW,UAAS,KAAK,aAAa;AAExD,QAAM,YAAY,iBAAiB,WAAW,cAAc,MAAM;AAClE,MAAI,UAAU,UAAW,UAAS,KAAK,SAAS;AAEhD,QAAM,kBAAkB,oBAAoB,SAAS,MAAM;AAC3D,MAAI,gBAAgB,UAAW,UAAS,KAAK,eAAe;AAE5D,SAAO;AACT;;;AC7aA;AAYA;AAJA,SAAqB,iBAAAG,iBAAe,aAAAC,mBAAiB;AACrD,SAAS,QAAAC,cAAY;;;ACTrB;AAMA,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,QAAAC,cAAY;AACrB,SAAS,YAAAC,kBAAgB;AAuEzB,eAAsB,sBACpB,YACA,aACA,QACyB;AACzB,QAAM,UAA0B;AAAA,IAC9B,SAAS,WAAW;AAAA,IACpB,SAAS,WAAW;AAAA,IACpB,WAAW,WAAW;AAAA,IACtB,eAAe,WAAW;AAAA,IAC1B,iBAAiB;AAAA,IACjB,mBAAmB,WAAW;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,cAAc,WAAW,gBAAgB;AAAA,IACzC,WAAW,WAAW,aAAa;AAAA,EACrC;AAGA,QAAM,aAAa,SAAS,WAAW,SAAS;AAGhD,QAAM,gBAAgB,SAAS,WAAW,SAAS;AAGnD,QAAM,kBAAkB,SAAS,WAAW,OAAO;AAEnD,SAAO;AACT;AAKA,eAAe,aAAa,SAAyB,WAAkC;AACrF,MAAI;AAEF,UAAM,YAAYD,OAAK,WAAW,oBAAoB;AACtD,QAAIF,aAAW,SAAS,GAAG;AACzB,cAAQ,YAAYC,eAAa,WAAW,OAAO;AAAA,IACrD;AAGA,UAAM,WAAWC,OAAK,WAAW,WAAW;AAC5C,QAAIF,aAAW,QAAQ,GAAG;AACxB,cAAQ,WAAWC,eAAa,UAAU,OAAO;AAAA,IACnD;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,0BAA0B,KAAK;AAAA,EAC/C;AACF;AAKA,eAAe,gBAAgB,SAAyB,WAAkC;AACxF,MAAI;AAEF,UAAM,SAASE,WAAS,6BAA6B;AAAA,MACnD,KAAK;AAAA,MACL,UAAU;AAAA,IACZ,CAAC,EAAE,KAAK;AACR,YAAQ,YAAY;AAGpB,UAAM,SAASA,WAAS,0BAA0B;AAAA,MAChD,KAAK;AAAA,MACL,UAAU;AAAA,IACZ,CAAC;AACD,YAAQ,mBAAmB,OACxB,MAAM,IAAI,EACV,OAAO,UAAQ,KAAK,KAAK,CAAC,EAC1B,IAAI,UAAQ,KAAK,UAAU,CAAC,CAAC;AAGhC,UAAM,aAAaA,WAAS,wBAAwB;AAAA,MAClD,KAAK;AAAA,MACL,UAAU;AAAA,IACZ,CAAC,EAAE,KAAK;AACR,YAAQ,aAAa;AAAA,EACvB,SAAS,OAAO;AACd,YAAQ,MAAM,8BAA8B,KAAK;AAAA,EACnD;AACF;AAKA,eAAe,kBAAkB,SAAyB,SAAgC;AACxF,MAAI;AAEF,UAAM,QAAQ,QAAQ,YAAY;AAClC,UAAM,SAASA,WAAS,qBAAqB,KAAK,IAAI;AAAA,MACpD,UAAU;AAAA,IACZ,CAAC;AAED,UAAM,QAAqB,KAAK,MAAM,MAAM;AAG5C,YAAQ,mBAAmB,MAAM,OAAO,OAAK,EAAE,WAAW,aAAa;AACvE,YAAQ,iBAAiB,MAAM,OAAO,OAAK,EAAE,WAAW,MAAM;AAC9D,YAAQ,iBAAiB,MAAM,OAAO,OAAK,EAAE,WAAW,QAAQ;AAAA,EAClE,SAAS,OAAO;AACd,YAAQ,MAAM,gCAAgC,KAAK;AACnD,YAAQ,mBAAmB,CAAC;AAC5B,YAAQ,iBAAiB,CAAC;AAC1B,YAAQ,iBAAiB,CAAC;AAAA,EAC5B;AACF;AAQO,SAAS,wBAAwB,SAAiC;AACvE,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,mBAAmB;AAC9B,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,eAAe,QAAQ,MAAM,EAAE;AAC1C,QAAM,KAAK,aAAa,QAAQ,aAAa,EAAE;AAC/C,QAAM,KAAK,WAAW,QAAQ,WAAW,EAAE;AAC3C,QAAM,KAAK,sBAAsB,QAAQ,YAAY,EAAE;AACvD,MAAI,QAAQ,WAAW;AACrB,UAAM,KAAK,qBAAqB,QAAQ,UAAU,QAAQ,CAAC,CAAC,EAAE;AAAA,EAChE;AACA,QAAM,KAAK,EAAE;AAGb,MAAI,QAAQ,WAAW;AACrB,UAAM,KAAK,cAAc;AACzB,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,eAAe,QAAQ,SAAS,EAAE;AAC7C,QAAI,QAAQ,YAAY;AACtB,YAAM,KAAK,oBAAoB,QAAQ,UAAU,EAAE;AAAA,IACrD;AACA,QAAI,QAAQ,oBAAoB,QAAQ,iBAAiB,SAAS,GAAG;AACnE,YAAM,KAAK,0BAA0B,QAAQ,iBAAiB,MAAM,EAAE;AACtE,YAAM,KAAK,KAAK;AAChB,cAAQ,iBAAiB,QAAQ,UAAQ,MAAM,KAAK,IAAI,CAAC;AACzD,YAAM,KAAK,KAAK;AAAA,IAClB;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,QAAQ,kBAAkB,QAAQ,eAAe,SAAS,GAAG;AAC/D,UAAM,KAAK,oBAAoB;AAC/B,UAAM,KAAK,EAAE;AACb,YAAQ,eAAe,QAAQ,UAAQ;AACrC,YAAM,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK,EAAE,GAAG;AAAA,IAC/C,CAAC;AACD,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,QAAQ,oBAAoB,QAAQ,iBAAiB,SAAS,GAAG;AACnE,UAAM,KAAK,iBAAiB;AAC5B,UAAM,KAAK,EAAE;AACb,YAAQ,iBAAiB,QAAQ,UAAQ;AACvC,YAAM,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK,EAAE,iBAAiB;AAAA,IAC7D,CAAC;AACD,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,QAAQ,kBAAkB,QAAQ,eAAe,SAAS,GAAG;AAC/D,UAAM,KAAK,oBAAoB;AAC/B,UAAM,KAAK,EAAE;AACb,YAAQ,eAAe,QAAQ,UAAQ;AACrC,YAAM,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK,EAAE,GAAG;AAAA,IAC/C,CAAC;AACD,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,QAAQ,WAAW;AACrB,UAAM,KAAK,6BAA6B;AACxC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,aAAa;AACxB,UAAM,KAAK,QAAQ,SAAS;AAC5B,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,QAAQ,aAAa;AACvB,UAAM,KAAK,kBAAkB;AAC7B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,QAAQ,WAAW;AAC9B,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,QAAQ,aAAa;AACvB,UAAM,KAAK,iBAAiB;AAC5B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,QAAQ,WAAW;AAC9B,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,UAAM,KAAK,aAAa;AACxB,UAAM,KAAK,EAAE;AACb,YAAQ,SAAS,QAAQ,aAAW,MAAM,KAAK,KAAK,OAAO,EAAE,CAAC;AAC9D,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,QAAQ,aAAa,QAAQ,UAAU,SAAS,GAAG;AACrD,UAAM,KAAK,mBAAmB;AAC9B,UAAM,KAAK,EAAE;AACb,YAAQ,UAAU,QAAQ,cAAY,MAAM,KAAK,KAAK,QAAQ,EAAE,CAAC;AACjE,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AASO,SAAS,mBACd,SACA,wBACQ;AACR,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,iBAAiB;AAC5B,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,qCAAqC,QAAQ,OAAO,WAAW,QAAQ,aAAa,SAAS;AACxG,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,uBAAuB,QAAQ,MAAM,EAAE;AAClD,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,wDAAwD;AACnE,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,wBAAwB,OAAO,CAAC;AAE3C,MAAI,wBAAwB;AAC1B,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,4BAA4B;AACvC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,sBAAsB;AACjC,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AD3TA;AA0CA,eAAsB,eACpB,SACA,SACwB;AAExB,QAAM,QAAQ,cAAc,OAAO;AACnC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EACF;AAGA,QAAM,SAAS,QAAQ,UAAU,oBAAoB,OAAO;AAG5D,MAAI,WAAW,mBAAmB;AAChC,WAAO,MAAM,sBAAsB,OAAO,OAAO;AAAA,EACnD,OAAO;AACL,WAAO,MAAM,oBAAoB,OAAO,OAAO;AAAA,EACjD;AACF;AAQA,SAAS,oBAAoB,SAAgC;AAE3D,QAAM,cAAc,CAAC,eAAe,gBAAgB,cAAc,gBAAgB;AAClF,MAAI,YAAY,KAAK,OAAK,QAAQ,SAAS,CAAC,CAAC,GAAG;AAC9C,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAiBA,eAAe,oBACb,OACA,SACwB;AACxB,MAAI;AAMF,QAAI,QAAQ,gBAAgB,OAAO;AACjC,YAAM,UAAU,QAAQ,iBAAiB;AACzC,YAAM,OAAO,MAAM,YAAY,MAAM,IAAI,OAAO;AAChD,UAAI,CAAC,MAAM;AACT,gBAAQ,KAAK,SAAS,MAAM,EAAE,+BAA+B,OAAO,IAAI;AAAA,MAC1E;AAAA,IACF;AAGA,UAAM,UAAU,MAAM,sBAAsB,OAAO,QAAQ,aAAa,QAAQ,MAAM;AAGtF,cAAU,MAAM,EAAE;AAGlB,UAAM,SAAS,mBAAmB,SAAS,QAAQ,sBAAsB;AAGzE,UAAM,aAAaC,OAAK,YAAY,MAAM,EAAE,GAAG,UAAU;AACzD,IAAAC,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,UAAM,cAAcD,OAAK,YAAY,WAAW,KAAK,IAAI,CAAC,KAAK;AAC/D,IAAAE,gBAAc,aAAa,MAAM;AAIjC,UAAM,WAAW,WAAW;AAAA,MAC1B,SAAS,MAAM;AAAA,MACf,WAAW,MAAM;AAAA,MACjB,SAAS,MAAM;AAAA,MACf,OAAO,QAAQ;AAAA,MACf;AAAA,IACF,CAAC;AAGD,aAAS,gBAAgB,MAAM,gBAAgB,KAAK;AACpD,aAAS,YAAY,MAAM,aAAa;AACxC,aAAS,aAAa,MAAM;AAC5B,mBAAe,QAAQ;AAEvB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,YAAY,SAAS;AAAA,MACrB;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D;AAAA,EACF;AACF;AAkBA,eAAe,sBACb,OACA,SACwB;AACxB,MAAI;AAEF,UAAM,UAAU,MAAM,sBAAsB,OAAO,QAAQ,aAAa,QAAQ,MAAM;AAGtF,UAAM,SAAS,mBAAmB,SAAS,QAAQ,sBAAsB;AAIzE,UAAM,iBAAiB,sBAAsB,MAAM,EAAE;AACrD,QAAI,CAAC,gBAAgB;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO;AAAA,MACT;AAAA,IACF;AAKA,YAAQ,KAAK,uEAAuE;AACpF,WAAO,MAAM,oBAAoB,OAAO,OAAO;AAAA,EAsBjD,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D;AAAA,EACF;AACF;AASA,eAAe,YAAY,SAAiB,WAAqC;AAC/E,QAAM,YAAY,KAAK,IAAI;AAE3B,SAAO,KAAK,IAAI,IAAI,YAAY,WAAW;AAEzC,QAAI,CAAC,cAAc,OAAO,GAAG;AAC3B,aAAO;AAAA,IACT;AAKA,UAAM,MAAM,GAAI;AAAA,EAClB;AAEA,SAAO;AACT;AAQA,SAAS,sBAAsB,SAAgC;AAC7D,QAAM,cAAc,CAAC,eAAe,gBAAgB,cAAc,gBAAgB;AAClF,aAAW,cAAc,aAAa;AACpC,QAAI,QAAQ,SAAS,WAAW,QAAQ,UAAU,EAAE,CAAC,GAAG;AACtD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAAC,aAAW,WAAWA,UAAS,EAAE,CAAC;AACvD;;;AEzSA;AAQA;AAFA,SAAS,cAAAC,cAAY,aAAAC,aAAW,kBAAAC,iBAAgB,gBAAAC,sBAAoB;AACpE,SAAS,QAAAC,cAAY;AA6CrB,IAAM,mBAAmBA,OAAK,iBAAiB,QAAQ,gBAAgB;AAKvE,SAAS,eAAqB;AAC5B,QAAM,SAASA,OAAK,iBAAiB,MAAM;AAC3C,MAAI,CAACJ,aAAW,MAAM,GAAG;AACvB,IAAAC,YAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,EACvC;AACF;AAOO,SAAS,gBAAgB,OAA2B;AACzD,eAAa;AAEb,QAAM,OAAO,KAAK,UAAU,KAAK,IAAI;AACrC,EAAAC,gBAAe,kBAAkB,MAAM,OAAO;AAChD;AAaO,SAAS,mBACd,SACA,SACA,SACA,SACA,SACA,cACc;AAEd,MAAI;AACJ,MAAI,YAAY,oBAAoB;AAAA,EAGpC;AAEA,SAAO;AAAA,IACL,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,QAAQ;AAAA,MACf,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,IACrB;AAAA,IACA,IAAI;AAAA,MACF,OAAO,QAAQ;AAAA,MACf,SAAS;AAAA;AAAA,MACT,WAAW;AAAA;AAAA,IACb;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,SAAS;AAAA,MACP,eAAe,QAAQ;AAAA,MACvB,cAAc,QAAQ;AAAA,MACtB;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AbzDO,IAAM,kBAAN,MAAsB;AAAA,EACnB,UAAmB;AAAA,EACnB,gBAAuC;AAAA,EACvC,YAAyB;AAAA,EACzB;AAAA,EACA,YAAqC,CAAC;AAAA,EACtC,iBAA2C,oBAAI,IAAI;AAAA,EAE3D,YAAY,QAAyB;AACnC,SAAK,SAAS,UAAU,mBAAmB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,QAAI,KAAK,SAAS;AAChB,cAAQ,KAAK,6BAA6B;AAC1C;AAAA,IACF;AAEA,YAAQ,IAAI,+CAAwC;AAGpD,QAAI;AACF,yBAAmB;AACnB,cAAQ,IAAI,8CAAyC;AAAA,IACvD,SAAS,OAAO;AACd,cAAQ,MAAM,kDAA6C,KAAK;AAAA,IAClE;AAGA,QAAI;AACF,cAAQ,IAAI,kCAA6B;AACzC,YAAM,UAAU,MAAM,6BAA6B;AACnD,iBAAW,UAAU,SAAS;AAC5B,YAAI,OAAO,SAAS;AAClB,kBAAQ,IAAI,cAAS,OAAO,IAAI,KAAK,OAAO,OAAO,EAAE;AAAA,QACvD,OAAO;AACL,kBAAQ,IAAI,cAAS,OAAO,IAAI,KAAK,OAAO,OAAO,EAAE;AAAA,QACvD;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,8CAAyC,KAAK;AAAA,IAC9D;AAEA,SAAK,UAAU;AACf,SAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAG7B,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAa;AACX,QAAI,CAAC,KAAK,SAAS;AACjB,cAAQ,KAAK,yBAAyB;AACtC;AAAA,IACF;AAEA,YAAQ,IAAI,+CAAwC;AACpD,SAAK,UAAU;AAEf,QAAI,KAAK,eAAe;AACtB,oBAAc,KAAK,aAAa;AAChC,WAAK,gBAAgB;AAAA,IACvB;AAGA,QAAI;AACF,0BAAoB;AAAA,IACtB,SAAS,OAAO;AACd,cAAQ,MAAM,oCAAoC,KAAK;AAAA,IACzD;AAEA,SAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAA0B;AACxB,YAAQ,IAAI,+CAAwC;AAEpD,UAAM,gBAAgB,kBAAkB;AACxC,UAAM,eAAyB,CAAC;AAEhC,eAAW,SAAS,eAAe;AACjC,UAAI,MAAM,YAAY;AACpB,YAAI;AACF,gBAAM,UAAU,mBAAmB,MAAM,EAAE;AAC3C,cAAI,SAAS;AACX,oBAAQ,UAAU,MAAM,EAAE;AAC1B,yBAAa,KAAK,MAAM,EAAE;AAC1B,oBAAQ,IAAI,mBAAc,MAAM,EAAE,EAAE;AAAA,UACtC;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,MAAM,2BAAsB,MAAM,EAAE,KAAK,KAAK;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAEA,SAAK,KAAK,EAAE,MAAM,kBAAkB,aAAa,CAAC;AAGlD,SAAK,KAAK;AAEV,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;AAElC,SAAK,mBAAmB;AAGxB,UAAM,aAAa,KAAK,OAAO,WAAW,iBAAiB;AAC3D,SAAK,gBAAgB,YAAY,MAAM;AACrC,WAAK,mBAAmB;AAAA,IAC1B,GAAG,UAAU;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,qBAAoC;AAChD,QAAI;AACF,YAAM,gBAAgB,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU;AACpE,YAAM,WAAW,cAAc,IAAI,CAAC,MAAM,EAAE,EAAE;AAE9C,UAAI,SAAS,WAAW,GAAG;AACzB,aAAK,YAAY,oBAAI,KAAK;AAC1B;AAAA,MACF;AAGA,YAAM,eAA8B,CAAC;AAErC,iBAAW,WAAW,UAAU;AAC9B,cAAM,UAAU,mBAAmB,OAAO;AAC1C,YAAI,SAAS;AACX,gBAAM,SAASG,gBAAe,SAAS,OAAO;AAC9C,uBAAa,KAAK,MAAM;AAGxB,eAAK,kBAAkB,MAAM;AAAA,QAC/B;AAAA,MACF;AAEA,WAAK,YAAY,oBAAI,KAAK;AAC1B,WAAK,KAAK,EAAE,MAAM,gBAAgB,aAAa,CAAC;AAGhD,YAAMC,kBAAiB,0BAA0B,YAAY;AAE7D,iBAAW,UAAUA,iBAAgB;AACnC,YAAI,OAAO,UAAU,WAAW;AAC9B,eAAK,KAAK,EAAE,MAAM,iBAAiB,SAAS,OAAO,SAAS,OAAO,CAAC;AAGpE,cAAI,KAAK,OAAO,aAAa,iBAAiB;AAC5C,iBAAK,UAAU,OAAO,OAAO;AAAA,UAC/B;AAAA,QACF,WAAW,OAAO,UAAU,SAAS;AACnC,eAAK,KAAK,EAAE,MAAM,eAAe,SAAS,OAAO,SAAS,OAAO,CAAC;AAGlE,cAAI,KAAK,OAAO,aAAa,eAAe;AAC1C,iBAAK,UAAU,OAAO,OAAO;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAGA,YAAM,KAAK,qBAAqB,YAAY;AAAA,IAC9C,SAAS,OAAO;AACd,cAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAK,KAAK,EAAE,MAAM,SAAS,MAAsB,CAAC;AAAA,IACpD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAU,SAAuB;AACvC,QAAI;AACF,YAAM,UAAU,mBAAmB,OAAO;AAC1C,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,8BAA8B,OAAO,EAAE;AAAA,MACzD;AAEA,YAAM,cACJ;AAGF,cAAQ,YAAY,SAAS,WAAW;AACxC,WAAK,KAAK,EAAE,MAAM,eAAe,QAAQ,CAAC;AAE1C,cAAQ,IAAI,mBAAY,OAAO,EAAE;AAAA,IACnC,SAAS,OAAO;AACd,cAAQ,MAAM,kBAAkB,OAAO,KAAK,KAAK;AAAA,IACnD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAU,SAAuB;AACvC,QAAI;AACF,YAAM,UAAU,mBAAmB,OAAO;AAC1C,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,8BAA8B,OAAO,EAAE;AAAA,MACzD;AAEA,cAAQ,UAAU,OAAO;AACzB,WAAK,KAAK,EAAE,MAAM,gBAAgB,QAAQ,CAAC;AAE3C,cAAQ,IAAI,oBAAa,OAAO,EAAE;AAAA,IACpC,SAAS,OAAO;AACd,cAAQ,MAAM,kBAAkB,OAAO,KAAK,KAAK;AAAA,IACnD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,kBAAkB,QAA2B;AACnD,QAAI;AACF,YAAM,eAAe,OAAO;AAC5B,YAAM,gBAAgB,KAAK,eAAe,IAAI,OAAO,OAAO;AAG5D,UAAI,kBAAkB,UAAa,kBAAkB,cAAc;AAEjE,cAAM,SAAS,OAAO,WAAW,SAC7B,KAAK,kBAAkB,OAAO,UAAU,MAAM,IAC9C;AAEJ,yBAAiB;AAAA,UACf,SAAS,OAAO;AAAA,UAChB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,UAClC,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,UAAU,OAAO,YACb,KAAK,UAAU;AAAA,YACb,YAAY,OAAO,UAAU;AAAA,YAC7B,YAAY,OAAO,UAAU;AAAA,YAC7B,UAAU,OAAO,UAAU;AAAA,YAC3B,mBAAmB,OAAO;AAAA,UAC5B,CAAC,IACD;AAAA,QACN,CAAC;AAGD,aAAK,eAAe,IAAI,OAAO,SAAS,YAAY;AAAA,MACtD;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,qCAAqC,OAAO,OAAO,KAAK,KAAK;AAAA,IAC7E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,qBAAqB,cAA4C;AAC7E,eAAW,UAAU,cAAc;AACjC,UAAI;AAEF,cAAM,aAAa,cAAc,OAAO,OAAO;AAC/C,YAAI,CAAC,WAAY;AAGjB,YAAI,CAAC,WAAW,UAAW;AAG3B,cAAM,WAAW;AAAA,UACf,OAAO;AAAA,UACP,WAAW;AAAA,UACX,WAAW;AAAA,UACX,WAAW;AAAA,UACX;AAAA,UACA,KAAK;AAAA,QACP;AAIA,YAAI,SAAS,SAAS,GAAG;AACvB,gBAAM,UAAU,SAAS,CAAC;AAC1B,eAAK,KAAK,EAAE,MAAM,qBAAqB,SAAS,OAAO,SAAS,QAAQ,CAAC;AAEzE,kBAAQ,IAAI,mCAA4B,OAAO,OAAO,KAAK,QAAQ,MAAM,EAAE;AAG3E,gBAAM,SAAS,MAAM,eAAe,OAAO,SAAS;AAAA,YAClD,aAAa,QAAQ,kBAAkB;AAAA,YACvC,QAAQ,QAAQ;AAAA,UAClB,CAAC;AAED,eAAK,KAAK,EAAE,MAAM,qBAAqB,SAAS,OAAO,SAAS,OAAO,CAAC;AAGxE,cAAI,OAAO,SAAS;AAClB,kBAAM,QAAQ;AAAA,cACZ,OAAO;AAAA,cACP,WAAW;AAAA,cACX,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,OAAO;AAAA,cACP,OAAO;AAAA,YACT;AACA,4BAAgB,KAAK;AAAA,UACvB;AAEA,cAAI,OAAO,SAAS;AAClB,oBAAQ,IAAI,6BAAwB,OAAO,OAAO,WAAM,OAAO,UAAU,KAAK,QAAQ,cAAc,GAAG;AAAA,UACzG,OAAO;AACL,oBAAQ,MAAM,0BAAqB,OAAO,KAAK,EAAE;AAAA,UACnD;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,wCAAwC,OAAO,OAAO,KAAK,KAAK;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,QAAwB;AAChD,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAA4B;AAC1B,UAAM,gBAAgB,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU;AACpE,UAAM,WAAW,cAAc,IAAI,CAAC,MAAM,EAAE,EAAE;AAE9C,UAAM,eAA8B,CAAC;AAErC,eAAW,WAAW,UAAU;AAC9B,YAAM,UAAU,mBAAmB,OAAO;AAC1C,UAAI,SAAS;AACX,cAAM,SAASD,gBAAe,SAAS,OAAO;AAC9C,qBAAa,KAAK,MAAM;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,UAAU,sBAAsB,YAAY;AAClD,UAAMC,kBAAiB,0BAA0B,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AAEnF,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,wBAAwBA;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,SAAqC;AAClD,UAAM,UAAU,mBAAmB,OAAO;AAC1C,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AAEA,WAAOD,gBAAe,SAAS,OAAO;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAmC;AACjC,UAAM,gBAAgB,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU;AACpE,UAAM,eAA8B,CAAC;AAErC,eAAW,SAAS,eAAe;AACjC,YAAM,UAAU,mBAAmB,MAAM,EAAE;AAC3C,UAAI,SAAS;AACX,cAAM,SAASA,gBAAe,MAAM,IAAI,OAAO;AAC/C,qBAAa,KAAK,MAAM;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqB;AACnB,SAAK,SAAS,mBAAmB;AAGjC,QAAI,KAAK,WAAW,KAAK,eAAe;AACtC,oBAAc,KAAK,aAAa;AAChC,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAA8B;AACzC,SAAK,SAAS;AAGd,QAAI,KAAK,WAAW,KAAK,eAAe;AACtC,oBAAc,KAAK,aAAa;AAChC,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,GAAG,UAAuC;AACxC,SAAK,UAAU,KAAK,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAuC;AACzC,SAAK,YAAY,KAAK,UAAU,OAAO,CAAC,MAAM,MAAM,QAAQ;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKQ,KAAK,OAA4B;AACvC,eAAW,YAAY,KAAK,WAAW;AACrC,UAAI;AACF,iBAAS,KAAK;AAAA,MAChB,SAAS,OAAO;AACd,gBAAQ,MAAM,kCAAkC,KAAK;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AACF;AAKA,IAAI,gBAAwC;AAOrC,SAAS,qBAAsC;AACpD,MAAI,CAAC,eAAe;AAClB,oBAAgB,IAAI,gBAAgB;AAAA,EACtC;AACA,SAAO;AACT;;;ADniBA,eAAsBE,eAAc,SAAuC;AACzE,QAAM,UAAU,mBAAmB;AACnC,QAAM,SAAS,QAAQ,UAAU;AAEjC,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,EACF;AAEA,UAAQ,IAAIC,QAAM,KAAK,uCAAgC,CAAC;AAGxD,QAAM,gBAAgB,OAAO,UAAUA,QAAM,MAAM,SAAS,IAAIA,QAAM,IAAI,SAAS;AACnF,UAAQ,IAAI,WAAW,aAAa,EAAE;AAEtC,MAAI,OAAO,WAAW;AACpB,UAAM,YAAY,IAAI,KAAK,OAAO,SAAS;AAC3C,UAAM,YAAY,KAAK,OAAO,KAAK,IAAI,IAAI,UAAU,QAAQ,KAAK,GAAI;AACtE,YAAQ,IAAI,eAAe,SAAS,OAAO;AAAA,EAC7C;AAEA,UAAQ,IAAI,EAAE;AAGd,UAAQ,IAAIA,QAAM,KAAK,uBAAuB,CAAC;AAC/C,UAAQ,IAAI,wBAAiBA,QAAM,MAAM,OAAO,QAAQ,MAAM,CAAC,EAAE;AACjE,UAAQ,IAAI,wBAAiBA,QAAM,OAAO,OAAO,QAAQ,KAAK,CAAC,EAAE;AACjE,UAAQ,IAAI,wBAAiBA,QAAM,IAAI,SAAS,EAAE,OAAO,QAAQ,OAAO,CAAC,EAAE;AAC3E,UAAQ,IAAI,wBAAiBA,QAAM,IAAI,OAAO,QAAQ,KAAK,CAAC,EAAE;AAC9D,UAAQ,IAAI,iBAAiB,OAAO,QAAQ,KAAK,EAAE;AAEnD,UAAQ,IAAI,EAAE;AAGd,MAAI,OAAO,uBAAuB,SAAS,GAAG;AAC5C,YAAQ,IAAIA,QAAM,KAAK,yCAA+B,CAAC;AACvD,eAAW,WAAW,OAAO,wBAAwB;AACnD,YAAM,SAAS,QAAQ,eAAe,OAAO;AAC7C,UAAI,QAAQ;AACV,cAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,cAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,cAAM,QAAQ,OAAO,UAAU,YAAYA,QAAM,IAAI,SAAS,IAAIA,QAAM;AACxE,gBAAQ,IAAI,KAAK,KAAK,IAAI,MAAM,OAAO,CAAC,MAAM,KAAK,EAAE;AAAA,MACvD;AAAA,IACF;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAGA,UAAQ,IAAIA,QAAM,KAAK,gBAAgB,CAAC;AACxC,UAAQ,IAAI,iBAAiB,OAAO,OAAO,QAAQ,aAAa,YAAY,UAAU,EAAE;AACxF,UAAQ,IAAI,uBAAuB,OAAO,OAAO,WAAW,KAAK,cAAc,OAAO,OAAO,WAAW,OAAO,YAAY,OAAO,OAAO,WAAW,KAAK,GAAG;AAC5J,UAAQ,IAAI,iBAAiB;AAC7B,UAAQ,IAAI,0BAA0B,OAAO,OAAO,aAAa,kBAAkB,YAAY,UAAU,EAAE;AAC3G,UAAQ,IAAI,0BAA0B,OAAO,OAAO,aAAa,gBAAgBA,QAAM,IAAI,SAAS,IAAI,UAAU,EAAE;AAEpH,UAAQ,IAAI,EAAE;AAChB;;;AevEA;AAMA,OAAOC,aAAW;AAGlB,eAAsB,eAA8B;AAClD,QAAM,UAAU,mBAAmB;AAEnC,MAAI,QAAQ,UAAU,GAAG;AACvB,YAAQ,IAAIC,QAAM,OAAO,2CAAiC,CAAC;AAC3D;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM;AACpB,UAAQ,IAAIA,QAAM,MAAM,yBAAoB,CAAC;AAC7C,UAAQ,IAAIA,QAAM,IAAI,oCAAoC,CAAC;AAC7D;;;ACpBA;AAMA,OAAOC,aAAW;AAOlB,eAAsB,YAAY,SAAqC;AACrE,QAAM,UAAU,mBAAmB;AAEnC,MAAI,CAAC,QAAQ,UAAU,KAAK,CAAC,QAAQ,WAAW;AAC9C,YAAQ,IAAIC,QAAM,OAAO,uCAA6B,CAAC;AACvD;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW;AAErB,YAAQ,IAAIA,QAAM,IAAI,KAAK,+CAAwC,CAAC;AACpE,YAAQ,IAAIA,QAAM,IAAI,mDAAmD,CAAC;AAE1E,UAAM,eAAe,QAAQ,cAAc;AAE3C,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,QAAM,MAAM,iBAAY,aAAa,MAAM,YAAY,CAAC;AACpE,eAAW,WAAW,cAAc;AAClC,cAAQ,IAAIA,QAAM,IAAI,OAAO,OAAO,EAAE,CAAC;AAAA,IACzC;AAAA,EACF,OAAO;AAEL,YAAQ,KAAK;AACb,YAAQ,IAAIA,QAAM,MAAM,yBAAoB,CAAC;AAC7C,YAAQ,IAAIA,QAAM,IAAI,4BAA4B,CAAC;AAAA,EACrD;AACF;;;AjB5BO,SAAS,yBAAyBC,UAAwB;AAC/D,QAAM,WAAWA,SACd,QAAQ,UAAU,EAClB,YAAY,kCAAkC;AAGjD,WACG,QAAQ,QAAQ,EAChB,YAAY,+CAA+C,EAC3D,OAAO,UAAU,uBAAuB,EACxC,OAAOC,cAAa;AAGvB,WACG,QAAQ,OAAO,EACf,YAAY,mCAAmC,EAC/C,OAAO,YAAY;AAGtB,WACG,QAAQ,MAAM,EACd,YAAY,oDAAoD,EAChE,OAAO,WAAW;AAGrB,WACG,QAAQ,gBAAgB,EACxB,YAAY,8CAA8C,EAC1D,OAAO,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC,CAAC;AAClD;;;AkBxCA;;;ACAA;AAAA,OAAOC,aAAW;AAClB,SAAS,gBAAAC,gBAAc,iBAAAC,iBAAe,cAAAC,cAAY,aAAAC,aAAW,gBAAAC,eAAc,iBAAiB;AAC5F,SAAS,QAAAC,cAAY;AACrB,SAAS,YAAAC,kBAAgB;AACzB,SAAS,WAAAC,gBAAe;AAkBxB,SAAS,mBAA4B;AACnC,MAAI;AACF,IAAAD,WAAS,YAAY,EAAE,OAAO,OAAO,CAAC;AACtC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,YAAqB;AAC5B,UAAQ,IAAIP,QAAM,OAAO,6BAA6B,CAAC;AAEvD,MAAI;AAEF,UAAMS,YAAW,QAAQ;AAEzB,QAAIA,cAAa,UAAU;AAEzB,UAAI;AACF,QAAAF,WAAS,kBAAkB,EAAE,OAAO,OAAO,CAAC;AAC5C,QAAAA,WAAS,mBAAmB,EAAE,OAAO,UAAU,CAAC;AAChD,gBAAQ,IAAIP,QAAM,MAAM,kCAA6B,CAAC;AACtD,eAAO;AAAA,MACT,QAAQ;AACN,gBAAQ,IAAIA,QAAM,OAAO,2BAAsB,CAAC;AAAA,MAClD;AAAA,IACF,WAAWS,cAAa,SAAS;AAE/B,UAAI;AACF,QAAAF,WAAS,qBAAqB,EAAE,OAAO,OAAO,CAAC;AAC/C,QAAAA,WAAS,qDAAqD,EAAE,OAAO,UAAU,CAAC;AAClF,gBAAQ,IAAIP,QAAM,MAAM,6BAAwB,CAAC;AACjD,eAAO;AAAA,MACT,QAAQ;AACN,YAAI;AACF,UAAAO,WAAS,iBAAiB,EAAE,OAAO,OAAO,CAAC;AAC3C,UAAAA,WAAS,0BAA0B,EAAE,OAAO,UAAU,CAAC;AACvD,kBAAQ,IAAIP,QAAM,MAAM,6BAAwB,CAAC;AACjD,iBAAO;AAAA,QACT,QAAQ;AACN,kBAAQ,IAAIA,QAAM,OAAO,qDAAgD,CAAC;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,IAAIA,QAAM,IAAI,2CAAsC,CAAC;AAC7D,WAAO;AAAA,EACT;AACF;AAKA,SAAS,sBAAsB,UAA0B,UAA2B;AAClF,QAAM,cAAc,UAAU,OAAO,eAAe,CAAC;AACrD,SAAO,YAAY;AAAA,IAAK,CAAC,eACvB,WAAW,OAAO;AAAA,MAAK,CAAC,SACtB,KAAK,YAAY,YACjB,KAAK,SAAS,SAAS,YAAY,KACnC,KAAK,SAAS,SAAS,gBAAgB;AAAA,IACzC;AAAA,EACF;AACF;AAKA,eAAsB,oBAAmC;AACvD,UAAQ,IAAIA,QAAM,KAAK,yCAAyC,CAAC;AAGjE,MAAI,CAAC,iBAAiB,GAAG;AACvB,YAAQ,IAAIA,QAAM,OAAO,2CAAsC,CAAC;AAChE,UAAM,YAAY,UAAU;AAE5B,QAAI,CAAC,WAAW;AACd,cAAQ,IAAIA,QAAM,IAAI,8CAAyC,CAAC;AAChE,cAAQ,IAAIA,QAAM,IAAI,+BAA+B,CAAC;AACtD,cAAQ,IAAIA,QAAM,IAAI,2BAA2B,CAAC;AAClD,cAAQ,IAAIA,QAAM,IAAI,mCAAmC,CAAC;AAC1D,cAAQ,IAAIA,QAAM,IAAI,iCAAiC,CAAC;AACxD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,OAAO;AACL,YAAQ,IAAIA,QAAM,MAAM,wBAAmB,CAAC;AAAA,EAC9C;AAGA,QAAM,iBAAiBM,OAAKE,SAAQ,GAAG,aAAa;AACpD,QAAM,SAASF,OAAK,gBAAgB,KAAK;AACzC,QAAM,gBAAgBA,OAAK,gBAAgB,YAAY;AAEvD,MAAI,CAACH,aAAW,MAAM,GAAG;AACvB,IAAAC,YAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,YAAQ,IAAIJ,QAAM,MAAM,mCAA8B,CAAC;AAAA,EACzD;AAEA,MAAI,CAACG,aAAW,aAAa,GAAG;AAC9B,IAAAC,YAAU,eAAe,EAAE,WAAW,KAAK,CAAC;AAC5C,YAAQ,IAAIJ,QAAM,MAAM,0CAAqC,CAAC;AAAA,EAChE;AAIA,QAAM,eAAeM,OAAK,QAAQ,IAAI,GAAG,WAAW,gBAAgB;AACpE,QAAM,aAAaA,OAAK,QAAQ,gBAAgB;AAGhD,MAAI,aAAa;AACjB,MAAI,CAACH,aAAW,UAAU,GAAG;AAE3B,UAAM,EAAE,eAAAO,eAAc,IAAI,MAAM,OAAO,KAAK;AAC5C,UAAM,EAAE,SAAAC,SAAQ,IAAI,MAAM,OAAO,MAAM;AACvC,UAAMC,aAAYD,SAAQD,eAAc,YAAY,GAAG,CAAC;AACxD,UAAM,kBAAkBJ,OAAKM,YAAW,MAAM,MAAM,MAAM,WAAW,gBAAgB;AAErF,QAAIT,aAAW,eAAe,GAAG;AAC/B,mBAAa;AAAA,IACf,OAAO;AACL,cAAQ,IAAIH,QAAM,IAAI,6CAAwC,CAAC;AAC/D,cAAQ,IAAIA,QAAM,IAAI,cAAc,YAAY,EAAE,CAAC;AACnD,cAAQ,IAAIA,QAAM,IAAI,cAAc,eAAe,EAAE,CAAC;AACtD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,EAAAK,cAAa,YAAY,UAAU;AACnC,YAAU,YAAY,GAAK;AAC3B,UAAQ,IAAIL,QAAM,MAAM,wCAAmC,CAAC;AAG5D,QAAM,YAAYM,OAAKE,SAAQ,GAAG,SAAS;AAC3C,QAAM,eAAeF,OAAK,WAAW,eAAe;AAEpD,MAAI,WAA2B,CAAC;AAEhC,MAAIH,aAAW,YAAY,GAAG;AAC5B,QAAI;AACF,YAAM,kBAAkBF,eAAa,cAAc,OAAO;AAC1D,iBAAW,KAAK,MAAM,eAAe;AACrC,cAAQ,IAAID,QAAM,MAAM,2CAAsC,CAAC;AAAA,IACjE,SAAS,OAAO;AACd,cAAQ,IAAIA,QAAM,OAAO,yDAAoD,CAAC;AAC9E,iBAAW,CAAC;AAAA,IACd;AAAA,EACF,OAAO;AACL,YAAQ,IAAIA,QAAM,IAAI,oDAAoD,CAAC;AAC3E,QAAI,CAACG,aAAW,SAAS,GAAG;AAC1B,MAAAC,YAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AAAA,EACF;AAGA,MAAI,sBAAsB,UAAU,UAAU,GAAG;AAC/C,YAAQ,IAAIJ,QAAM,KAAK,uDAAkD,CAAC;AAC1E,YAAQ,IAAIA,QAAM,IAAI,uBAAuB,CAAC;AAC9C;AAAA,EACF;AAGA,MAAI,CAAC,SAAS,OAAO;AACnB,aAAS,QAAQ,CAAC;AAAA,EACpB;AAEA,MAAI,CAAC,SAAS,MAAM,aAAa;AAC/B,aAAS,MAAM,cAAc,CAAC;AAAA,EAChC;AAGA,WAAS,MAAM,YAAY,KAAK;AAAA,IAC9B,SAAS;AAAA,IACT,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF,CAAC;AAGD,EAAAE,gBAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC7D,UAAQ,IAAIF,QAAM,MAAM,0CAAqC,CAAC;AAG9D,UAAQ,IAAIA,QAAM,MAAM,KAAK,4BAAuB,CAAC;AACrD,UAAQ,IAAIA,QAAM,IAAI,yDAAyD,CAAC;AAChF,UAAQ,IAAIA,QAAM,IAAI,6DAA6D,CAAC;AACpF,UAAQ,IAAIA,QAAM,IAAI,gCAAgC,CAAC;AACzD;;;ADjNO,SAAS,sBAAsBa,UAAwB;AAC5D,QAAM,QAAQA,SACX,QAAQ,OAAO,EACf,YAAY,2CAA2C;AAE1D,QACG,QAAQ,OAAO,EACf,YAAY,oDAAoD,EAChE,OAAO,iBAAiB;AAC7B;;;AEfA;AAAA,OAAOC,aAAW;AAClB,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,QAAAC,QAAM,eAAe;AAkB9B,eAAsB,kBACpB,aACA,UAAsB,CAAC,GACR;AACf,QAAM,WAAW,QAAQ,WAAW;AAEpC,MAAI,CAACC,aAAW,QAAQ,GAAG;AACzB,YAAQ,IAAIC,QAAM,IAAI,wBAAwB,QAAQ,EAAE,CAAC;AACzD;AAAA,EACF;AAGA,QAAM,OAAO,QAAQ,QAAQ,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AAC1D,QAAM,MAAM,KAAK,YAAY,EAAE,QAAQ,eAAe,GAAG;AAGzD,QAAM,WAAW,WAAW,GAAG;AAC/B,MAAI,UAAU;AACZ,YAAQ,IAAIA,QAAM,OAAO,wCAAwC,GAAG,EAAE,CAAC;AACvE,YAAQ,IAAIA,QAAM,IAAI,kBAAkB,SAAS,IAAI,EAAE,CAAC;AACxD,YAAQ,IAAIA,QAAM,IAAI,4CAA4C,GAAG,EAAE,CAAC;AACxE;AAAA,EACF;AAGA,MAAI,aAAa,QAAQ;AACzB,MAAI,CAAC,YAAY;AACf,UAAM,cAAcC,OAAK,UAAU,eAAe,cAAc;AAChE,QAAIF,aAAW,WAAW,GAAG;AAC3B,YAAM,UAAUG,eAAa,aAAa,OAAO;AACjD,YAAM,QAAQ,QAAQ,MAAM,sBAAsB;AAClD,UAAI,MAAO,cAAa,MAAM,CAAC;AAAA,IACjC;AAAA,EACF;AAEA,QAAM,gBAA+B;AAAA,IACnC;AAAA,IACA,MAAM;AAAA,EACR;AAEA,MAAI,YAAY;AACd,kBAAc,cAAc,WAAW,YAAY;AAAA,EACrD;AAEA,kBAAgB,KAAK,aAAa;AAElC,UAAQ,IAAIF,QAAM,MAAM,yBAAoB,IAAI,EAAE,CAAC;AACnD,UAAQ,IAAIA,QAAM,IAAI,UAAU,GAAG,EAAE,CAAC;AACtC,UAAQ,IAAIA,QAAM,IAAI,WAAW,QAAQ,EAAE,CAAC;AAC5C,MAAI,YAAY;AACd,YAAQ,IAAIA,QAAM,IAAI,kBAAkB,UAAU,EAAE,CAAC;AAAA,EACvD;AACA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,QAAM,IAAI,QAAQ,oBAAoB,8BAA8B,CAAC;AACnF;AAMA,eAAsB,mBAAmB,UAAuB,CAAC,GAAkB;AACjF,QAAM,WAAW,aAAa;AAE9B,MAAI,SAAS,WAAW,GAAG;AACzB,YAAQ,IAAIA,QAAM,IAAI,yBAAyB,CAAC;AAChD,YAAQ,IAAIA,QAAM,IAAI,2DAA2D,CAAC;AAClF,YAAQ,IAAIA,QAAM,IAAI,YAAY,oBAAoB,EAAE,CAAC;AACzD;AAAA,EACF;AAEA,MAAI,QAAQ,MAAM;AAChB,UAAM,SAAwC,CAAC;AAC/C,eAAW,EAAE,KAAK,OAAO,KAAK,UAAU;AACtC,aAAO,GAAG,IAAI;AAAA,IAChB;AACA,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,EACF;AAEA,UAAQ,IAAIA,QAAM,KAAK,0BAA0B,CAAC;AAElD,aAAW,EAAE,KAAK,OAAO,KAAK,UAAU;AACtC,UAAM,SAASD,aAAW,OAAO,IAAI;AACrC,UAAM,aAAa,SAASC,QAAM,MAAM,QAAG,IAAIA,QAAM,IAAI,QAAG;AAE5D,YAAQ,IAAI,GAAG,UAAU,IAAIA,QAAM,KAAK,OAAO,IAAI,CAAC,IAAIA,QAAM,IAAI,IAAI,GAAG,GAAG,CAAC,EAAE;AAC/E,YAAQ,IAAI,KAAKA,QAAM,IAAI,OAAO,IAAI,CAAC,EAAE;AACzC,QAAI,OAAO,aAAa;AACtB,cAAQ,IAAI,KAAKA,QAAM,KAAK,WAAW,OAAO,WAAW,EAAE,CAAC,EAAE;AAAA,IAChE;AACA,QAAI,OAAO,iBAAiB,OAAO,cAAc,SAAS,GAAG;AAC3D,cAAQ,IAAI,KAAKA,QAAM,IAAI,WAAW,OAAO,cAAc,MAAM,QAAQ,CAAC,EAAE;AAAA,IAC9E;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAEA,UAAQ,IAAIA,QAAM,IAAI,WAAW,oBAAoB,EAAE,CAAC;AAC1D;AAEA,eAAsB,qBAAqB,YAAmC;AAE5E,QAAM,WAAW,aAAa;AAG9B,MAAI,kBAAkB,UAAU,GAAG;AACjC,YAAQ,IAAIA,QAAM,MAAM,2BAAsB,UAAU,EAAE,CAAC;AAC3D;AAAA,EACF;AAGA,aAAW,EAAE,KAAK,OAAO,KAAK,UAAU;AACtC,QAAI,OAAO,SAAS,cAAc,OAAO,SAAS,QAAQ,UAAU,GAAG;AACrE,wBAAkB,GAAG;AACrB,cAAQ,IAAIA,QAAM,MAAM,2BAAsB,OAAO,IAAI,EAAE,CAAC;AAC5D;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,IAAIA,QAAM,IAAI,sBAAsB,UAAU,EAAE,CAAC;AACzD,UAAQ,IAAIA,QAAM,IAAI,oDAAoD,CAAC;AAC7E;AAEA,eAAsB,qBAAoC;AACxD,MAAID,aAAW,oBAAoB,GAAG;AACpC,YAAQ,IAAIC,QAAM,OAAO,0BAA0B,oBAAoB,EAAE,CAAC;AAC1E;AAAA,EACF;AAEA,2BAAyB;AAEzB,UAAQ,IAAIA,QAAM,MAAM,oCAA+B,CAAC;AACxD,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,QAAM,IAAI,QAAQ,oBAAoB,wBAAwB,CAAC;AAC3E,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIA,QAAM,KAAK,cAAc,CAAC;AACtC,UAAQ;AAAA,IACNA,QAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,mBAAmB,WAAkC;AACzE,QAAM,WAAW,aAAa;AAG9B,MAAI,QAAQ,WAAW,SAAS;AAChC,MAAI,WAAW;AAEf,MAAI,CAAC,OAAO;AACV,eAAW,EAAE,KAAK,OAAO,KAAK,UAAU;AACtC,UAAI,OAAO,KAAK,YAAY,MAAM,UAAU,YAAY,GAAG;AACzD,gBAAQ;AACR,mBAAW;AACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,OAAO;AACV,YAAQ,MAAMA,QAAM,IAAI,sBAAsB,SAAS,EAAE,CAAC;AAC1D,YAAQ,IAAIA,QAAM,IAAI,oDAAoD,CAAC;AAC3E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,aAAaD,aAAW,MAAM,IAAI;AACxC,QAAM,aAAa,aAAaC,QAAM,MAAM,QAAG,IAAIA,QAAM,IAAI,QAAG;AAEhE,UAAQ,IAAIA,QAAM,KAAK;AAAA,WAAc,QAAQ;AAAA,CAAI,CAAC;AAClD,UAAQ,IAAI,aAAa,MAAM,IAAI,EAAE;AACrC,UAAQ,IAAI,aAAa,UAAU,IAAI,MAAM,IAAI,EAAE;AACnD,MAAI,MAAM,aAAa;AACrB,YAAQ,IAAI,aAAa,MAAM,WAAW,EAAE;AAAA,EAC9C;AAEA,MAAI,MAAM,iBAAiB,MAAM,cAAc,SAAS,GAAG;AACzD,YAAQ,IAAI,SAASA,QAAM,KAAK,gBAAgB,CAAC;AACjD,eAAW,QAAQ,MAAM,eAAe;AACtC,UAAI,KAAK,QAAQ;AACf,gBAAQ,IAAI,eAAe,KAAK,OAAO,KAAK,IAAI,CAAC,EAAE;AACnD,gBAAQ,IAAI,gBAAW,KAAK,IAAI,EAAE;AAAA,MACpC,WAAW,KAAK,SAAS;AACvB,gBAAQ,IAAI,cAAc;AAC1B,gBAAQ,IAAI,gBAAW,KAAK,IAAI,EAAE;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,IAAI,EAAE;AAChB;;;ACjNA;AAKA;AALA,OAAOG,aAAW;AAClB,SAAS,cAAAC,cAAY,eAAAC,qBAAmB;AACxC,SAAS,YAAAC,kBAAgB;AACzB,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,cAAY;AAgBrB,SAASC,cAAa,KAAsB;AAC1C,MAAI;AACF,IAAAH,WAAS,SAAS,GAAG,IAAI,EAAE,UAAU,SAAS,OAAO,OAAO,CAAC;AAC7D,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAe,MAAuB;AAC7C,SAAOF,aAAW,IAAI;AACxB;AAEA,SAAS,WAAW,MAAsB;AACxC,MAAI,CAACA,aAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,WAAOC,cAAY,IAAI,EAAE;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,gBAA+B;AACnD,UAAQ,IAAIF,QAAM,KAAK,uBAAuB,CAAC;AAC/C,UAAQ,IAAIA,QAAM,IAAI,6BAA6B,CAAC;AAEpD,QAAM,SAAwB,CAAC;AAG/B,QAAM,mBAAmB;AAAA,IACvB,EAAE,KAAK,OAAO,MAAM,OAAO,KAAK,cAAc;AAAA,IAC9C,EAAE,KAAK,QAAQ,MAAM,QAAQ,KAAK,qDAAqD;AAAA,IACvF,EAAE,KAAK,QAAQ,MAAM,WAAW,KAAK,sBAAsB;AAAA,IAC3D,EAAE,KAAK,UAAU,MAAM,cAAc,KAAK,oDAAoD;AAAA,EAChG;AAEA,aAAW,EAAE,KAAK,MAAM,IAAI,KAAK,kBAAkB;AACjD,QAAIM,cAAa,GAAG,GAAG;AACrB,aAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,SAAS,YAAY,CAAC;AAAA,IAC1D,OAAO;AACL,aAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,SAAS,aAAa,IAAI,CAAC;AAAA,IAClE;AAAA,EACF;AAGA,QAAM,mBAAmB;AAAA,IACvB,EAAE,KAAK,MAAM,MAAM,cAAc,KAAK,yBAAyB;AAAA,IAC/D,EAAE,KAAK,MAAM,MAAM,aAAa,KAAK,kCAAkC;AAAA,IACvE,EAAE,KAAK,UAAU,MAAM,UAAU,KAAK,0CAA0C;AAAA,EAClF;AAEA,aAAW,EAAE,KAAK,MAAM,IAAI,KAAK,kBAAkB;AACjD,QAAIA,cAAa,GAAG,GAAG;AACrB,aAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,SAAS,YAAY,CAAC;AAAA,IAC1D,OAAO;AACL,aAAO,KAAK,EAAE,MAAM,QAAQ,QAAQ,SAAS,4BAA4B,IAAI,CAAC;AAAA,IAChF;AAAA,EACF;AAGA,QAAM,cAAc;AAAA,IAClB,EAAE,MAAM,iBAAiB,MAAM,mBAAmB,KAAK,gBAAgB;AAAA,IACvE,EAAE,MAAM,YAAY,MAAM,oBAAoB,KAAK,gBAAgB;AAAA,IACnE,EAAE,MAAM,cAAc,MAAM,sBAAsB,KAAK,gBAAgB;AAAA,IACvE,EAAE,MAAM,YAAY,MAAM,oBAAoB,KAAK,gBAAgB;AAAA,EACrE;AAEA,aAAW,EAAE,MAAM,MAAM,IAAI,KAAK,aAAa;AAC7C,QAAI,eAAe,IAAI,GAAG;AACxB,YAAM,QAAQ,WAAW,IAAI;AAC7B,aAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,SAAS,WAAW,KAAK,UAAU,CAAC;AAAA,IACxE,OAAO;AACL,aAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,SAAS,WAAW,IAAI,CAAC;AAAA,IAChE;AAAA,EACF;AAGA,MAAI,eAAe,UAAU,GAAG;AAC9B,UAAM,cAAc,WAAWD,OAAK,YAAY,QAAQ,CAAC;AACzD,UAAM,gBAAgB,WAAWA,OAAK,YAAY,UAAU,CAAC;AAC7D,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,cAAc,IAAI,OAAO;AAAA,MACjC,SAAS,GAAG,WAAW;AAAA,MACvB,KAAK,gBAAgB,IAAI,kBAAkB;AAAA,IAC7C,CAAC;AACD,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,gBAAgB,IAAI,OAAO;AAAA,MACnC,SAAS,GAAG,aAAa;AAAA,MACzB,KAAK,kBAAkB,IAAI,kBAAkB;AAAA,IAC/C,CAAC;AAAA,EACH,OAAO;AACL,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAGA,QAAM,UAAUA,OAAKD,SAAQ,GAAG,iBAAiB;AACjD,MAAIH,aAAW,OAAO,GAAG;AACvB,WAAO,KAAK,EAAE,MAAM,eAAe,QAAQ,MAAM,SAAS,2BAA2B,CAAC;AAAA,EACxF,OAAO;AACL,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAGA,MAAI,QAAQ,IAAI,gBAAgB;AAC9B,WAAO,KAAK,EAAE,MAAM,kBAAkB,QAAQ,MAAM,SAAS,qBAAqB,CAAC;AAAA,EACrF,WAAWA,aAAW,OAAO,GAAG;AAC9B,UAAM,UAAU,UAAQ,IAAI,EAAE,aAAa,SAAS,OAAO;AAC3D,QAAI,QAAQ,SAAS,gBAAgB,GAAG;AACtC,aAAO,KAAK,EAAE,MAAM,kBAAkB,QAAQ,MAAM,SAAS,qBAAqB,CAAC;AAAA,IACrF,OAAO;AACL,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,EACF,OAAO;AACL,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAGA,MAAI;AACF,UAAM,WAAWE,WAAS,0CAA0C,EAAE,UAAU,QAAQ,CAAC;AACzF,UAAM,gBAAgB,SAAS,MAAM,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,CAAC,EAAE;AAC/E,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,aAAa;AAAA,IAC3B,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAGA,QAAM,QAAQ;AAAA,IACZ,IAAIH,QAAM,MAAM,QAAQ;AAAA,IACxB,MAAMA,QAAM,OAAO,QAAQ;AAAA,IAC3B,OAAOA,QAAM,IAAI,QAAQ;AAAA,EAC3B;AAEA,MAAI,YAAY;AAChB,MAAI,cAAc;AAElB,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM,MAAM,MAAM;AAC/B,UAAM,UAAU,MAAM,WAAW,UAAUA,QAAM,IAAI,MAAM,OAAO,IAClD,MAAM,WAAW,SAASA,QAAM,OAAO,MAAM,OAAO,IACpDA,QAAM,IAAI,MAAM,OAAO;AAEvC,YAAQ,IAAI,GAAG,IAAI,IAAI,MAAM,IAAI,KAAK,OAAO,EAAE;AAE/C,QAAI,MAAM,OAAO,MAAM,WAAW,MAAM;AACtC,cAAQ,IAAIA,QAAM,IAAI,UAAU,MAAM,GAAG,EAAE,CAAC;AAAA,IAC9C;AAEA,QAAI,MAAM,WAAW,QAAS,aAAY;AAC1C,QAAI,MAAM,WAAW,OAAQ,eAAc;AAAA,EAC7C;AAEA,UAAQ,IAAI,EAAE;AAEd,MAAI,WAAW;AACb,YAAQ,IAAIA,QAAM,IAAI,uCAAuC,CAAC;AAC9D,YAAQ,IAAIA,QAAM,IAAI,+CAA+C,CAAC;AAAA,EACxE,WAAW,aAAa;AACtB,YAAQ,IAAIA,QAAM,OAAO,2DAA2D,CAAC;AAAA,EACvF,OAAO;AACL,YAAQ,IAAIA,QAAM,MAAM,0BAA0B,CAAC;AAAA,EACrD;AACA,UAAQ,IAAI,EAAE;AAChB;;;ACpNA;AAIA,SAAS,YAAAO,kBAAgB;AACzB,OAAOC,aAAW;AAKlB,SAAS,oBAA4B;AACnC,MAAI;AACF,UAAM,MAAM;AACZ,WAAO,IAAI;AAAA,EACb,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAe,mBAAoC;AACjD,MAAI;AACF,UAAM,SAASC,WAAS,mCAAmC;AAAA,MACzD,UAAU;AAAA,MACV,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAChC,CAAC;AACD,WAAO,OAAO,KAAK;AAAA,EACrB,QAAQ;AACN,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACF;AAGA,SAAS,QAAQ,QAAgB,SAA0B;AACzD,QAAM,eAAe,CAAC,MAAc;AAClC,UAAM,QAAQ,EAAE,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG;AAC3C,WAAO;AAAA,MACL,OAAO,SAAS,MAAM,CAAC,KAAK,KAAK,EAAE;AAAA,MACnC,OAAO,SAAS,MAAM,CAAC,KAAK,KAAK,EAAE;AAAA,MACnC,OAAO,SAAS,MAAM,CAAC,KAAK,KAAK,EAAE;AAAA,IACrC;AAAA,EACF;AAEA,QAAM,IAAI,aAAa,MAAM;AAC7B,QAAM,IAAI,aAAa,OAAO;AAE9B,MAAI,EAAE,UAAU,EAAE,MAAO,QAAO,EAAE,QAAQ,EAAE;AAC5C,MAAI,EAAE,UAAU,EAAE,MAAO,QAAO,EAAE,QAAQ,EAAE;AAC5C,SAAO,EAAE,QAAQ,EAAE;AACrB;AAEA,eAAsB,cAAc,SAGjC;AACD,UAAQ,IAAIC,QAAM,KAAK,qBAAqB,CAAC;AAE7C,QAAM,iBAAiB,kBAAkB;AACzC,UAAQ,IAAI,oBAAoBA,QAAM,KAAK,cAAc,CAAC,EAAE;AAE5D,MAAI;AACJ,MAAI;AACF,YAAQ,IAAIA,QAAM,IAAI,oCAAoC,CAAC;AAC3D,oBAAgB,MAAM,iBAAiB;AACvC,YAAQ,IAAI,oBAAoBA,QAAM,KAAK,aAAa,CAAC,EAAE;AAAA,EAC7D,SAAS,OAAO;AACd,YAAQ,MAAMA,QAAM,IAAI,6BAA6B,CAAC;AACtD,YAAQ,MAAMA,QAAM,IAAI,0CAA0C,CAAC;AACnE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,cAAc,QAAQ,eAAe,cAAc;AAEzD,MAAI,CAAC,aAAa;AAChB,YAAQ,IAAIA,QAAM,MAAM,wCAAmC,CAAC;AAC5D;AAAA,EACF;AAEA,UAAQ;AAAA,IACNA,QAAM,OAAO;AAAA,2BAAyB,cAAc,WAAM,aAAa,EAAE;AAAA,EAC3E;AAEA,MAAI,QAAQ,OAAO;AACjB,YAAQ,IAAIA,QAAM,IAAI,+BAA+B,CAAC;AACtD;AAAA,EACF;AAGA,UAAQ,IAAIA,QAAM,IAAI,0BAA0B,CAAC;AAEjD,MAAI;AACF,IAAAD,WAAS,wCAAwC;AAAA,MAC/C,OAAO;AAAA,IACT,CAAC;AAED,YAAQ,IAAIC,QAAM,MAAM;AAAA,oBAAkB,aAAa,EAAE,CAAC;AAG1D,UAAM,SAAS,WAAW;AAC1B,QAAI,OAAO,KAAK,WAAW;AACzB,cAAQ,IAAIA,QAAM,IAAI,wBAAwB,CAAC;AAC/C,YAAM,YAAY,CAAC,CAAC;AAAA,IACtB;AAEA,YAAQ,IAAIA,QAAM,IAAI,sDAAsD,CAAC;AAAA,EAC/E,SAAS,OAAO;AACd,YAAQ,MAAMA,QAAM,IAAI,iBAAiB,CAAC;AAC1C,YAAQ;AAAA,MACNA,QAAM,IAAI,kEAAkE;AAAA,IAC9E;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AlD/FA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,KAAK,EACV,YAAY,oDAAoD,EAChE,QAAQ,OAAO;AAElB,QACG,QAAQ,MAAM,EACd,YAAY,wCAAwC,EACpD,OAAO,WAAW;AAErB,QACG,QAAQ,MAAM,EACd,YAAY,kCAAkC,EAC9C,OAAO,aAAa,2BAA2B,EAC/C,OAAO,WAAW,2BAA2B,EAC7C,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,WAAW;AAErB,QACG,QAAQ,qBAAqB,EAC7B,YAAY,qBAAqB,EACjC,OAAO,cAAc;AAGxB,IAAM,SAAS,QAAQ,QAAQ,QAAQ,EAAE,YAAY,gBAAgB;AAErE,OACG,QAAQ,MAAM,EACd,YAAY,kBAAkB,EAC9B,OAAO,UAAU,gBAAgB,EACjC,OAAO,iBAAiB;AAE3B,OACG,QAAQ,OAAO,EACf,YAAY,oBAAoB,EAChC,OAAO,kBAAkB,6BAA6B,IAAI,EAC1D,OAAO,kBAAkB;AAE5B,QACG,QAAQ,QAAQ,EAChB,YAAY,wBAAwB,EACpC,OAAO,UAAU,gBAAgB,EACjC,OAAO,aAAa;AAGvB,qBAAqB,OAAO;AAG5B,0BAA0B,OAAO;AAGjC,yBAAyB,OAAO;AAGhC,sBAAsB,OAAO;AAG7B,uBAAuB,OAAO;AAG9B,QACG,QAAQ,QAAQ,EAChB,YAAY,iDAAiD,EAC7D,OAAO,UAAU,gBAAgB,EACjC,OAAO,aAAa;AAGvB,QACG,QAAQ,IAAI,EACZ,YAAY,0CAA0C,EACtD,OAAO,YAAY,mBAAmB,EACtC,OAAO,kBAAkB,sBAAsB,EAC/C,OAAO,OAAO,YAAY;AACzB,QAAM,EAAE,OAAO,UAAAC,WAAS,IAAI,MAAM,OAAO,eAAe;AACxD,QAAM,EAAE,MAAAC,QAAM,SAAAC,SAAQ,IAAI,MAAM,OAAO,MAAM;AAC7C,QAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,KAAK;AAC5C,QAAM,EAAE,cAAAC,gBAAc,YAAAC,aAAW,IAAI,MAAM,OAAO,IAAI;AACtD,QAAM,EAAE,OAAAC,OAAM,IAAI,MAAM,OAAO,aAAa;AAG5C,QAAMC,aAAYL,SAAQC,eAAc,YAAY,GAAG,CAAC;AACxD,QAAM,eAAeF,OAAKM,YAAW,MAAM,WAAW;AAGtD,QAAM,aAAaN,OAAK,QAAQ,IAAI,QAAQ,IAAI,eAAe,aAAa;AAC5E,MAAI,iBAAiB;AACrB,MAAI,gBAAgB;AAEpB,MAAII,aAAW,UAAU,GAAG;AAC1B,QAAI;AACF,YAAM,gBAAgBD,eAAa,YAAY,OAAO;AACtD,YAAM,SAASE,OAAM,aAAa;AAClC,uBAAiB,OAAO,SAAS,YAAY;AAC7C,sBAAgB,OAAO,SAAS,UAAU;AAAA,IAC5C,SAAS,OAAO;AACd,cAAQ,IAAIE,QAAM,OAAO,qCAAqC,CAAC;AAAA,IACjE;AAAA,EACF;AAEA,UAAQ,IAAIA,QAAM,KAAK,0BAA0B,CAAC;AAGlD,MAAI,kBAAkB,CAAC,QAAQ,aAAa;AAC1C,UAAM,aAAaP,OAAK,QAAQ,IAAI,QAAQ,IAAI,eAAe,SAAS;AACxE,QAAII,aAAW,UAAU,GAAG;AAC1B,UAAI;AACF,gBAAQ,IAAIG,QAAM,IAAI,qBAAqB,CAAC;AAC5C,QAAAR,WAAS,wBAAwB;AAAA,UAC/B,KAAK;AAAA,UACL,OAAO;AAAA,QACT,CAAC;AACD,gBAAQ,IAAIQ,QAAM,MAAM,wBAAmB,CAAC;AAC5C,gBAAQ,IAAIA,QAAM,IAAI,gCAAgC,aAAa;AAAA,CAAS,CAAC;AAAA,MAC/E,SAAS,OAAO;AACd,gBAAQ,IAAIA,QAAM,OAAO,oDAA+C,CAAC;AACzE,gBAAQ,IAAIA,QAAM,IAAI,sDAAsD,CAAC;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AAGA,UAAQ,IAAIA,QAAM,IAAI,uBAAuB,CAAC;AAE9C,MAAI,QAAQ,QAAQ;AAElB,UAAM,QAAQ,MAAM,OAAO,CAAC,OAAO,KAAK,GAAG;AAAA,MACzC,KAAK;AAAA,MACL,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AACD,UAAM,MAAM;AACZ,YAAQ,IAAIA,QAAM,MAAM,wCAAmC,CAAC;AAC5D,QAAI,gBAAgB;AAClB,cAAQ,IAAI,eAAeA,QAAM,KAAK,WAAW,aAAa,EAAE,CAAC,EAAE;AACnE,cAAQ,IAAI,eAAeA,QAAM,KAAK,WAAW,aAAa,MAAM,CAAC,EAAE;AAAA,IACzE,OAAO;AACL,cAAQ,IAAI,eAAeA,QAAM,KAAK,uBAAuB,CAAC,EAAE;AAChE,cAAQ,IAAI,eAAeA,QAAM,KAAK,uBAAuB,CAAC,EAAE;AAAA,IAClE;AAAA,EACF,OAAO;AAEL,QAAI,gBAAgB;AAClB,cAAQ,IAAI,eAAeA,QAAM,KAAK,WAAW,aAAa,EAAE,CAAC,EAAE;AACnE,cAAQ,IAAI,eAAeA,QAAM,KAAK,WAAW,aAAa,MAAM,CAAC,EAAE;AAAA,IACzE,OAAO;AACL,cAAQ,IAAI,eAAeA,QAAM,KAAK,uBAAuB,CAAC,EAAE;AAChE,cAAQ,IAAI,eAAeA,QAAM,KAAK,uBAAuB,CAAC,EAAE;AAAA,IAClE;AACA,YAAQ,IAAIA,QAAM,IAAI,0BAA0B,CAAC;AAEjD,UAAM,QAAQ,MAAM,OAAO,CAAC,OAAO,KAAK,GAAG;AAAA,MACzC,KAAK;AAAA,MACL,OAAO;AAAA,IACT,CAAC;AAED,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,cAAQ,MAAMA,QAAM,IAAI,4BAA4B,GAAG,IAAI,OAAO;AAClE,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AAAA,EACH;AACF,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,yCAAyC,EACrD,OAAO,kBAAkB,uBAAuB,EAChD,OAAO,OAAO,YAAY;AACzB,QAAM,EAAE,UAAAR,WAAS,IAAI,MAAM,OAAO,eAAe;AACjD,QAAM,EAAE,MAAAC,OAAK,IAAI,MAAM,OAAO,MAAM;AACpC,QAAM,EAAE,cAAAG,gBAAc,YAAAC,aAAW,IAAI,MAAM,OAAO,IAAI;AACtD,QAAM,EAAE,OAAAC,OAAM,IAAI,MAAM,OAAO,aAAa;AAE5C,UAAQ,IAAIE,QAAM,KAAK,0BAA0B,CAAC;AAGlD,UAAQ,IAAIA,QAAM,IAAI,uBAAuB,CAAC;AAC9C,MAAI;AAEF,IAAAR,WAAS,qDAAqD,EAAE,OAAO,OAAO,CAAC;AAC/E,IAAAA,WAAS,qDAAqD,EAAE,OAAO,OAAO,CAAC;AAC/E,YAAQ,IAAIQ,QAAM,MAAM,0BAAqB,CAAC;AAAA,EAChD,QAAQ;AACN,YAAQ,IAAIA,QAAM,IAAI,gCAAgC,CAAC;AAAA,EACzD;AAGA,QAAM,aAAaP,OAAK,QAAQ,IAAI,QAAQ,IAAI,eAAe,aAAa;AAC5E,MAAI,iBAAiB;AAErB,MAAII,aAAW,UAAU,GAAG;AAC1B,QAAI;AACF,YAAM,gBAAgBD,eAAa,YAAY,OAAO;AACtD,YAAM,SAASE,OAAM,aAAa;AAClC,uBAAiB,OAAO,SAAS,YAAY;AAAA,IAC/C,SAAS,OAAO;AAAA,IAEhB;AAAA,EACF;AAGA,MAAI,kBAAkB,CAAC,QAAQ,aAAa;AAC1C,UAAM,aAAaL,OAAK,QAAQ,IAAI,QAAQ,IAAI,eAAe,SAAS;AACxE,QAAII,aAAW,UAAU,GAAG;AAC1B,cAAQ,IAAIG,QAAM,IAAI,qBAAqB,CAAC;AAC5C,UAAI;AACF,QAAAR,WAAS,uBAAuB;AAAA,UAC9B,KAAK;AAAA,UACL,OAAO;AAAA,QACT,CAAC;AACD,gBAAQ,IAAIQ,QAAM,MAAM,wBAAmB,CAAC;AAAA,MAC9C,SAAS,OAAO;AACd,gBAAQ,IAAIA,QAAM,OAAO,+BAA0B,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,IAAI,EAAE;AAChB,CAAC;AAGH,IAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,sDAAsD;AAE7G,QACG,QAAQ,YAAY,EACpB,YAAY,oCAAoC,EAChD,OAAO,iBAAiB,cAAc,EACtC,OAAO,iBAAiB,sCAAsC,YAAY,EAC1E,OAAO,wBAAwB,qCAAqC,EACpE,OAAO,iBAAiB;AAE3B,QACG,QAAQ,MAAM,EACd,YAAY,8BAA8B,EAC1C,OAAO,UAAU,gBAAgB,EACjC,OAAO,kBAAkB;AAE5B,QACG,QAAQ,YAAY,EACpB,YAAY,qCAAqC,EACjD,OAAO,kBAAkB;AAE5B,QACG,QAAQ,qBAAqB,EAC7B,YAAY,oCAAoC,EAChD,OAAO,oBAAoB;AAE9B,QACG,QAAQ,MAAM,EACd,YAAY,qDAAqD,EACjE,OAAO,kBAAkB;AAG5B,QACG,QAAQ,QAAQ,EAChB,YAAY,sCAAsC,EAClD,OAAO,aAAa;AAGvB,QACG,QAAQ,QAAQ,EAChB,YAAY,qCAAqC,EACjD,OAAO,WAAW,uCAAwC,EAC1D,OAAO,WAAW,gCAAgC,EAClD,OAAO,aAAa;AAGvB,QAAQ,MAAM;","names":["existsSync","mkdirSync","readFileSync","readdirSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","readdirSync","join","existsSync","mkdirSync","writeFileSync","readFileSync","readdirSync","join","execSync","homedir","chalk","chalk","ora","chalk","spinner","ora","backup","chalk","ora","chalk","backup","ora","chalk","chalk","backup","readdirSync","existsSync","join","chalk","chalk","ora","existsSync","readFileSync","join","dirname","join","existsSync","dirname","readFileSync","ora","chalk","planningContext","beadsTasks","chalk","chalk","chalk","isRunning","chalk","existsSync","readFileSync","join","chalk","ora","existsSync","writeFileSync","readFileSync","join","execSync","chalk","ora","inquirer","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","homedir","execSync","getLinearApiKey","project","chalk","ora","chalk","ora","chalk","ora","readFileSync","writeFileSync","existsSync","mkdirSync","join","homedir","getTrackerConfig","join","homedir","existsSync","readFileSync","mkdirSync","writeFileSync","ora","chalk","secondaryTracker","chalk","chalk","ora","agentId","chalk","chalk","existsSync","mkdirSync","readFileSync","writeFileSync","readdirSync","join","join","mkdirSync","existsSync","writeFileSync","readdirSync","readFileSync","join","existsSync","readdirSync","join","readFileSync","readFileSync","existsSync","chalk","chalk","existsSync","mkdirSync","readFileSync","writeFileSync","join","execSync","execSync","existsSync","readdirSync","resolve","chalk","program","chalk","ora","existsSync","mkdirSync","writeFileSync","join","basename","execSync","mkdirSync","dirname","readFileSync","existsSync","readdirSync","join","existsSync","readdirSync","mkdirSync","appendFileSync","join","execSync","program","listCommand","ora","join","chalk","existsSync","writeFileSync","mkdirSync","listProjects","worktrees","workspaces","basename","chalk","ora","execSync","existsSync","mkdirSync","readFileSync","readdirSync","join","homedir","program","readFileSync","existsSync","mkdirSync","readdirSync","join","execSync","homedir","chalk","ora","plat","chalk","readFileSync","writeFileSync","existsSync","mkdirSync","join","getAgentHealth","isRunning","join","existsSync","mkdirSync","readFileSync","writeFileSync","existsSync","mkdirSync","readdirSync","unlinkSync","join","basename","execSync","existsSync","readFileSync","readdirSync","statSync","join","basename","homedir","join","join","join","homedir","existsSync","readdirSync","statSync","existsSync","readFileSync","model","basename","join","existsSync","mkdirSync","readFileSync","writeFileSync","execSync","execSync","resolve","existsSync","readFileSync","statSync","mkdirSync","join","homedir","CLAUDE_PROJECTS_DIR","join","homedir","existsSync","readFileSync","statSync","mkdirSync","saveAgentState","existsSync","join","execSync","execSync","join","existsSync","writeFileSync","mkdirSync","join","existsSync","readFileSync","join","execSync","join","mkdirSync","writeFileSync","resolve","existsSync","mkdirSync","appendFileSync","readFileSync","join","getAgentHealth","needsAttention","statusCommand","chalk","chalk","chalk","chalk","chalk","program","statusCommand","chalk","readFileSync","writeFileSync","existsSync","mkdirSync","copyFileSync","join","execSync","homedir","platform","fileURLToPath","dirname","__dirname","program","chalk","existsSync","readFileSync","join","existsSync","chalk","join","readFileSync","chalk","existsSync","readdirSync","execSync","homedir","join","checkCommand","execSync","chalk","execSync","chalk","execSync","join","dirname","fileURLToPath","readFileSync","existsSync","parse","__dirname","chalk"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/commands/sync.ts","../../src/cli/commands/restore.ts","../../src/cli/commands/backup.ts","../../src/cli/commands/skills.ts","../../src/cli/commands/work/issue.ts","../../src/lib/agents.ts","../../src/lib/tmux.ts","../../src/lib/hooks.ts","../../src/lib/cv.ts","../../src/cli/commands/work/status.ts","../../src/cli/commands/work/tell.ts","../../src/cli/commands/work/kill.ts","../../src/cli/commands/work/pending.ts","../../src/cli/commands/work/approve.ts","../../src/cli/commands/work/plan.ts","../../src/cli/commands/work/list.ts","../../src/cli/commands/work/triage.ts","../../src/cli/commands/work/hook.ts","../../src/cli/commands/work/recover.ts","../../src/cli/commands/work/cv.ts","../../src/cli/commands/work/context.ts","../../src/lib/context.ts","../../src/cli/commands/work/health.ts","../../src/lib/health.ts","../../src/cli/commands/work/index.ts","../../src/cli/commands/workspace.ts","../../src/lib/worktree.ts","../../src/lib/template.ts","../../src/lib/skills-merge.ts","../../src/cli/commands/install.ts","../../src/cli/commands/cloister/status.ts","../../src/lib/cloister/config.ts","../../src/lib/cloister/health.ts","../../src/lib/cloister/database.ts","../../src/lib/cloister/specialists.ts","../../src/lib/cost-parsers/jsonl-parser.ts","../../src/lib/cost.ts","../../src/lib/runtimes/claude-code.ts","../../src/lib/runtimes/index.ts","../../src/lib/cloister/triggers.ts","../../src/lib/cloister/handoff.ts","../../src/lib/cloister/handoff-context.ts","../../src/lib/cloister/handoff-logger.ts","../../src/lib/cloister/service.ts","../../src/cli/commands/cloister/start.ts","../../src/cli/commands/cloister/stop.ts","../../src/cli/commands/cloister/index.ts","../../src/cli/commands/setup/hooks.ts","../../src/cli/commands/setup/index.ts","../../src/cli/commands/project.ts","../../src/cli/commands/doctor.ts","../../src/cli/commands/update.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { initCommand } from './commands/init.js';\nimport { syncCommand } from './commands/sync.js';\nimport { restoreCommand } from './commands/restore.js';\nimport { backupListCommand, backupCleanCommand } from './commands/backup.js';\nimport { skillsCommand } from './commands/skills.js';\nimport { registerWorkCommands, statusCommand } from './commands/work/index.js';\nimport { registerWorkspaceCommands } from './commands/workspace.js';\nimport { registerInstallCommand } from './commands/install.js';\nimport { registerCloisterCommands } from './commands/cloister/index.js';\nimport { registerSetupCommands } from './commands/setup/index.js';\nimport { projectAddCommand, projectListCommand, projectRemoveCommand, projectInitCommand, projectShowCommand } from './commands/project.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { updateCommand } from './commands/update.js';\n\nconst program = new Command();\n\nprogram\n .name('pan')\n .description('Multi-agent orchestration for AI coding assistants')\n .version('0.1.3');\n\nprogram\n .command('init')\n .description('Initialize Panopticon (~/.panopticon/)')\n .action(initCommand);\n\nprogram\n .command('sync')\n .description('Sync skills/commands to AI tools')\n .option('--dry-run', 'Show what would be synced')\n .option('--force', 'Overwrite without prompts')\n .option('--backup-only', 'Only create backup')\n .action(syncCommand);\n\nprogram\n .command('restore [timestamp]')\n .description('Restore from backup')\n .action(restoreCommand);\n\n// Backup management\nconst backup = program.command('backup').description('Manage backups');\n\nbackup\n .command('list')\n .description('List all backups')\n .option('--json', 'Output as JSON')\n .action(backupListCommand);\n\nbackup\n .command('clean')\n .description('Remove old backups')\n .option('--keep <count>', 'Number of backups to keep', '10')\n .action(backupCleanCommand);\n\nprogram\n .command('skills')\n .description('List and manage skills')\n .option('--json', 'Output as JSON')\n .action(skillsCommand);\n\n// Register work commands (pan work issue, pan work status, etc.)\nregisterWorkCommands(program);\n\n// Register workspace commands (pan workspace create, pan workspace list, etc.)\nregisterWorkspaceCommands(program);\n\n// Register cloister commands (pan cloister status, pan cloister start, etc.)\nregisterCloisterCommands(program);\n\n// Register setup commands (pan setup hooks, etc.)\nregisterSetupCommands(program);\n\n// Register install command\nregisterInstallCommand(program);\n\n// Shorthand: pan status = pan work status\nprogram\n .command('status')\n .description('Show running agents (shorthand for work status)')\n .option('--json', 'Output as JSON')\n .action(statusCommand);\n\n// Dashboard commands\nprogram\n .command('up')\n .description('Start dashboard (and Traefik if enabled)')\n .option('--detach', 'Run in background')\n .option('--skip-traefik', 'Skip Traefik startup')\n .action(async (options) => {\n const { spawn, execSync } = await import('child_process');\n const { join, dirname } = await import('path');\n const { fileURLToPath } = await import('url');\n const { readFileSync, existsSync } = await import('fs');\n const { parse } = await import('@iarna/toml');\n\n // Find dashboard directory relative to CLI\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const dashboardDir = join(__dirname, '..', 'dashboard');\n\n // Check if Traefik is enabled\n const configFile = join(process.env.HOME || '', '.panopticon', 'config.toml');\n let traefikEnabled = false;\n let traefikDomain = 'pan.localhost';\n\n if (existsSync(configFile)) {\n try {\n const configContent = readFileSync(configFile, 'utf-8');\n const config = parse(configContent) as any;\n traefikEnabled = config.traefik?.enabled === true;\n traefikDomain = config.traefik?.domain || 'pan.localhost';\n } catch (error) {\n console.log(chalk.yellow('Warning: Could not read config.toml'));\n }\n }\n\n console.log(chalk.bold('Starting Panopticon...\\n'));\n\n // Start Traefik if enabled\n if (traefikEnabled && !options.skipTraefik) {\n const traefikDir = join(process.env.HOME || '', '.panopticon', 'traefik');\n if (existsSync(traefikDir)) {\n try {\n console.log(chalk.dim('Starting Traefik...'));\n execSync('docker-compose up -d', {\n cwd: traefikDir,\n stdio: 'pipe',\n });\n console.log(chalk.green('✓ Traefik started'));\n console.log(chalk.dim(` Dashboard: https://traefik.${traefikDomain}:8080\\n`));\n } catch (error) {\n console.log(chalk.yellow('⚠ Failed to start Traefik (continuing anyway)'));\n console.log(chalk.dim(' Run with --skip-traefik to suppress this message\\n'));\n }\n }\n }\n\n // Start dashboard\n console.log(chalk.dim('Starting dashboard...'));\n\n if (options.detach) {\n // Run in background\n const child = spawn('npm', ['run', 'dev'], {\n cwd: dashboardDir,\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n console.log(chalk.green('✓ Dashboard started in background'));\n if (traefikEnabled) {\n console.log(` Frontend: ${chalk.cyan(`https://${traefikDomain}`)}`);\n console.log(` API: ${chalk.cyan(`https://${traefikDomain}/api`)}`);\n } else {\n console.log(` Frontend: ${chalk.cyan('http://localhost:3001')}`);\n console.log(` API: ${chalk.cyan('http://localhost:3002')}`);\n }\n } else {\n // Run in foreground\n if (traefikEnabled) {\n console.log(` Frontend: ${chalk.cyan(`https://${traefikDomain}`)}`);\n console.log(` API: ${chalk.cyan(`https://${traefikDomain}/api`)}`);\n } else {\n console.log(` Frontend: ${chalk.cyan('http://localhost:3001')}`);\n console.log(` API: ${chalk.cyan('http://localhost:3002')}`);\n }\n console.log(chalk.dim('\\nPress Ctrl+C to stop\\n'));\n\n const child = spawn('npm', ['run', 'dev'], {\n cwd: dashboardDir,\n stdio: 'inherit',\n });\n\n child.on('error', (err) => {\n console.error(chalk.red('Failed to start dashboard:'), err.message);\n process.exit(1);\n });\n }\n });\n\nprogram\n .command('down')\n .description('Stop dashboard (and Traefik if enabled)')\n .option('--skip-traefik', 'Skip Traefik shutdown')\n .action(async (options) => {\n const { execSync } = await import('child_process');\n const { join } = await import('path');\n const { readFileSync, existsSync } = await import('fs');\n const { parse } = await import('@iarna/toml');\n\n console.log(chalk.bold('Stopping Panopticon...\\n'));\n\n // Stop dashboard\n console.log(chalk.dim('Stopping dashboard...'));\n try {\n // Kill processes on dashboard ports\n execSync('lsof -ti:3001 | xargs kill -9 2>/dev/null || true', { stdio: 'pipe' });\n execSync('lsof -ti:3002 | xargs kill -9 2>/dev/null || true', { stdio: 'pipe' });\n console.log(chalk.green('✓ Dashboard stopped'));\n } catch {\n console.log(chalk.dim(' No dashboard processes found'));\n }\n\n // Check if Traefik is enabled\n const configFile = join(process.env.HOME || '', '.panopticon', 'config.toml');\n let traefikEnabled = false;\n\n if (existsSync(configFile)) {\n try {\n const configContent = readFileSync(configFile, 'utf-8');\n const config = parse(configContent) as any;\n traefikEnabled = config.traefik?.enabled === true;\n } catch (error) {\n // Ignore config read errors\n }\n }\n\n // Stop Traefik if enabled\n if (traefikEnabled && !options.skipTraefik) {\n const traefikDir = join(process.env.HOME || '', '.panopticon', 'traefik');\n if (existsSync(traefikDir)) {\n console.log(chalk.dim('Stopping Traefik...'));\n try {\n execSync('docker-compose down', {\n cwd: traefikDir,\n stdio: 'pipe',\n });\n console.log(chalk.green('✓ Traefik stopped'));\n } catch (error) {\n console.log(chalk.yellow('⚠ Failed to stop Traefik'));\n }\n }\n }\n\n console.log('');\n });\n\n// Project management commands\nconst project = program.command('project').description('Project registry for multi-project workspace support');\n\nproject\n .command('add <path>')\n .description('Register a project with Panopticon')\n .option('--name <name>', 'Project name')\n .option('--type <type>', 'Project type (standalone/monorepo)', 'standalone')\n .option('--linear-team <team>', 'Linear team prefix (e.g., MIN, PAN)')\n .action(projectAddCommand);\n\nproject\n .command('list')\n .description('List all registered projects')\n .option('--json', 'Output as JSON')\n .action(projectListCommand);\n\nproject\n .command('show <key>')\n .description('Show details for a specific project')\n .action(projectShowCommand);\n\nproject\n .command('remove <nameOrPath>')\n .description('Remove a project from the registry')\n .action(projectRemoveCommand);\n\nproject\n .command('init')\n .description('Initialize projects.yaml with example configuration')\n .action(projectInitCommand);\n\n// Doctor command\nprogram\n .command('doctor')\n .description('Check system health and dependencies')\n .action(doctorCommand);\n\n// Update command\nprogram\n .command('update')\n .description('Update Panopticon to latest version')\n .option('--check', 'Only check for updates, don\\'t install')\n .option('--force', 'Force update even if on latest')\n .action(updateCommand);\n\n// Parse and execute\nprogram.parse();\n","import { existsSync, mkdirSync, readdirSync, cpSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { INIT_DIRS, CONFIG_FILE, PANOPTICON_HOME, SKILLS_DIR, AGENTS_DIR } from '../../lib/paths.js';\nimport { getDefaultConfig, saveConfig } from '../../lib/config.js';\nimport { detectShell, getShellRcFile, addAlias, getAliasInstructions } from '../../lib/shell.js';\n\n// Get the package root directory (where skills/ and agents/ live)\n// Note: After bundling, code runs from dist/cli/index.js, so go up 2 levels\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst PACKAGE_ROOT = join(__dirname, '..', '..'); // dist/cli -> dist -> package root\nconst BUNDLED_SKILLS_DIR = join(PACKAGE_ROOT, 'skills');\nconst BUNDLED_AGENTS_DIR = join(PACKAGE_ROOT, 'agents');\n\n/**\n * Copy bundled skills from package to ~/.panopticon/skills/\n * Returns the number of skills copied\n */\nfunction copyBundledSkills(): number {\n if (!existsSync(BUNDLED_SKILLS_DIR)) {\n return 0;\n }\n\n // Ensure skills directory exists\n if (!existsSync(SKILLS_DIR)) {\n mkdirSync(SKILLS_DIR, { recursive: true });\n }\n\n const skills = readdirSync(BUNDLED_SKILLS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n let copied = 0;\n for (const skill of skills) {\n const sourcePath = join(BUNDLED_SKILLS_DIR, skill.name);\n const targetPath = join(SKILLS_DIR, skill.name);\n\n // Copy skill directory (overwrites existing)\n cpSync(sourcePath, targetPath, { recursive: true });\n copied++;\n }\n\n return copied;\n}\n\n/**\n * Copy bundled agents from package to ~/.panopticon/agents/\n * Returns the number of agents copied\n */\nfunction copyBundledAgents(): number {\n if (!existsSync(BUNDLED_AGENTS_DIR)) {\n return 0;\n }\n\n // Ensure agents directory exists\n if (!existsSync(AGENTS_DIR)) {\n mkdirSync(AGENTS_DIR, { recursive: true });\n }\n\n const agents = readdirSync(BUNDLED_AGENTS_DIR, { withFileTypes: true })\n .filter(entry => entry.isFile() && entry.name.endsWith('.md'));\n\n let copied = 0;\n for (const agent of agents) {\n const sourcePath = join(BUNDLED_AGENTS_DIR, agent.name);\n const targetPath = join(AGENTS_DIR, agent.name);\n\n // Copy agent file (overwrites existing)\n cpSync(sourcePath, targetPath);\n copied++;\n }\n\n return copied;\n}\n\nexport async function initCommand(): Promise<void> {\n const spinner = ora('Initializing Panopticon...').start();\n\n // Check if already initialized\n if (existsSync(CONFIG_FILE)) {\n spinner.info('Panopticon already initialized');\n console.log(chalk.dim(` Config: ${CONFIG_FILE}`));\n console.log(chalk.dim(` Home: ${PANOPTICON_HOME}`));\n console.log(chalk.dim(' Run `pan sync` to update skills'));\n return;\n }\n\n try {\n // Create all directories\n for (const dir of INIT_DIRS) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n spinner.text = 'Created directories...';\n\n // Write default config\n const config = getDefaultConfig();\n saveConfig(config);\n spinner.text = 'Created config...';\n\n // Copy bundled skills from package\n spinner.text = 'Installing bundled skills...';\n const skillsCopied = copyBundledSkills();\n\n // Copy bundled agents from package\n spinner.text = 'Installing bundled agents...';\n const agentsCopied = copyBundledAgents();\n\n // Detect shell and add alias\n const shell = detectShell();\n const rcFile = getShellRcFile(shell);\n\n if (rcFile && existsSync(rcFile)) {\n addAlias(rcFile);\n spinner.succeed('Panopticon initialized!');\n console.log('');\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(PANOPTICON_HOME));\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(CONFIG_FILE));\n if (skillsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${skillsCopied} bundled skills`);\n }\n if (agentsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${agentsCopied} bundled agents`);\n }\n console.log(chalk.green('✓') + ' ' + getAliasInstructions(shell));\n } else {\n spinner.succeed('Panopticon initialized!');\n console.log('');\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(PANOPTICON_HOME));\n console.log(chalk.green('✓') + ' Created ' + chalk.cyan(CONFIG_FILE));\n if (skillsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${skillsCopied} bundled skills`);\n }\n if (agentsCopied > 0) {\n console.log(chalk.green('✓') + ` Installed ${agentsCopied} bundled agents`);\n }\n console.log(chalk.yellow('!') + ' Could not detect shell. Add alias manually:');\n console.log(chalk.dim(' alias pan=\"panopticon\"'));\n }\n\n console.log('');\n console.log('Next steps:');\n console.log(chalk.dim(' 1. Run: pan sync'));\n console.log(chalk.dim(' 2. Start dashboard: pan up'));\n\n } catch (error: any) {\n spinner.fail('Failed to initialize');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { loadConfig } from '../../lib/config.js';\nimport { createBackup } from '../../lib/backup.js';\nimport { planSync, executeSync, planHooksSync, syncHooks } from '../../lib/sync.js';\nimport { SYNC_TARGETS, Runtime } from '../../lib/paths.js';\n\ninterface SyncOptions {\n dryRun?: boolean;\n force?: boolean;\n backupOnly?: boolean;\n}\n\nexport async function syncCommand(options: SyncOptions): Promise<void> {\n const config = loadConfig();\n const targets = config.sync?.targets;\n\n // Defensive check: ensure targets is defined and is a valid array\n if (!targets || !Array.isArray(targets) || targets.length === 0) {\n console.log(chalk.yellow('No sync targets configured.'));\n console.log(chalk.dim('Edit ~/.panopticon/config.toml to add targets to the [sync] section.'));\n console.log(chalk.dim('Example: targets = [\"claude-code\", \"cursor\"]'));\n return;\n }\n\n // Type assertion is now safe since we've validated the array\n const validTargets = targets as Runtime[];\n\n // Dry run mode\n if (options.dryRun) {\n console.log(chalk.bold('Sync Plan (dry run):\\n'));\n\n // Show hooks plan\n const hooksPlan = planHooksSync();\n if (hooksPlan.length > 0) {\n console.log(chalk.cyan('hooks (bin scripts):'));\n for (const hook of hooksPlan) {\n const icon = hook.status === 'new' ? chalk.green('+') : chalk.blue('↻');\n const status = hook.status === 'new' ? '' : chalk.dim('[update]');\n console.log(` ${icon} ${hook.name} ${status}`);\n }\n console.log('');\n }\n\n for (const runtime of validTargets) {\n const plan = planSync(runtime);\n\n console.log(chalk.cyan(`${runtime}:`));\n\n if (plan.skills.length === 0 && plan.commands.length === 0 && plan.agents.length === 0) {\n console.log(chalk.dim(' (nothing to sync)'));\n continue;\n }\n\n for (const item of plan.skills) {\n const icon = item.status === 'conflict' ? chalk.yellow('!') : chalk.green('+');\n const status = item.status === 'conflict' ? chalk.yellow('[conflict]') : '';\n console.log(` ${icon} skill/${item.name} ${status}`);\n }\n\n for (const item of plan.commands) {\n const icon = item.status === 'conflict' ? chalk.yellow('!') : chalk.green('+');\n const status = item.status === 'conflict' ? chalk.yellow('[conflict]') : '';\n console.log(` ${icon} command/${item.name} ${status}`);\n }\n\n for (const item of plan.agents) {\n const icon = item.status === 'conflict' ? chalk.yellow('!') : chalk.green('+');\n const status = item.status === 'conflict' ? chalk.yellow('[conflict]') : '';\n console.log(` ${icon} agent/${item.name} ${status}`);\n }\n\n console.log('');\n }\n\n console.log(chalk.dim('Run without --dry-run to apply changes.'));\n return;\n }\n\n // Create backup if enabled\n if (config.sync.backup_before_sync) {\n const spinner = ora('Creating backup...').start();\n\n const backupDirs = validTargets.flatMap((r) => [\n SYNC_TARGETS[r].skills,\n SYNC_TARGETS[r].commands,\n SYNC_TARGETS[r].agents,\n ]);\n\n const backup = createBackup(backupDirs);\n\n if (backup.targets.length > 0) {\n spinner.succeed(`Backup created: ${backup.timestamp}`);\n } else {\n spinner.info('No existing content to backup');\n }\n\n if (options.backupOnly) {\n return;\n }\n }\n\n // Execute sync\n const spinner = ora('Syncing...').start();\n\n let totalCreated = 0;\n let totalConflicts = 0;\n\n for (const runtime of validTargets) {\n spinner.text = `Syncing to ${runtime}...`;\n\n const result = executeSync(runtime, { force: options.force });\n\n totalCreated += result.created.length;\n totalConflicts += result.conflicts.length;\n\n if (result.conflicts.length > 0 && !options.force) {\n console.log('');\n console.log(chalk.yellow(`Conflicts in ${runtime}:`));\n for (const name of result.conflicts) {\n console.log(chalk.dim(` - ${name} (use --force to overwrite)`));\n }\n }\n }\n\n if (totalConflicts > 0 && !options.force) {\n spinner.warn(`Synced ${totalCreated} items, ${totalConflicts} conflicts`);\n console.log('');\n console.log(chalk.dim('Use --force to overwrite conflicting items.'));\n } else {\n spinner.succeed(`Synced ${totalCreated} items to ${validTargets.join(', ')}`);\n }\n\n // Sync hooks (bin scripts)\n const hooksSpinner = ora('Syncing hooks...').start();\n const hooksResult = syncHooks();\n\n if (hooksResult.errors.length > 0) {\n hooksSpinner.warn(`Synced ${hooksResult.synced.length} hooks, ${hooksResult.errors.length} errors`);\n for (const error of hooksResult.errors) {\n console.log(chalk.red(` ✗ ${error}`));\n }\n } else if (hooksResult.synced.length > 0) {\n hooksSpinner.succeed(`Synced ${hooksResult.synced.length} hooks to ~/.panopticon/bin/`);\n } else {\n hooksSpinner.info('No hooks to sync');\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport inquirer from 'inquirer';\nimport { listBackups, restoreBackup } from '../../lib/backup.js';\nimport { loadConfig } from '../../lib/config.js';\nimport { SYNC_TARGETS, Runtime } from '../../lib/paths.js';\n\nexport async function restoreCommand(timestamp?: string): Promise<void> {\n const backups = listBackups();\n\n if (backups.length === 0) {\n console.log(chalk.yellow('No backups found.'));\n return;\n }\n\n // If no timestamp provided, let user choose\n if (!timestamp) {\n console.log(chalk.bold('Available backups:\\n'));\n\n for (const backup of backups.slice(0, 10)) {\n console.log(` ${chalk.cyan(backup.timestamp)} - ${backup.targets.join(', ')}`);\n }\n\n if (backups.length > 10) {\n console.log(chalk.dim(` ... and ${backups.length - 10} more`));\n }\n\n console.log('');\n\n const { selected } = await inquirer.prompt([\n {\n type: 'list',\n name: 'selected',\n message: 'Select backup to restore:',\n choices: backups.slice(0, 10).map((b) => ({\n name: `${b.timestamp} (${b.targets.join(', ')})`,\n value: b.timestamp,\n })),\n },\n ]);\n\n timestamp = selected;\n }\n\n // Confirm restore\n const { confirm } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'confirm',\n message: `Restore backup ${timestamp}? This will overwrite current files.`,\n default: false,\n },\n ]);\n\n if (!confirm) {\n console.log(chalk.dim('Restore cancelled.'));\n return;\n }\n\n const spinner = ora('Restoring backup...').start();\n\n try {\n const config = loadConfig();\n const targets = config.sync.targets as Runtime[];\n\n // Build target dirs map\n const targetDirs: Record<string, string> = {};\n\n for (const runtime of targets) {\n targetDirs[`${runtime}-skills`] = SYNC_TARGETS[runtime].skills;\n targetDirs[`${runtime}-commands`] = SYNC_TARGETS[runtime].commands;\n // Also try simple names for backwards compatibility\n targetDirs['skills'] = SYNC_TARGETS[runtime].skills;\n targetDirs['commands'] = SYNC_TARGETS[runtime].commands;\n }\n\n restoreBackup(timestamp!, targetDirs);\n\n spinner.succeed(`Restored backup: ${timestamp}`);\n\n } catch (error: any) {\n spinner.fail('Failed to restore');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { listBackups, cleanOldBackups } from '../../lib/backup.js';\n\nexport async function backupListCommand(options: { json?: boolean }): Promise<void> {\n const backups = listBackups();\n\n if (options.json) {\n console.log(JSON.stringify(backups, null, 2));\n return;\n }\n\n if (backups.length === 0) {\n console.log(chalk.dim('No backups found.'));\n console.log(chalk.dim('Backups are created automatically during sync.'));\n return;\n }\n\n console.log(chalk.bold('Backups:\\n'));\n\n for (const backup of backups) {\n console.log(` ${chalk.cyan(backup.timestamp)}`);\n console.log(` ${chalk.dim('Contains:')} ${backup.targets.join(', ')}`);\n }\n\n console.log();\n console.log(chalk.dim(`Total: ${backups.length} backups`));\n console.log(chalk.dim('Use `pan restore <timestamp>` to restore a backup.'));\n}\n\nexport async function backupCleanCommand(options: { keep?: string }): Promise<void> {\n const keepCount = parseInt(options.keep || '10', 10);\n const removed = cleanOldBackups(keepCount);\n\n if (removed === 0) {\n console.log(chalk.dim(`No backups removed (keeping ${keepCount}).`));\n } else {\n console.log(chalk.green(`Removed ${removed} old backup(s), keeping ${keepCount}.`));\n }\n}\n","import { readdirSync, readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport { SKILLS_DIR } from '../../lib/paths.js';\n\nexport interface SkillMeta {\n name: string;\n description: string;\n path: string;\n}\n\nfunction parseSkillFrontmatter(content: string): { name?: string; description?: string } {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n\n const frontmatter = match[1];\n const name = frontmatter.match(/name:\\s*(.+)/)?.[1]?.trim();\n const description = frontmatter.match(/description:\\s*(.+)/)?.[1]?.trim();\n\n return { name, description };\n}\n\nexport function listSkills(): SkillMeta[] {\n if (!existsSync(SKILLS_DIR)) return [];\n\n const skills: SkillMeta[] = [];\n const dirs = readdirSync(SKILLS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n for (const dir of dirs) {\n const skillFile = join(SKILLS_DIR, dir.name, 'SKILL.md');\n if (!existsSync(skillFile)) continue;\n\n const content = readFileSync(skillFile, 'utf8');\n const { name, description } = parseSkillFrontmatter(content);\n\n skills.push({\n name: name || dir.name,\n description: description || '(no description)',\n path: skillFile,\n });\n }\n\n return skills.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport async function skillsCommand(options: { json?: boolean }): Promise<void> {\n const skills = listSkills();\n\n if (options.json) {\n console.log(JSON.stringify(skills, null, 2));\n return;\n }\n\n console.log(chalk.bold(`\\nPanopticon Skills (${skills.length})\\n`));\n\n if (skills.length === 0) {\n console.log(chalk.yellow('No skills found.'));\n console.log(chalk.dim('Skills should be in ~/.panopticon/skills/<name>/SKILL.md'));\n return;\n }\n\n for (const skill of skills) {\n console.log(chalk.cyan(skill.name));\n console.log(chalk.dim(` ${skill.description}`));\n }\n\n console.log(`\\n${chalk.dim('Run \"pan sync\" to sync skills to Claude Code')}`);\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { spawnAgent } from '../../../lib/agents.js';\nimport { resolveProjectFromIssue, hasProjects, listProjects } from '../../../lib/projects.js';\n\ninterface IssueOptions {\n model: string;\n runtime: string;\n dryRun?: boolean;\n}\n\n/**\n * Find the workspace directory for an issue.\n * First checks project registry for the correct project path,\n * then looks for workspaces/feature-{issue-id}/ in the project root.\n */\nfunction findWorkspace(issueId: string, labels: string[] = []): string | null {\n const normalizedId = issueId.toLowerCase();\n\n // First, try to resolve from project registry\n const resolved = resolveProjectFromIssue(issueId, labels);\n if (resolved) {\n const workspaceName = `feature-${normalizedId}`;\n const workspacePath = join(resolved.projectPath, 'workspaces', workspaceName);\n if (existsSync(workspacePath)) {\n return workspacePath;\n }\n // Also try without \"feature-\" prefix\n const altPath = join(resolved.projectPath, 'workspaces', normalizedId);\n if (existsSync(altPath)) {\n return altPath;\n }\n }\n\n // Fall back to searching upward from cwd (backward compatible)\n let dir = process.cwd();\n for (let i = 0; i < 10; i++) {\n const workspacesDir = join(dir, 'workspaces');\n if (existsSync(workspacesDir)) {\n // Look for feature-{issue-id} workspace\n const workspaceName = `feature-${normalizedId}`;\n const workspacePath = join(workspacesDir, workspaceName);\n if (existsSync(workspacePath)) {\n return workspacePath;\n }\n\n // Also try without \"feature-\" prefix\n const altPath = join(workspacesDir, normalizedId);\n if (existsSync(altPath)) {\n return altPath;\n }\n }\n\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\n/**\n * Find the project root (contains workspaces/, .git, or CLAUDE.md)\n * First checks project registry, then falls back to searching upward.\n */\nfunction findProjectRoot(issueId?: string, labels: string[] = []): string {\n // If we have an issue ID, try to resolve from registry first\n if (issueId) {\n const resolved = resolveProjectFromIssue(issueId, labels);\n if (resolved) {\n return resolved.projectPath;\n }\n }\n\n // Fall back to searching upward from cwd\n let dir = process.cwd();\n for (let i = 0; i < 10; i++) {\n if (existsSync(join(dir, 'workspaces')) ||\n existsSync(join(dir, '.git')) ||\n existsSync(join(dir, 'CLAUDE.md'))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return process.cwd();\n}\n\n/**\n * Read planning artifacts for an issue (STATE.md, etc.)\n */\nfunction readPlanningContext(workspacePath: string): string | null {\n const statePath = join(workspacePath, '.planning', 'STATE.md');\n if (existsSync(statePath)) {\n return readFileSync(statePath, 'utf-8');\n }\n return null;\n}\n\n/**\n * Extract beads IDs from STATE.md content\n * Looks for patterns like `panopticon-1dg` in backticks or tables\n */\nfunction extractBeadsIdsFromState(stateContent: string): string[] {\n const ids: string[] = [];\n\n // Match beads IDs in backticks (e.g., `panopticon-1dg`)\n const backtickMatches = stateContent.match(/`([a-z]+-[a-z0-9]+)`/g) || [];\n for (const match of backtickMatches) {\n const id = match.replace(/`/g, '');\n // Filter for valid beads IDs (project-xxx format)\n if (id.match(/^[a-z]+-[a-z0-9]{2,4}$/)) {\n ids.push(id);\n }\n }\n\n return [...new Set(ids)]; // Deduplicate\n}\n\n/**\n * Read beads tasks for an issue from both workspace and project root.\n * Uses STATE.md to find the associated beads IDs.\n */\nfunction readBeadsTasks(workspacePath: string, projectRoot: string, issueId: string): string[] {\n const tasks: string[] = [];\n const normalizedId = issueId.toLowerCase();\n\n // First, extract beads IDs from STATE.md\n const stateContent = readPlanningContext(workspacePath);\n const beadsIds = stateContent ? extractBeadsIdsFromState(stateContent) : [];\n\n // Check both locations for beads database\n const beadsPaths = [\n join(workspacePath, '.beads', 'issues.jsonl'),\n join(projectRoot, '.beads', 'issues.jsonl'),\n ];\n\n const seenIds = new Set<string>();\n\n for (const beadsPath of beadsPaths) {\n if (!existsSync(beadsPath)) continue;\n\n try {\n const content = readFileSync(beadsPath, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n\n for (const line of lines) {\n try {\n const task = JSON.parse(line);\n if (seenIds.has(task.id)) continue;\n\n // Match by:\n // 1. Task ID is in the STATE.md beads list\n // 2. Task is tagged with the issue ID\n // 3. Task title contains the issue ID\n const tags = task.tags || [];\n const isMatch =\n beadsIds.includes(task.id) ||\n tags.some((t: string) => t.toLowerCase().includes(normalizedId)) ||\n task.title?.toLowerCase().includes(normalizedId);\n\n if (isMatch) {\n seenIds.add(task.id);\n tasks.push(`- [${task.status || 'open'}] ${task.title} (${task.id})`);\n }\n } catch {}\n }\n } catch {}\n }\n\n return tasks;\n}\n\n/**\n * Build a comprehensive prompt with planning context\n */\nfunction buildAgentPrompt(issueId: string, workspacePath: string, projectRoot: string): string {\n const lines: string[] = [\n `# Working on Issue: ${issueId}`,\n '',\n `**Workspace:** ${workspacePath}`,\n '',\n ];\n\n // Check what context files exist\n const hasStateFile = existsSync(join(workspacePath, '.planning', 'STATE.md'));\n const hasClaudeMd = existsSync(join(workspacePath, 'CLAUDE.md'));\n const hasProjectClaudeMd = existsSync(join(projectRoot, 'CLAUDE.md'));\n\n // CRITICAL: Instruct agent to read context files FIRST\n lines.push('## IMPORTANT: Read Context Files First');\n lines.push('');\n lines.push('Before starting any work, you MUST read these files to understand the full context:');\n lines.push('');\n\n if (hasStateFile) {\n lines.push(`1. **Read \\`.planning/STATE.md\\`** - Contains the full planning context, decisions made, and current status for this issue.`);\n }\n if (hasClaudeMd) {\n lines.push(`2. **Read \\`CLAUDE.md\\`** (in workspace) - Contains workspace-specific instructions and warnings.`);\n }\n if (hasProjectClaudeMd && projectRoot !== workspacePath) {\n lines.push(`3. **Read \\`${projectRoot}/CLAUDE.md\\`** - Contains project-wide development guidelines.`);\n }\n\n lines.push('');\n lines.push('These files contain critical context that may have been updated since the last session.');\n lines.push('');\n\n // Add beads tasks summary\n const beadsTasks = readBeadsTasks(workspacePath, projectRoot, issueId);\n if (beadsTasks.length > 0) {\n lines.push('## Beads Tasks');\n lines.push('');\n lines.push('Tasks created during planning (check STATE.md for which are complete):');\n lines.push('');\n lines.push(beadsTasks.join('\\n'));\n lines.push('');\n lines.push('Use `bd show <task-id>` to see task details, `bd update <task-id> --status in_progress` to start work.');\n lines.push('');\n }\n\n lines.push('## Your Task');\n lines.push('');\n lines.push('1. Read the context files listed above');\n lines.push('2. Check STATE.md for current status and what work remains');\n lines.push('3. Continue implementing the planned work');\n lines.push('4. Mark beads tasks as complete as you finish them: `bd update <task-id> --status closed`');\n lines.push('');\n\n // CRITICAL: Instructions for maintaining state for crash recovery\n lines.push('## CRITICAL: Keep STATE.md Updated');\n lines.push('');\n lines.push('**You may be interrupted, crash, or be stopped at any time.** To ensure the next agent can continue:');\n lines.push('');\n lines.push('1. **Update `.planning/STATE.md` frequently** as you complete work');\n lines.push('2. After completing each task or significant milestone, update the \"Current Status\" section');\n lines.push('3. Document any decisions made or blockers encountered');\n lines.push('4. Keep the \"Remaining Work\" section accurate');\n lines.push('');\n lines.push('The next agent will read STATE.md to know exactly where to pick up. Beads tasks track individual items,');\n lines.push('but STATE.md provides the narrative context and current state that beads alone cannot capture.');\n lines.push('');\n\n // CRITICAL: Work completion requirements\n lines.push('## CRITICAL: Work Completion Requirements');\n lines.push('');\n lines.push('**You are NOT done until ALL of these are true:**');\n lines.push('');\n lines.push('1. **Tests pass** - Run the full test suite (`npm test` or equivalent)');\n lines.push('2. **All changes committed** - `git status` shows \"nothing to commit, working tree clean\"');\n lines.push('3. **Pushed to remote** - `git push -u origin $(git branch --show-current)`');\n lines.push('');\n lines.push('**Before declaring work complete, run:**');\n lines.push('```');\n lines.push('npm test # Run tests');\n lines.push('git add -A && git commit -m \"feat: description\" # Commit ALL changes');\n lines.push('git push -u origin $(git branch --show-current) # Push');\n lines.push('git status # Must show \"nothing to commit\"');\n lines.push('```');\n lines.push('');\n lines.push('**Uncommitted changes = NOT COMPLETE. Do not say you are done if `git status` shows changes.**');\n lines.push('');\n\n return lines.join('\\n');\n}\n\nexport async function issueCommand(id: string, options: IssueOptions): Promise<void> {\n const spinner = ora(`Preparing workspace for ${id}...`).start();\n\n try {\n // Normalize issue ID (MIN-648 -> min-648 for tmux session name)\n const normalizedId = id.toLowerCase();\n\n // Find workspace for this issue (using project registry first, then cwd fallback)\n const projectRoot = findProjectRoot(id);\n let workspace = findWorkspace(id);\n\n // Log project resolution info\n const resolved = resolveProjectFromIssue(id);\n if (resolved) {\n spinner.text = `Resolved project: ${resolved.projectName} (${resolved.projectPath})`;\n }\n\n if (!workspace) {\n spinner.warn(`No workspace found for ${id}, using project root`);\n workspace = projectRoot;\n } else {\n spinner.text = `Found workspace: ${workspace}`;\n }\n\n if (options.dryRun) {\n spinner.info('Dry run mode');\n console.log('');\n console.log(chalk.bold('Would create:'));\n console.log(` Agent ID: agent-${normalizedId}`);\n console.log(` Workspace: ${workspace}`);\n console.log(` Runtime: ${options.runtime}`);\n console.log(` Model: ${options.model}`);\n\n // Show what context would be included\n const planningContext = readPlanningContext(workspace);\n const beadsTasks = readBeadsTasks(workspace, projectRoot, id);\n console.log('');\n console.log(chalk.bold('Context:'));\n console.log(` Planning: ${planningContext ? 'Found (.planning/STATE.md)' : 'None'}`);\n console.log(` Beads: ${beadsTasks.length} tasks`);\n return;\n }\n\n spinner.text = 'Building agent prompt with planning context...';\n const prompt = buildAgentPrompt(id, workspace, projectRoot);\n\n spinner.text = 'Spawning agent...';\n\n const agent = spawnAgent({\n issueId: id,\n workspace,\n runtime: options.runtime,\n model: options.model,\n prompt,\n });\n\n spinner.succeed(`Agent spawned: ${agent.id}`);\n\n console.log('');\n console.log(chalk.bold('Agent Details:'));\n console.log(` Session: ${chalk.cyan(agent.id)}`);\n console.log(` Workspace: ${workspace}`);\n console.log(` Runtime: ${agent.runtime} (${agent.model})`);\n\n // Show context info\n const planningContext = readPlanningContext(workspace);\n const beadsTasks = readBeadsTasks(workspace, projectRoot, id);\n if (planningContext || beadsTasks.length > 0) {\n console.log('');\n console.log(chalk.bold('Context Loaded:'));\n if (planningContext) console.log(` Planning: ${chalk.green('✓')} STATE.md`);\n if (beadsTasks.length > 0) console.log(` Beads: ${chalk.green('✓')} ${beadsTasks.length} tasks`);\n }\n\n console.log('');\n console.log(chalk.dim('Commands:'));\n console.log(` Attach: tmux attach -t ${agent.id}`);\n console.log(` Message: pan work tell ${id} \"your message\"`);\n console.log(` Kill: pan work kill ${id}`);\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { homedir } from 'os';\nimport { AGENTS_DIR } from './paths.js';\nimport { createSession, killSession, sendKeys, sessionExists, getAgentSessions } from './tmux.js';\nimport { initHook, checkHook, generateGUPPPrompt } from './hooks.js';\nimport { startWork, completeWork, getAgentCV } from './cv.js';\nimport type { ComplexityLevel } from './cloister/complexity.js';\n\nexport interface AgentState {\n id: string;\n issueId: string;\n workspace: string;\n runtime: string;\n model: string;\n status: 'starting' | 'running' | 'stopped' | 'error';\n startedAt: string;\n lastActivity?: string;\n\n // Model routing & handoffs (Phase 4)\n complexity?: ComplexityLevel;\n handoffCount?: number;\n costSoFar?: number;\n sessionId?: string; // For resuming sessions after handoff\n}\n\nexport function getAgentDir(agentId: string): string {\n return join(AGENTS_DIR, agentId);\n}\n\nexport function getAgentState(agentId: string): AgentState | null {\n const stateFile = join(getAgentDir(agentId), 'state.json');\n if (!existsSync(stateFile)) return null;\n\n const content = readFileSync(stateFile, 'utf8');\n return JSON.parse(content);\n}\n\nexport function saveAgentState(state: AgentState): void {\n const dir = getAgentDir(state.id);\n mkdirSync(dir, { recursive: true });\n\n writeFileSync(\n join(dir, 'state.json'),\n JSON.stringify(state, null, 2)\n );\n}\n\nexport interface SpawnOptions {\n issueId: string;\n workspace: string;\n runtime?: string;\n model?: string;\n prompt?: string;\n}\n\nexport function spawnAgent(options: SpawnOptions): AgentState {\n const agentId = `agent-${options.issueId.toLowerCase()}`;\n\n // Check if already running\n if (sessionExists(agentId)) {\n throw new Error(`Agent ${agentId} already running. Use 'pan work tell' to message it.`);\n }\n\n // Initialize hook for this agent (GUPP support)\n initHook(agentId);\n\n // Create state\n const state: AgentState = {\n id: agentId,\n issueId: options.issueId,\n workspace: options.workspace,\n runtime: options.runtime || 'claude',\n model: options.model || 'sonnet',\n status: 'starting',\n startedAt: new Date().toISOString(),\n // Initialize Phase 4 fields\n handoffCount: 0,\n costSoFar: 0,\n };\n\n saveAgentState(state);\n\n // Build prompt with GUPP work if available\n let prompt = options.prompt || '';\n\n // GUPP: Check for pending work on hook\n const { hasWork, items } = checkHook(agentId);\n if (hasWork) {\n const guppPrompt = generateGUPPPrompt(agentId);\n if (guppPrompt) {\n prompt = guppPrompt + '\\n\\n---\\n\\n' + prompt;\n }\n }\n\n // Write prompt to file for complex prompts (avoids shell escaping issues)\n const promptFile = join(getAgentDir(agentId), 'initial-prompt.md');\n if (prompt) {\n writeFileSync(promptFile, prompt);\n }\n\n // Auto-setup hooks if not configured\n checkAndSetupHooks();\n\n // Write initial task cache for heartbeat hook\n writeTaskCache(agentId, options.issueId);\n\n // Create tmux session and start claude\n const claudeCmd = `claude --dangerously-skip-permissions --model ${state.model}`;\n createSession(agentId, options.workspace, claudeCmd, {\n env: {\n PANOPTICON_AGENT_ID: agentId\n }\n });\n\n // If there's a prompt, load it via tmux buffer after claude starts\n if (prompt) {\n // Wait for claude to be ready by checking for the prompt character\n // Claude shows \"❯\" when ready for input\n let ready = false;\n for (let i = 0; i < 15; i++) { // Max 15 seconds\n execSync('sleep 1');\n try {\n const pane = execSync(`tmux capture-pane -t ${agentId} -p`, { encoding: 'utf-8' });\n if (pane.includes('❯') || pane.includes('>')) {\n ready = true;\n break;\n }\n } catch {}\n }\n\n if (ready) {\n // Use tmux load-buffer and paste-buffer to send the prompt\n // This avoids all shell escaping issues\n execSync(`tmux load-buffer \"${promptFile}\"`);\n execSync(`tmux paste-buffer -t ${agentId}`);\n // Small delay to let paste complete, then send Enter\n execSync('sleep 0.5');\n execSync(`tmux send-keys -t ${agentId} Enter`);\n } else {\n console.error('Claude did not become ready in time, prompt not sent');\n }\n }\n\n // Update status\n state.status = 'running';\n saveAgentState(state);\n\n // Track work in CV\n startWork(agentId, options.issueId);\n\n return state;\n}\n\nexport function listRunningAgents(): (AgentState & { tmuxActive: boolean })[] {\n const tmuxSessions = getAgentSessions();\n const tmuxNames = new Set(tmuxSessions.map(s => s.name));\n\n const agents: (AgentState & { tmuxActive: boolean })[] = [];\n\n // Read all agent states\n if (!existsSync(AGENTS_DIR)) return agents;\n\n const dirs = readdirSync(AGENTS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n for (const dir of dirs) {\n const state = getAgentState(dir.name);\n if (state) {\n agents.push({\n ...state,\n tmuxActive: tmuxNames.has(state.id),\n });\n }\n }\n\n return agents;\n}\n\nexport function stopAgent(agentId: string): void {\n // Normalize agent ID\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n\n if (sessionExists(normalizedId)) {\n killSession(normalizedId);\n }\n\n const state = getAgentState(normalizedId);\n if (state) {\n state.status = 'stopped';\n saveAgentState(state);\n }\n}\n\nexport function messageAgent(agentId: string, message: string): void {\n // Normalize agent ID\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n\n if (!sessionExists(normalizedId)) {\n throw new Error(`Agent ${normalizedId} not running`);\n }\n\n sendKeys(normalizedId, message);\n\n // Also save to mail queue\n const mailDir = join(getAgentDir(normalizedId), 'mail');\n mkdirSync(mailDir, { recursive: true });\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n writeFileSync(\n join(mailDir, `${timestamp}.md`),\n `# Message\\n\\n${message}\\n`\n );\n}\n\n/**\n * Detect crashed agents (state shows running but tmux session is gone)\n */\nexport function detectCrashedAgents(): AgentState[] {\n const agents = listRunningAgents();\n return agents.filter(\n (agent) => agent.status === 'running' && !agent.tmuxActive\n );\n}\n\n/**\n * Recover a crashed agent by restarting it with context\n */\nexport function recoverAgent(agentId: string): AgentState | null {\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n const state = getAgentState(normalizedId);\n\n if (!state) {\n return null;\n }\n\n // Check if already running\n if (sessionExists(normalizedId)) {\n return state;\n }\n\n // Update crash count in health file\n const healthFile = join(getAgentDir(normalizedId), 'health.json');\n let health = { consecutiveFailures: 0, killCount: 0, recoveryCount: 0 };\n if (existsSync(healthFile)) {\n try {\n health = { ...health, ...JSON.parse(readFileSync(healthFile, 'utf-8')) };\n } catch {}\n }\n health.recoveryCount = (health.recoveryCount || 0) + 1;\n writeFileSync(healthFile, JSON.stringify(health, null, 2));\n\n // Build recovery prompt\n const recoveryPrompt = generateRecoveryPrompt(state);\n\n // Restart the agent with recovery context (YOLO mode - skip permissions)\n const claudeCmd = `claude --dangerously-skip-permissions --model ${state.model} \"${recoveryPrompt.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n')}\"`;\n createSession(normalizedId, state.workspace, claudeCmd);\n\n // Update state\n state.status = 'running';\n state.lastActivity = new Date().toISOString();\n saveAgentState(state);\n\n return state;\n}\n\n/**\n * Generate a recovery prompt for a crashed agent\n */\nfunction generateRecoveryPrompt(state: AgentState): string {\n const lines: string[] = [\n '# Agent Recovery',\n '',\n '⚠️ This agent session was recovered after a crash.',\n '',\n '## Previous Context',\n `- Issue: ${state.issueId}`,\n `- Workspace: ${state.workspace}`,\n `- Started: ${state.startedAt}`,\n '',\n '## Recovery Steps',\n '1. Check beads for context: `bd show ' + state.issueId + '`',\n '2. Review recent git commits: `git log --oneline -10`',\n '3. Check hook for pending work: `pan work hook check`',\n '4. Resume from last known state',\n '',\n '## GUPP Reminder',\n '> \"If there is work on your Hook, YOU MUST RUN IT.\"',\n '',\n ];\n\n // Add GUPP work if available\n const { hasWork } = checkHook(state.id);\n if (hasWork) {\n const guppPrompt = generateGUPPPrompt(state.id);\n if (guppPrompt) {\n lines.push('---');\n lines.push('');\n lines.push(guppPrompt);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Auto-recover all crashed agents\n */\nexport function autoRecoverAgents(): { recovered: string[]; failed: string[] } {\n const crashed = detectCrashedAgents();\n const recovered: string[] = [];\n const failed: string[] = [];\n\n for (const agent of crashed) {\n try {\n const result = recoverAgent(agent.id);\n if (result) {\n recovered.push(agent.id);\n } else {\n failed.push(agent.id);\n }\n } catch (error) {\n failed.push(agent.id);\n }\n }\n\n return { recovered, failed };\n}\n\n/**\n * Check if Panopticon hooks are configured, and auto-setup if not\n */\nfunction checkAndSetupHooks(): void {\n const settingsPath = join(homedir(), '.claude', 'settings.json');\n const hookPath = join(homedir(), '.panopticon', 'bin', 'heartbeat-hook');\n\n // Check if settings.json exists and has heartbeat hook configured\n if (existsSync(settingsPath)) {\n try {\n const settingsContent = readFileSync(settingsPath, 'utf-8');\n const settings = JSON.parse(settingsContent);\n const postToolUse = settings?.hooks?.PostToolUse || [];\n\n const hookConfigured = postToolUse.some((hookConfig: any) =>\n hookConfig.hooks?.some((hook: any) =>\n hook.command === hookPath ||\n hook.command?.includes('panopticon') ||\n hook.command?.includes('heartbeat-hook')\n )\n );\n\n if (hookConfigured) {\n return; // Already configured\n }\n } catch {\n // Ignore errors, will attempt setup\n }\n }\n\n // Hooks not configured - run setup silently\n try {\n console.log('Configuring Panopticon heartbeat hooks...');\n execSync('pan setup hooks', { stdio: 'pipe' });\n console.log('✓ Heartbeat hooks configured');\n } catch (error) {\n console.warn('⚠ Failed to auto-configure hooks. Run `pan setup hooks` manually.');\n }\n}\n\n/**\n * Write task cache for heartbeat hook to use\n */\nfunction writeTaskCache(agentId: string, issueId: string): void {\n const cacheDir = join(getAgentDir(agentId));\n mkdirSync(cacheDir, { recursive: true });\n\n const cacheFile = join(cacheDir, 'current-task.json');\n writeFileSync(\n cacheFile,\n JSON.stringify({\n id: issueId,\n title: `Working on ${issueId}`,\n updated_at: new Date().toISOString()\n }, null, 2)\n );\n}\n","import { execSync } from 'child_process';\nimport { writeFileSync, chmodSync } from 'fs';\n\nexport interface TmuxSession {\n name: string;\n created: Date;\n attached: boolean;\n windows: number;\n}\n\nexport function listSessions(): TmuxSession[] {\n try {\n const output = execSync('tmux list-sessions -F \"#{session_name}|#{session_created}|#{session_attached}|#{session_windows}\"', {\n encoding: 'utf8',\n });\n\n return output.trim().split('\\n').filter(Boolean).map(line => {\n const [name, created, attached, windows] = line.split('|');\n return {\n name,\n created: new Date(parseInt(created) * 1000),\n attached: attached === '1',\n windows: parseInt(windows),\n };\n });\n } catch {\n return []; // No sessions\n }\n}\n\nexport function sessionExists(name: string): boolean {\n try {\n execSync(`tmux has-session -t ${name} 2>/dev/null`);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function createSession(\n name: string,\n cwd: string,\n initialCommand?: string,\n options?: { env?: Record<string, string> }\n): void {\n const escapedCwd = cwd.replace(/\"/g, '\\\\\"');\n\n // Build environment variable flags for tmux\n let envFlags = '';\n if (options?.env) {\n for (const [key, value] of Object.entries(options.env)) {\n envFlags += ` -e ${key}=\"${value.replace(/\"/g, '\\\\\"')}\"`;\n }\n }\n\n // For complex commands (with special chars), start session first then send command\n if (initialCommand && (initialCommand.includes('`') || initialCommand.includes('\\n') || initialCommand.length > 500)) {\n // Create session without command\n execSync(`tmux new-session -d -s ${name} -c \"${escapedCwd}\"${envFlags}`);\n\n // Small delay to let session initialize\n execSync('sleep 0.5');\n\n // Send the command in chunks if needed (tmux has buffer limits)\n // First, write to a temp file and source it\n const tmpFile = `/tmp/pan-cmd-${name}.sh`;\n writeFileSync(tmpFile, initialCommand);\n chmodSync(tmpFile, '755');\n\n // Execute the script\n execSync(`tmux send-keys -t ${name} \"bash ${tmpFile}\" Enter`);\n } else if (initialCommand) {\n // Simple command - use inline\n const cmd = `tmux new-session -d -s ${name} -c \"${escapedCwd}\"${envFlags} \"${initialCommand.replace(/\"/g, '\\\\\"')}\"`;\n execSync(cmd);\n } else {\n execSync(`tmux new-session -d -s ${name} -c \"${escapedCwd}\"${envFlags}`);\n }\n}\n\nexport function killSession(name: string): void {\n execSync(`tmux kill-session -t ${name}`);\n}\n\nexport function sendKeys(sessionName: string, keys: string): void {\n // CRITICAL: Send keys and Enter as separate commands\n // This is the correct way - combining them doesn't work\n const escapedKeys = keys.replace(/\"/g, '\\\\\"');\n execSync(`tmux send-keys -t ${sessionName} \"${escapedKeys}\"`);\n execSync(`tmux send-keys -t ${sessionName} Enter`);\n}\n\nexport function capturePane(sessionName: string, lines: number = 50): string {\n try {\n return execSync(`tmux capture-pane -t ${sessionName} -p -S -${lines}`, {\n encoding: 'utf8',\n });\n } catch {\n return '';\n }\n}\n\nexport function getAgentSessions(): TmuxSession[] {\n return listSessions().filter(s => s.name.startsWith('agent-'));\n}\n","/**\n * GUPP Hooks System\n *\n * \"If there is work on your Hook, YOU MUST RUN IT.\"\n *\n * Hooks are persistent work queues for agents. When an agent starts,\n * it checks its hook for pending work and executes immediately.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from './paths.js';\n\nexport interface HookItem {\n id: string;\n type: 'task' | 'message' | 'notification';\n priority: 'urgent' | 'high' | 'normal' | 'low';\n source: string;\n payload: {\n issueId?: string;\n message?: string;\n action?: string;\n context?: Record<string, any>;\n };\n createdAt: string;\n expiresAt?: string;\n}\n\nexport interface Hook {\n agentId: string;\n items: HookItem[];\n lastChecked?: string;\n}\n\nfunction getHookDir(agentId: string): string {\n return join(AGENTS_DIR, agentId);\n}\n\nfunction getHookFile(agentId: string): string {\n return join(getHookDir(agentId), 'hook.json');\n}\n\nfunction getMailDir(agentId: string): string {\n return join(getHookDir(agentId), 'mail');\n}\n\n/**\n * Initialize hook structure for an agent\n */\nexport function initHook(agentId: string): void {\n const hookDir = getHookDir(agentId);\n const mailDir = getMailDir(agentId);\n\n mkdirSync(hookDir, { recursive: true });\n mkdirSync(mailDir, { recursive: true });\n\n const hookFile = getHookFile(agentId);\n if (!existsSync(hookFile)) {\n const hook: Hook = {\n agentId,\n items: [],\n };\n writeFileSync(hookFile, JSON.stringify(hook, null, 2));\n }\n}\n\n/**\n * Get the hook for an agent\n */\nexport function getHook(agentId: string): Hook | null {\n const hookFile = getHookFile(agentId);\n if (!existsSync(hookFile)) {\n return null;\n }\n\n try {\n const content = readFileSync(hookFile, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Add work to an agent's hook (GUPP trigger)\n */\nexport function pushToHook(agentId: string, item: Omit<HookItem, 'id' | 'createdAt'>): HookItem {\n initHook(agentId);\n\n const hook = getHook(agentId) || { agentId, items: [] };\n\n const newItem: HookItem = {\n ...item,\n id: `hook-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n createdAt: new Date().toISOString(),\n };\n\n hook.items.push(newItem);\n writeFileSync(getHookFile(agentId), JSON.stringify(hook, null, 2));\n\n return newItem;\n}\n\n/**\n * Check if agent has pending work (GUPP check)\n */\nexport function checkHook(agentId: string): { hasWork: boolean; urgentCount: number; items: HookItem[] } {\n const hook = getHook(agentId);\n\n if (!hook || hook.items.length === 0) {\n // Also check mail directory for incoming messages\n const mailDir = getMailDir(agentId);\n if (existsSync(mailDir)) {\n const mails = readdirSync(mailDir).filter((f) => f.endsWith('.json'));\n if (mails.length > 0) {\n // Convert mail to hook items\n const mailItems: HookItem[] = mails.map((file) => {\n try {\n const content = readFileSync(join(mailDir, file), 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n }).filter(Boolean) as HookItem[];\n\n return {\n hasWork: mailItems.length > 0,\n urgentCount: mailItems.filter((i) => i.priority === 'urgent').length,\n items: mailItems,\n };\n }\n }\n\n return { hasWork: false, urgentCount: 0, items: [] };\n }\n\n // Filter out expired items\n const now = new Date();\n const activeItems = hook.items.filter((item) => {\n if (item.expiresAt) {\n return new Date(item.expiresAt) > now;\n }\n return true;\n });\n\n // Sort by priority: urgent > high > normal > low\n const priorityOrder = { urgent: 0, high: 1, normal: 2, low: 3 };\n activeItems.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);\n\n return {\n hasWork: activeItems.length > 0,\n urgentCount: activeItems.filter((i) => i.priority === 'urgent').length,\n items: activeItems,\n };\n}\n\n/**\n * Pop the next work item from hook (after execution)\n */\nexport function popFromHook(agentId: string, itemId: string): boolean {\n const hook = getHook(agentId);\n if (!hook) return false;\n\n const index = hook.items.findIndex((i) => i.id === itemId);\n if (index === -1) return false;\n\n hook.items.splice(index, 1);\n hook.lastChecked = new Date().toISOString();\n writeFileSync(getHookFile(agentId), JSON.stringify(hook, null, 2));\n\n return true;\n}\n\n/**\n * Clear all items from hook\n */\nexport function clearHook(agentId: string): void {\n const hook = getHook(agentId);\n if (!hook) return;\n\n hook.items = [];\n hook.lastChecked = new Date().toISOString();\n writeFileSync(getHookFile(agentId), JSON.stringify(hook, null, 2));\n}\n\n/**\n * Send a message to an agent's mailbox\n */\nexport function sendMail(\n toAgentId: string,\n from: string,\n message: string,\n priority: HookItem['priority'] = 'normal'\n): void {\n initHook(toAgentId);\n const mailDir = getMailDir(toAgentId);\n\n const mailItem: HookItem = {\n id: `mail-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n type: 'message',\n priority,\n source: from,\n payload: { message },\n createdAt: new Date().toISOString(),\n };\n\n writeFileSync(\n join(mailDir, `${mailItem.id}.json`),\n JSON.stringify(mailItem, null, 2)\n );\n}\n\n/**\n * Get and clear mail for an agent\n */\nexport function collectMail(agentId: string): HookItem[] {\n const mailDir = getMailDir(agentId);\n if (!existsSync(mailDir)) return [];\n\n const mails: HookItem[] = [];\n const files = readdirSync(mailDir).filter((f) => f.endsWith('.json'));\n\n for (const file of files) {\n const filePath = join(mailDir, file);\n try {\n const content = readFileSync(filePath, 'utf-8');\n mails.push(JSON.parse(content));\n unlinkSync(filePath); // Remove after reading\n } catch {\n // Skip invalid mail\n }\n }\n\n return mails;\n}\n\n/**\n * Generate GUPP prompt for agent startup\n */\nexport function generateGUPPPrompt(agentId: string): string | null {\n const { hasWork, urgentCount, items } = checkHook(agentId);\n\n if (!hasWork) return null;\n\n const lines: string[] = [\n '# GUPP: Work Found on Your Hook',\n '',\n '> \"If there is work on your Hook, YOU MUST RUN IT.\"',\n '',\n ];\n\n if (urgentCount > 0) {\n lines.push(`⚠️ **${urgentCount} URGENT item(s) require immediate attention**`);\n lines.push('');\n }\n\n lines.push(`## Pending Work Items (${items.length})`);\n lines.push('');\n\n for (const item of items) {\n const priorityEmoji = {\n urgent: '🔴',\n high: '🟠',\n normal: '🟢',\n low: '⚪',\n }[item.priority];\n\n lines.push(`### ${priorityEmoji} ${item.type.toUpperCase()}: ${item.id}`);\n lines.push(`- Source: ${item.source}`);\n lines.push(`- Created: ${item.createdAt}`);\n\n if (item.payload.issueId) {\n lines.push(`- Issue: ${item.payload.issueId}`);\n }\n if (item.payload.message) {\n lines.push(`- Message: ${item.payload.message}`);\n }\n if (item.payload.action) {\n lines.push(`- Action: ${item.payload.action}`);\n }\n lines.push('');\n }\n\n lines.push('---');\n lines.push('');\n lines.push('Execute these items in priority order. Use `bd hook pop <id>` after completing each item.');\n\n return lines.join('\\n');\n}\n","/**\n * Agent CV (Work History) System\n *\n * Tracks agent performance over time to enable capability-based routing.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from './paths.js';\n\nexport interface WorkEntry {\n issueId: string;\n startedAt: string;\n completedAt?: string;\n outcome: 'success' | 'failed' | 'abandoned' | 'in_progress';\n duration?: number; // minutes\n skills?: string[];\n failureReason?: string;\n commits?: number;\n linesChanged?: number;\n}\n\nexport interface AgentCV {\n agentId: string;\n createdAt: string;\n lastActive: string;\n runtime: string;\n model: string;\n stats: {\n totalIssues: number;\n successCount: number;\n failureCount: number;\n abandonedCount: number;\n avgDuration: number; // minutes\n successRate: number; // 0-1\n };\n skillsUsed: string[];\n recentWork: WorkEntry[];\n}\n\nfunction getCVFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'cv.json');\n}\n\n/**\n * Get or create an agent's CV\n */\nexport function getAgentCV(agentId: string): AgentCV {\n const cvFile = getCVFile(agentId);\n\n if (existsSync(cvFile)) {\n try {\n return JSON.parse(readFileSync(cvFile, 'utf-8'));\n } catch {}\n }\n\n // Create new CV\n const cv: AgentCV = {\n agentId,\n createdAt: new Date().toISOString(),\n lastActive: new Date().toISOString(),\n runtime: 'claude',\n model: 'sonnet',\n stats: {\n totalIssues: 0,\n successCount: 0,\n failureCount: 0,\n abandonedCount: 0,\n avgDuration: 0,\n successRate: 0,\n },\n skillsUsed: [],\n recentWork: [],\n };\n\n saveAgentCV(cv);\n return cv;\n}\n\n/**\n * Save an agent's CV\n */\nexport function saveAgentCV(cv: AgentCV): void {\n const dir = join(AGENTS_DIR, cv.agentId);\n mkdirSync(dir, { recursive: true });\n writeFileSync(getCVFile(cv.agentId), JSON.stringify(cv, null, 2));\n}\n\n/**\n * Start tracking work for an agent\n */\nexport function startWork(agentId: string, issueId: string, skills?: string[]): void {\n const cv = getAgentCV(agentId);\n\n const entry: WorkEntry = {\n issueId,\n startedAt: new Date().toISOString(),\n outcome: 'in_progress',\n skills,\n };\n\n cv.recentWork.unshift(entry);\n cv.stats.totalIssues++;\n cv.lastActive = new Date().toISOString();\n\n // Track skills\n if (skills) {\n for (const skill of skills) {\n if (!cv.skillsUsed.includes(skill)) {\n cv.skillsUsed.push(skill);\n }\n }\n }\n\n // Keep only last 50 entries\n if (cv.recentWork.length > 50) {\n cv.recentWork = cv.recentWork.slice(0, 50);\n }\n\n saveAgentCV(cv);\n}\n\n/**\n * Complete work for an agent\n */\nexport function completeWork(\n agentId: string,\n issueId: string,\n outcome: 'success' | 'failed' | 'abandoned',\n details?: { commits?: number; linesChanged?: number; failureReason?: string }\n): void {\n const cv = getAgentCV(agentId);\n\n // Find the work entry\n const entry = cv.recentWork.find(\n (w) => w.issueId === issueId && w.outcome === 'in_progress'\n );\n\n if (entry) {\n entry.outcome = outcome;\n entry.completedAt = new Date().toISOString();\n entry.duration = Math.round(\n (new Date().getTime() - new Date(entry.startedAt).getTime()) / (1000 * 60)\n );\n if (details?.commits) entry.commits = details.commits;\n if (details?.linesChanged) entry.linesChanged = details.linesChanged;\n if (details?.failureReason) entry.failureReason = details.failureReason;\n }\n\n // Update stats\n if (outcome === 'success') {\n cv.stats.successCount++;\n } else if (outcome === 'failed') {\n cv.stats.failureCount++;\n } else if (outcome === 'abandoned') {\n cv.stats.abandonedCount++;\n }\n\n // Calculate success rate\n const completed = cv.stats.successCount + cv.stats.failureCount + cv.stats.abandonedCount;\n cv.stats.successRate = completed > 0 ? cv.stats.successCount / completed : 0;\n\n // Calculate average duration (only from completed work)\n const completedEntries = cv.recentWork.filter(\n (w) => w.duration !== undefined && w.outcome !== 'in_progress'\n );\n if (completedEntries.length > 0) {\n const totalDuration = completedEntries.reduce((sum, w) => sum + (w.duration || 0), 0);\n cv.stats.avgDuration = Math.round(totalDuration / completedEntries.length);\n }\n\n cv.lastActive = new Date().toISOString();\n saveAgentCV(cv);\n}\n\n/**\n * Get agent rankings by success rate\n */\nexport function getAgentRankings(): Array<{\n agentId: string;\n successRate: number;\n totalIssues: number;\n avgDuration: number;\n}> {\n const rankings: Array<{\n agentId: string;\n successRate: number;\n totalIssues: number;\n avgDuration: number;\n }> = [];\n\n if (!existsSync(AGENTS_DIR)) return rankings;\n\n const dirs = readdirSync(AGENTS_DIR, { withFileTypes: true }).filter(\n (d) => d.isDirectory()\n );\n\n for (const dir of dirs) {\n const cv = getAgentCV(dir.name);\n if (cv.stats.totalIssues > 0) {\n rankings.push({\n agentId: dir.name,\n successRate: cv.stats.successRate,\n totalIssues: cv.stats.totalIssues,\n avgDuration: cv.stats.avgDuration,\n });\n }\n }\n\n // Sort by success rate, then by total issues\n rankings.sort((a, b) => {\n if (b.successRate !== a.successRate) {\n return b.successRate - a.successRate;\n }\n return b.totalIssues - a.totalIssues;\n });\n\n return rankings;\n}\n\n/**\n * Format CV for display\n */\nexport function formatCV(cv: AgentCV): string {\n const lines: string[] = [\n `# Agent CV: ${cv.agentId}`,\n '',\n `Runtime: ${cv.runtime} (${cv.model})`,\n `Created: ${cv.createdAt}`,\n `Last Active: ${cv.lastActive}`,\n '',\n '## Statistics',\n '',\n `- Total Issues: ${cv.stats.totalIssues}`,\n `- Success Rate: ${(cv.stats.successRate * 100).toFixed(1)}%`,\n `- Successes: ${cv.stats.successCount}`,\n `- Failures: ${cv.stats.failureCount}`,\n `- Abandoned: ${cv.stats.abandonedCount}`,\n `- Avg Duration: ${cv.stats.avgDuration} minutes`,\n '',\n ];\n\n if (cv.skillsUsed.length > 0) {\n lines.push('## Skills Used');\n lines.push('');\n lines.push(cv.skillsUsed.join(', '));\n lines.push('');\n }\n\n if (cv.recentWork.length > 0) {\n lines.push('## Recent Work');\n lines.push('');\n\n for (const work of cv.recentWork.slice(0, 10)) {\n const statusIcon = {\n success: '✓',\n failed: '✗',\n abandoned: '⊘',\n in_progress: '●',\n }[work.outcome];\n\n const duration = work.duration ? ` (${work.duration}m)` : '';\n lines.push(`${statusIcon} ${work.issueId}${duration}`);\n\n if (work.failureReason) {\n lines.push(` Reason: ${work.failureReason}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","import chalk from 'chalk';\nimport { listRunningAgents } from '../../../lib/agents.js';\n\ninterface StatusOptions {\n json?: boolean;\n}\n\nexport async function statusCommand(options: StatusOptions): Promise<void> {\n const agents = listRunningAgents();\n\n if (options.json) {\n console.log(JSON.stringify(agents, null, 2));\n return;\n }\n\n if (agents.length === 0) {\n console.log(chalk.dim('No running agents.'));\n console.log(chalk.dim('Use \"pan work issue <id>\" to spawn one.'));\n return;\n }\n\n console.log(chalk.bold('\\nRunning Agents\\n'));\n\n for (const agent of agents) {\n const statusColor = agent.tmuxActive ? chalk.green : chalk.red;\n const status = agent.tmuxActive ? 'running' : 'stopped';\n\n const startedAt = new Date(agent.startedAt);\n const duration = Math.floor((Date.now() - startedAt.getTime()) / 1000 / 60);\n\n console.log(`${chalk.cyan(agent.id)}`);\n console.log(` Issue: ${agent.issueId}`);\n console.log(` Status: ${statusColor(status)}`);\n console.log(` Runtime: ${agent.runtime} (${agent.model})`);\n console.log(` Duration: ${duration} min`);\n console.log(` Workspace: ${chalk.dim(agent.workspace)}`);\n console.log('');\n }\n}\n","import chalk from 'chalk';\nimport { messageAgent } from '../../../lib/agents.js';\n\nexport async function tellCommand(id: string, message: string): Promise<void> {\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n\n try {\n messageAgent(agentId, message);\n console.log(chalk.green('Message sent to ' + agentId));\n console.log(chalk.dim(` \"${message}\"`));\n } catch (error: any) {\n console.error(chalk.red('Error: ' + error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { stopAgent, getAgentState } from '../../../lib/agents.js';\nimport { sessionExists } from '../../../lib/tmux.js';\n\ninterface KillOptions {\n force?: boolean;\n}\n\nexport async function killCommand(id: string, options: KillOptions): Promise<void> {\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n\n // Check if exists\n const state = getAgentState(agentId);\n const isRunning = sessionExists(agentId);\n\n if (!state && !isRunning) {\n console.log(chalk.yellow(`Agent ${agentId} not found.`));\n return;\n }\n\n if (!options.force && isRunning) {\n // In a real implementation, we'd prompt for confirmation\n // For now, just proceed\n }\n\n try {\n stopAgent(agentId);\n console.log(chalk.green(`Killed agent: ${agentId}`));\n } catch (error: any) {\n console.error(chalk.red('Error: ' + error.message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { listRunningAgents } from '../../../lib/agents.js';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from '../../../lib/paths.js';\n\nexport async function pendingCommand(): Promise<void> {\n // Find agents with completed work (status file or convention)\n // For now, show stopped agents that might have completed work\n\n const agents = listRunningAgents().filter(a => !a.tmuxActive && a.status !== 'error');\n\n if (agents.length === 0) {\n console.log(chalk.dim('No pending reviews.'));\n console.log(chalk.dim('Agents will appear here when they complete work.'));\n return;\n }\n\n console.log(chalk.bold('\\nPending Reviews\\n'));\n\n for (const agent of agents) {\n console.log(`${chalk.cyan(agent.issueId)}`);\n console.log(` Agent: ${agent.id}`);\n console.log(` Workspace: ${chalk.dim(agent.workspace)}`);\n\n // Check for completion notes\n const completionFile = join(AGENTS_DIR, agent.id, 'completion.md');\n if (existsSync(completionFile)) {\n const content = readFileSync(completionFile, 'utf8');\n const firstLine = content.split('\\n').find(l => l.trim() && !l.startsWith('#'));\n if (firstLine) {\n console.log(` Summary: ${chalk.dim(firstLine.trim())}`);\n }\n }\n\n console.log('');\n }\n\n console.log(chalk.dim('Run \"pan work approve <id>\" to approve and merge.'));\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAgentState, saveAgentState } from '../../../lib/agents.js';\nimport { existsSync, writeFileSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { execSync } from 'child_process';\nimport { AGENTS_DIR } from '../../../lib/paths.js';\n\ninterface ApproveOptions {\n merge?: boolean;\n noLinear?: boolean;\n}\n\nfunction getLinearApiKey(): string | null {\n const envFile = join(homedir(), '.panopticon.env');\n if (existsSync(envFile)) {\n const content = readFileSync(envFile, 'utf-8');\n const match = content.match(/LINEAR_API_KEY=(.+)/);\n if (match) return match[1].trim();\n }\n return process.env.LINEAR_API_KEY || null;\n}\n\nfunction checkGhCli(): boolean {\n try {\n execSync('which gh', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findPRForBranch(workspace: string): { number: number; url: string } | null {\n try {\n // Get current branch\n const branch = execSync('git rev-parse --abbrev-ref HEAD', {\n cwd: workspace,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n // Find PR for this branch\n const prJson = execSync(`gh pr list --head \"${branch}\" --json number,url --limit 1`, {\n cwd: workspace,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const prs = JSON.parse(prJson);\n if (prs.length > 0) {\n return { number: prs[0].number, url: prs[0].url };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction mergePR(workspace: string, prNumber: number): { success: boolean; error?: string } {\n try {\n execSync(`gh pr merge ${prNumber} --squash --delete-branch`, {\n cwd: workspace,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return { success: true };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nasync function updateLinearStatus(apiKey: string, issueIdentifier: string): Promise<boolean> {\n try {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey });\n\n // Get the team and find the Done state\n const me = await client.viewer;\n const teams = await me.teams();\n const team = teams.nodes[0];\n\n if (!team) return false;\n\n // Find the issue\n const issues = await team.issues({ first: 100 });\n const issue = issues.nodes.find(\n (i) => i.identifier.toUpperCase() === issueIdentifier.toUpperCase()\n );\n\n if (!issue) return false;\n\n // Find the Done state\n const states = await team.states();\n const doneState = states.nodes.find((s) => s.type === 'completed' && s.name === 'Done');\n\n if (!doneState) return false;\n\n // Update issue\n await issue.update({ stateId: doneState.id });\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function approveCommand(id: string, options: ApproveOptions = {}): Promise<void> {\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n const state = getAgentState(agentId);\n\n if (!state) {\n console.log(chalk.yellow(`Agent ${agentId} not found.`));\n console.log(chalk.dim('Run \"pan work status\" to see running agents.'));\n return;\n }\n\n const spinner = ora('Approving work...').start();\n\n try {\n const workspace = state.workspace;\n let prMerged = false;\n let linearUpdated = false;\n\n // Step 1: Find and merge PR if requested\n if (options.merge !== false) {\n if (!checkGhCli()) {\n spinner.warn('gh CLI not found - skipping PR merge');\n console.log(chalk.dim(' Install: https://cli.github.com/'));\n } else {\n spinner.text = 'Looking for PR...';\n const pr = findPRForBranch(workspace);\n\n if (pr) {\n spinner.text = `Merging PR #${pr.number}...`;\n const result = mergePR(workspace, pr.number);\n\n if (result.success) {\n prMerged = true;\n console.log(chalk.green(` ✓ Merged PR #${pr.number}`));\n } else {\n console.log(chalk.yellow(` ⚠ Failed to merge: ${result.error}`));\n console.log(chalk.dim(` Merge manually: gh pr merge ${pr.number} --squash`));\n }\n } else {\n console.log(chalk.dim(' No PR found for this branch'));\n }\n }\n }\n\n // Step 2: Update Linear status\n if (options.noLinear !== true) {\n const apiKey = getLinearApiKey();\n if (apiKey) {\n spinner.text = 'Updating Linear status...';\n linearUpdated = await updateLinearStatus(apiKey, state.issueId);\n if (linearUpdated) {\n console.log(chalk.green(` ✓ Updated ${state.issueId} to Done`));\n } else {\n console.log(chalk.yellow(` ⚠ Failed to update Linear status`));\n }\n } else {\n console.log(chalk.dim(' LINEAR_API_KEY not set - skipping status update'));\n }\n }\n\n // Step 3: Update agent state\n state.status = 'stopped';\n state.lastActivity = new Date().toISOString();\n saveAgentState(state);\n\n // Mark as approved\n const approvedFile = join(AGENTS_DIR, agentId, 'approved');\n writeFileSync(approvedFile, JSON.stringify({\n timestamp: new Date().toISOString(),\n prMerged,\n linearUpdated,\n }));\n\n spinner.succeed(`Approved: ${state.issueId}`);\n console.log('');\n\n // Summary\n console.log(chalk.bold('Summary:'));\n console.log(` Issue: ${chalk.cyan(state.issueId)}`);\n console.log(` PR: ${prMerged ? chalk.green('Merged') : chalk.dim('Not merged')}`);\n console.log(` Linear: ${linearUpdated ? chalk.green('Updated to Done') : chalk.dim('Not updated')}`);\n console.log('');\n\n console.log(chalk.dim('Workspace can be cleaned up with:'));\n console.log(chalk.dim(` pan workspace destroy ${state.issueId}`));\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport inquirer from 'inquirer';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { execSync } from 'child_process';\n\ninterface PlanOptions {\n output?: string;\n json?: boolean;\n skipDiscovery?: boolean;\n force?: boolean;\n}\n\ninterface LinearIssue {\n id: string;\n identifier: string;\n title: string;\n description?: string;\n state: { name: string };\n priority: number;\n url: string;\n labels?: { name: string }[];\n assignee?: { name: string };\n project?: { name: string };\n}\n\ninterface ComplexityAnalysis {\n isComplex: boolean;\n reasons: string[];\n subsystems: string[];\n estimatedTasks: number;\n}\n\ninterface PlanTask {\n name: string;\n description: string;\n dependsOn?: string;\n}\n\ninterface DiscoveryDecision {\n question: string;\n answer: string;\n}\n\nfunction getLinearApiKey(): string | null {\n const envFile = join(homedir(), '.panopticon.env');\n if (existsSync(envFile)) {\n const content = readFileSync(envFile, 'utf-8');\n const match = content.match(/LINEAR_API_KEY=(.+)/);\n if (match) return match[1].trim();\n }\n return process.env.LINEAR_API_KEY || null;\n}\n\nfunction findPRDFiles(issueId: string): string[] {\n const found: string[] = [];\n const cwd = process.cwd();\n\n const searchPaths = [\n 'docs/prds/active',\n 'docs/prds/planned',\n 'docs/prds',\n 'docs/prd',\n 'prds',\n 'docs',\n ];\n\n const issueIdLower = issueId.toLowerCase();\n\n for (const searchPath of searchPaths) {\n const fullPath = join(cwd, searchPath);\n if (!existsSync(fullPath)) continue;\n\n try {\n const result = execSync(\n `find \"${fullPath}\" -type f -name \"*.md\" 2>/dev/null | xargs grep -l -i \"${issueIdLower}\" 2>/dev/null || true`,\n { encoding: 'utf-8' }\n );\n\n const files = result.trim().split('\\n').filter(f => f);\n found.push(...files);\n } catch {\n // Ignore search errors\n }\n }\n\n return [...new Set(found)];\n}\n\n/**\n * Analyze issue complexity to determine if full planning is needed\n */\nfunction analyzeComplexity(issue: LinearIssue, prdFiles: string[]): ComplexityAnalysis {\n const reasons: string[] = [];\n const subsystems: string[] = [];\n let estimatedTasks = 1;\n\n const desc = (issue.description || '').toLowerCase();\n const title = issue.title.toLowerCase();\n const combined = `${title} ${desc}`;\n\n // Check for multiple subsystems\n if (combined.includes('frontend') || combined.includes('ui') || combined.includes('component')) {\n subsystems.push('frontend');\n }\n if (combined.includes('backend') || combined.includes('api') || combined.includes('endpoint')) {\n subsystems.push('backend');\n }\n if (combined.includes('database') || combined.includes('migration') || combined.includes('schema')) {\n subsystems.push('database');\n }\n if (combined.includes('test') || combined.includes('e2e') || combined.includes('playwright')) {\n subsystems.push('tests');\n }\n\n if (subsystems.length > 1) {\n reasons.push(`Multiple subsystems involved: ${subsystems.join(', ')}`);\n estimatedTasks += subsystems.length;\n }\n\n // Check for ambiguous requirements\n const ambiguousPatterns = [\n 'should we', 'maybe', 'or', 'consider', 'option', 'approach',\n 'tbd', 'to be determined', 'needs discussion', 'unclear'\n ];\n for (const pattern of ambiguousPatterns) {\n if (combined.includes(pattern)) {\n reasons.push('Requirements may be ambiguous');\n break;\n }\n }\n\n // Check for architecture keywords\n const architecturePatterns = [\n 'refactor', 'architecture', 'redesign', 'restructure', 'migrate',\n 'integration', 'authentication', 'authorization', 'security'\n ];\n for (const pattern of architecturePatterns) {\n if (combined.includes(pattern)) {\n reasons.push(`Architecture decision needed: ${pattern}`);\n estimatedTasks += 2;\n break;\n }\n }\n\n // Check description length (longer = more complex usually)\n if (desc.length > 500) {\n reasons.push('Detailed description suggests complexity');\n estimatedTasks += 1;\n }\n\n // Check for existing PRD (pre-done discovery)\n if (prdFiles.length > 0) {\n reasons.push(`PRD exists - complexity already documented`);\n }\n\n // Check labels for complexity hints\n const complexLabels = ['complex', 'large', 'epic', 'multi-phase', 'architecture'];\n for (const label of issue.labels || []) {\n if (complexLabels.some(cl => label.name.toLowerCase().includes(cl))) {\n reasons.push(`Label indicates complexity: ${label.name}`);\n estimatedTasks += 2;\n }\n }\n\n const isComplex = reasons.length >= 2 || subsystems.length > 1 || estimatedTasks >= 4;\n\n return {\n isComplex,\n reasons,\n subsystems,\n estimatedTasks: Math.max(estimatedTasks, subsystems.length + 1),\n };\n}\n\n/**\n * Run discovery phase - ask clarifying questions\n */\nasync function runDiscoveryPhase(\n issue: LinearIssue,\n complexity: ComplexityAnalysis,\n prdContent?: string\n): Promise<{ tasks: PlanTask[]; decisions: DiscoveryDecision[] }> {\n const decisions: DiscoveryDecision[] = [];\n const tasks: PlanTask[] = [];\n\n console.log('');\n console.log(chalk.bold.cyan('═══════════════════════════════════════════════════════════'));\n console.log(chalk.bold.cyan(' DISCOVERY PHASE'));\n console.log(chalk.bold.cyan('═══════════════════════════════════════════════════════════'));\n console.log('');\n console.log(chalk.dim('Answer questions to create a detailed execution plan.'));\n console.log(chalk.dim('Press Enter to skip optional questions.'));\n console.log('');\n\n // Show what we know\n console.log(chalk.bold('Issue:'), `${issue.identifier} - ${issue.title}`);\n if (complexity.subsystems.length > 0) {\n console.log(chalk.bold('Detected subsystems:'), complexity.subsystems.join(', '));\n }\n console.log('');\n\n // Q1: Scope clarification\n const scopeAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'scope',\n message: 'What specific changes are needed? (be specific about files/components):',\n default: issue.description?.slice(0, 100) || '',\n }]);\n if (scopeAnswer.scope) {\n decisions.push({ question: 'Scope', answer: scopeAnswer.scope });\n }\n\n // Q2: Technical approach\n const approachAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'approach',\n message: 'Any specific technical approach or patterns to follow?',\n }]);\n if (approachAnswer.approach) {\n decisions.push({ question: 'Technical approach', answer: approachAnswer.approach });\n }\n\n // Q3: Edge cases\n const edgeCasesAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'edgeCases',\n message: 'Any edge cases or error scenarios to handle?',\n }]);\n if (edgeCasesAnswer.edgeCases) {\n decisions.push({ question: 'Edge cases', answer: edgeCasesAnswer.edgeCases });\n }\n\n // Q4: Testing requirements\n const testingAnswer = await inquirer.prompt([{\n type: 'checkbox',\n name: 'testing',\n message: 'What testing is required?',\n choices: [\n { name: 'Unit tests', value: 'unit', checked: true },\n { name: 'Integration tests', value: 'integration' },\n { name: 'E2E tests (Playwright)', value: 'e2e' },\n { name: 'Manual testing only', value: 'manual' },\n ],\n }]);\n if (testingAnswer.testing.length > 0) {\n decisions.push({ question: 'Testing', answer: testingAnswer.testing.join(', ') });\n }\n\n // Q5: Out of scope\n const outOfScopeAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'outOfScope',\n message: 'Anything explicitly OUT of scope for this issue?',\n }]);\n if (outOfScopeAnswer.outOfScope) {\n decisions.push({ question: 'Out of scope', answer: outOfScopeAnswer.outOfScope });\n }\n\n // Q6: Define tasks\n console.log('');\n console.log(chalk.bold('Define execution tasks:'));\n console.log(chalk.dim('Enter tasks in order. Empty task name to finish.'));\n console.log('');\n\n // Start with standard tasks based on complexity\n const suggestedTasks: PlanTask[] = [\n { name: 'Understand requirements', description: 'Review issue, PRD, and existing code' },\n ];\n\n if (complexity.subsystems.length > 1) {\n suggestedTasks.push({ name: 'Design approach', description: 'Document architecture decisions', dependsOn: 'Understand requirements' });\n }\n\n for (const subsystem of complexity.subsystems) {\n suggestedTasks.push({\n name: `Implement ${subsystem}`,\n description: `Core ${subsystem} changes`,\n dependsOn: complexity.subsystems.length > 1 ? 'Design approach' : 'Understand requirements',\n });\n }\n\n if (suggestedTasks.length === 1) {\n suggestedTasks.push({ name: 'Implement changes', description: 'Core implementation', dependsOn: 'Understand requirements' });\n }\n\n if (testingAnswer.testing.includes('unit') || testingAnswer.testing.includes('integration')) {\n suggestedTasks.push({ name: 'Add tests', description: 'Unit and/or integration tests', dependsOn: suggestedTasks[suggestedTasks.length - 1].name });\n }\n\n if (testingAnswer.testing.includes('e2e')) {\n suggestedTasks.push({ name: 'Add E2E tests', description: 'Playwright E2E tests', dependsOn: 'Add tests' });\n }\n\n suggestedTasks.push({ name: 'Verify and cleanup', description: 'Lint, type check, final review', dependsOn: suggestedTasks[suggestedTasks.length - 1].name });\n\n // Show suggested tasks and let user modify\n console.log(chalk.bold('Suggested tasks:'));\n for (let i = 0; i < suggestedTasks.length; i++) {\n const task = suggestedTasks[i];\n console.log(` ${i + 1}. ${task.name}${task.dependsOn ? chalk.dim(` (after: ${task.dependsOn})`) : ''}`);\n }\n console.log('');\n\n const useDefaultAnswer = await inquirer.prompt([{\n type: 'confirm',\n name: 'useDefault',\n message: 'Use these suggested tasks?',\n default: true,\n }]);\n\n if (useDefaultAnswer.useDefault) {\n tasks.push(...suggestedTasks);\n } else {\n // Custom task entry\n let taskIndex = 1;\n let previousTask = '';\n\n while (true) {\n const taskAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'name',\n message: `Task ${taskIndex} name (empty to finish):`,\n }]);\n\n if (!taskAnswer.name) break;\n\n const descAnswer = await inquirer.prompt([{\n type: 'input',\n name: 'description',\n message: `Task ${taskIndex} description:`,\n default: taskAnswer.name,\n }]);\n\n tasks.push({\n name: taskAnswer.name,\n description: descAnswer.description,\n dependsOn: previousTask || undefined,\n });\n\n previousTask = taskAnswer.name;\n taskIndex++;\n }\n }\n\n return { tasks, decisions };\n}\n\n/**\n * Generate STATE.md content\n */\nfunction generateStateFile(\n issue: LinearIssue,\n decisions: DiscoveryDecision[],\n tasks: PlanTask[]\n): string {\n const lines: string[] = [\n `# Agent State: ${issue.identifier}`,\n '',\n `**Last Updated:** ${new Date().toISOString()}`,\n '',\n '## Current Position',\n '',\n `- **Issue:** ${issue.identifier}`,\n `- **Title:** ${issue.title}`,\n `- **Status:** Planning complete, ready for execution`,\n `- **Linear:** ${issue.url}`,\n '',\n '## Decisions Made During Planning',\n '',\n ];\n\n if (decisions.length > 0) {\n for (const decision of decisions) {\n lines.push(`- **${decision.question}:** ${decision.answer}`);\n }\n } else {\n lines.push('- No specific decisions recorded');\n }\n\n lines.push('');\n lines.push('## Planned Tasks');\n lines.push('');\n\n for (const task of tasks) {\n lines.push(`- [ ] ${task.name}${task.dependsOn ? ` (after: ${task.dependsOn})` : ''}`);\n }\n\n lines.push('');\n lines.push('## Blockers/Concerns');\n lines.push('');\n lines.push('- None identified during planning');\n lines.push('');\n lines.push('## Notes');\n lines.push('');\n lines.push('<!-- Add notes as work progresses -->');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate WORKSPACE.md content\n */\nfunction generateWorkspaceFile(issue: LinearIssue, prdFiles: string[]): string {\n const lines: string[] = [\n `# Workspace: ${issue.identifier}`,\n '',\n `> ${issue.title}`,\n '',\n '## Quick Links',\n '',\n `- [Linear Issue](${issue.url})`,\n ];\n\n for (const prd of prdFiles) {\n const relativePath = prd.replace(process.cwd() + '/', '');\n lines.push(`- [PRD](${relativePath})`);\n }\n\n lines.push('');\n lines.push('## Context Files');\n lines.push('');\n lines.push('- `STATE.md` - Current progress and decisions');\n lines.push('- `WORKSPACE.md` - This file');\n lines.push('');\n lines.push('## Beads');\n lines.push('');\n lines.push('Check current task status:');\n lines.push('```bash');\n lines.push('bd ready # Next actionable task');\n lines.push(`bd list --tag ${issue.identifier} # All tasks for this issue`);\n lines.push('```');\n lines.push('');\n lines.push('## Agent Instructions');\n lines.push('');\n lines.push('1. Run `bd ready` to get next task');\n lines.push('2. Complete the task following relevant skills');\n lines.push('3. Run `bd close \"<task name>\" --reason \"...\"` when done');\n lines.push('4. Update STATE.md with progress');\n lines.push('5. Repeat until all tasks complete');\n lines.push('');\n lines.push('## CRITICAL: Work Completion Requirements');\n lines.push('');\n lines.push('**You are NOT done until ALL of these are true:**');\n lines.push('');\n lines.push('1. **Tests pass** - Run the full test suite');\n lines.push('2. **All changes committed** - `git status` shows \"nothing to commit\"');\n lines.push('3. **Pushed to remote** - `git push`');\n lines.push('');\n lines.push('**Uncommitted changes = NOT COMPLETE.**');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Create Beads tasks with dependencies\n */\nfunction createBeadsTasks(issue: LinearIssue, tasks: PlanTask[]): { success: boolean; created: string[]; errors: string[] } {\n const created: string[] = [];\n const errors: string[] = [];\n const taskIds: Map<string, string> = new Map();\n\n // Check if bd is available\n try {\n execSync('which bd', { encoding: 'utf-8' });\n } catch {\n return { success: false, created: [], errors: ['bd (beads) CLI not found in PATH'] };\n }\n\n for (const task of tasks) {\n const fullName = `${issue.identifier}: ${task.name}`;\n\n try {\n // Build bd create command with correct flags\n // bd create \"title\" --type task -l label1,label2 -d \"description\" --deps \"blocks:id\"\n const escapedName = fullName.replace(/\"/g, '\\\\\"');\n let cmd = `bd create \"${escapedName}\" --type task -l \"${issue.identifier},linear\"`;\n\n // Add dependency if specified (format: blocks:id)\n if (task.dependsOn) {\n const depName = `${issue.identifier}: ${task.dependsOn}`;\n const depId = taskIds.get(depName);\n if (depId) {\n cmd += ` --deps \"blocks:${depId}\"`;\n }\n }\n\n // Add description\n if (task.description) {\n const escapedDesc = task.description.replace(/\"/g, '\\\\\"');\n cmd += ` -d \"${escapedDesc}\"`;\n }\n\n const result = execSync(cmd, { encoding: 'utf-8', cwd: process.cwd() });\n\n // Extract ID from output - bd outputs \"Created: bd-XXXX\" or similar\n const idMatch = result.match(/bd-[a-f0-9]+/i) || result.match(/([a-f0-9-]{8,})/i);\n if (idMatch) {\n taskIds.set(fullName, idMatch[0]);\n }\n\n created.push(fullName);\n } catch (error: any) {\n // Extract meaningful error from stderr\n const errMsg = error.stderr?.toString() || error.message;\n errors.push(`Failed to create \"${task.name}\": ${errMsg.split('\\n')[0]}`);\n }\n }\n\n // Sync beads to git (bd uses 'bd flush' to export to JSONL)\n if (created.length > 0) {\n try {\n execSync('bd flush', { encoding: 'utf-8', cwd: process.cwd() });\n } catch {\n // Flush might fail if no changes, that's OK\n }\n }\n\n return { success: errors.length === 0, created, errors };\n}\n\n/**\n * Copy plan to PRD directory\n */\nfunction copyToPRDDirectory(issue: LinearIssue, stateContent: string): string | null {\n const cwd = process.cwd();\n const prdDir = join(cwd, 'docs', 'prds', 'active');\n\n try {\n mkdirSync(prdDir, { recursive: true });\n\n const filename = `${issue.identifier.toLowerCase()}-plan.md`;\n const prdPath = join(prdDir, filename);\n\n writeFileSync(prdPath, stateContent);\n\n return prdPath;\n } catch {\n return null;\n }\n}\n\nexport async function planCommand(id: string, options: PlanOptions = {}): Promise<void> {\n const spinner = ora(`Creating execution plan for ${id}...`).start();\n\n try {\n const apiKey = getLinearApiKey();\n if (!apiKey) {\n spinner.fail('LINEAR_API_KEY not found');\n console.log('');\n console.log(chalk.dim('Set it in ~/.panopticon.env:'));\n console.log(' LINEAR_API_KEY=lin_api_xxxxx');\n process.exit(1);\n }\n\n // Fetch issue from Linear\n spinner.text = 'Fetching issue from Linear...';\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey });\n\n const me = await client.viewer;\n const teams = await me.teams();\n const team = teams.nodes[0];\n\n if (!team) {\n spinner.fail('No Linear team found');\n process.exit(1);\n }\n\n const searchResult = await team.issues({ first: 100 });\n const issue = searchResult.nodes.find(\n (i) => i.identifier.toUpperCase() === id.toUpperCase()\n );\n\n if (!issue) {\n spinner.fail(`Issue not found: ${id}`);\n process.exit(1);\n }\n\n const state = await issue.state;\n const assignee = await issue.assignee;\n const project = await issue.project;\n const labels = await issue.labels();\n\n const issueData: LinearIssue = {\n id: issue.id,\n identifier: issue.identifier,\n title: issue.title,\n description: issue.description || undefined,\n state: { name: state?.name || 'Unknown' },\n priority: issue.priority,\n url: issue.url,\n labels: labels.nodes.map(l => ({ name: l.name })),\n assignee: assignee ? { name: assignee.name } : undefined,\n project: project ? { name: project.name } : undefined,\n };\n\n // Look for related PRD files\n spinner.text = 'Searching for related PRDs...';\n const prdFiles = findPRDFiles(id);\n\n // Analyze complexity\n spinner.text = 'Analyzing complexity...';\n const complexity = analyzeComplexity(issueData, prdFiles);\n\n spinner.stop();\n\n // Show complexity analysis\n console.log('');\n console.log(chalk.bold('═══════════════════════════════════════════════════════════'));\n console.log(chalk.bold(` ${issueData.identifier}: ${issueData.title}`));\n console.log(chalk.bold('═══════════════════════════════════════════════════════════'));\n console.log('');\n\n console.log(chalk.bold('Complexity Analysis:'));\n console.log(` Level: ${complexity.isComplex ? chalk.yellow('COMPLEX') : chalk.green('SIMPLE')}`);\n console.log(` Estimated tasks: ${complexity.estimatedTasks}`);\n if (complexity.subsystems.length > 0) {\n console.log(` Subsystems: ${complexity.subsystems.join(', ')}`);\n }\n if (complexity.reasons.length > 0) {\n console.log(` Reasons:`);\n for (const reason of complexity.reasons) {\n console.log(` - ${reason}`);\n }\n }\n console.log('');\n\n if (prdFiles.length > 0) {\n console.log(chalk.bold('Related PRDs found:'));\n for (const prd of prdFiles) {\n console.log(` - ${prd.replace(process.cwd() + '/', '')}`);\n }\n console.log('');\n }\n\n // For simple issues, offer to skip planning\n if (!complexity.isComplex && !options.force) {\n const skipAnswer = await inquirer.prompt([{\n type: 'confirm',\n name: 'skip',\n message: 'This looks simple. Skip planning and go straight to /work-issue?',\n default: true,\n }]);\n\n if (skipAnswer.skip) {\n console.log('');\n console.log(chalk.cyan(`Run: pan work issue ${id}`));\n console.log('');\n return;\n }\n }\n\n // Run discovery phase\n let tasks: PlanTask[];\n let decisions: DiscoveryDecision[];\n\n if (options.skipDiscovery) {\n // Use default tasks based on complexity\n tasks = [\n { name: 'Understand requirements', description: 'Review issue and existing code' },\n { name: 'Implement changes', description: 'Core implementation', dependsOn: 'Understand requirements' },\n { name: 'Add tests', description: 'Unit/integration tests', dependsOn: 'Implement changes' },\n { name: 'Verify and cleanup', description: 'Lint, type check, final review', dependsOn: 'Add tests' },\n ];\n decisions = [];\n } else {\n const discovery = await runDiscoveryPhase(issueData, complexity);\n tasks = discovery.tasks;\n decisions = discovery.decisions;\n }\n\n // Generate context files\n const spinnerCreate = ora('Creating context files...').start();\n\n const stateContent = generateStateFile(issueData, decisions, tasks);\n const workspaceContent = generateWorkspaceFile(issueData, prdFiles);\n\n // Determine output directory (workspace or current)\n const outputDir = options.output ? dirname(options.output) : process.cwd();\n const planningDir = join(outputDir, '.planning');\n mkdirSync(planningDir, { recursive: true });\n\n // Write STATE.md\n const statePath = join(planningDir, 'STATE.md');\n writeFileSync(statePath, stateContent);\n\n // Write WORKSPACE.md\n const workspacePath = join(planningDir, 'WORKSPACE.md');\n writeFileSync(workspacePath, workspaceContent);\n\n spinnerCreate.succeed('Context files created');\n\n // Create Beads tasks\n const spinnerBeads = ora('Creating Beads tasks...').start();\n const beadsResult = createBeadsTasks(issueData, tasks);\n\n if (beadsResult.success) {\n spinnerBeads.succeed(`Created ${beadsResult.created.length} Beads tasks`);\n } else {\n spinnerBeads.warn(`Created ${beadsResult.created.length} tasks with errors`);\n for (const error of beadsResult.errors) {\n console.log(chalk.red(` - ${error}`));\n }\n }\n\n // Copy to PRD directory\n const prdPath = copyToPRDDirectory(issueData, stateContent);\n if (prdPath) {\n console.log(chalk.dim(`Plan copied to: ${prdPath.replace(process.cwd() + '/', '')}`));\n }\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify({\n issue: issueData,\n complexity,\n tasks,\n decisions,\n files: {\n state: statePath,\n workspace: workspacePath,\n prd: prdPath,\n },\n beads: beadsResult,\n }, null, 2));\n return;\n }\n\n // Summary\n console.log('');\n console.log(chalk.bold.green('═══════════════════════════════════════════════════════════'));\n console.log(chalk.bold.green(' PLAN COMPLETE'));\n console.log(chalk.bold.green('═══════════════════════════════════════════════════════════'));\n console.log('');\n\n console.log(chalk.bold('Files created:'));\n console.log(` ${chalk.cyan(statePath.replace(process.cwd() + '/', ''))}`);\n console.log(` ${chalk.cyan(workspacePath.replace(process.cwd() + '/', ''))}`);\n console.log('');\n\n console.log(chalk.bold('Beads tasks:'));\n for (const task of tasks) {\n console.log(` ${chalk.dim('○')} ${issueData.identifier}: ${task.name}`);\n }\n console.log('');\n\n if (decisions.length > 0) {\n console.log(chalk.bold('Decisions recorded:'));\n for (const decision of decisions) {\n console.log(` - ${decision.question}: ${chalk.dim(decision.answer.slice(0, 50))}${decision.answer.length > 50 ? '...' : ''}`);\n }\n console.log('');\n }\n\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Review ${chalk.cyan('.planning/STATE.md')}`);\n console.log(` 2. Run ${chalk.cyan(`pan work issue ${id}`)} to spawn agent`);\n console.log(` 3. Agent will use ${chalk.cyan('bd ready')} to get tasks`);\n console.log('');\n\n } catch (error: any) {\n console.error(chalk.red(`Error: ${error.message}`));\n process.exit(1);\n }\n}\n","/**\n * work list - List issues from configured trackers\n *\n * Uses the tracker abstraction to support Linear, GitHub, and GitLab.\n */\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { loadConfig } from '../../../lib/config.js';\nimport type { Issue, IssueTracker, TrackerType } from '../../../lib/tracker/index.js';\nimport { createTracker, TrackerConfig } from '../../../lib/tracker/index.js';\n\ninterface ListOptions {\n all?: boolean;\n mine?: boolean;\n json?: boolean;\n tracker?: string;\n allTrackers?: boolean;\n}\n\nconst PRIORITY_LABELS: Record<number, string> = {\n 0: chalk.dim('None'),\n 1: chalk.red('Urgent'),\n 2: chalk.yellow('High'),\n 3: chalk.blue('Medium'),\n 4: chalk.dim('Low'),\n};\n\nconst STATE_COLORS: Record<string, (s: string) => string> = {\n 'open': chalk.white,\n 'in_progress': chalk.yellow,\n 'closed': chalk.green,\n};\n\n/**\n * Get tracker config by type from panopticon config\n */\nfunction getTrackerConfig(trackerType: TrackerType): TrackerConfig | null {\n const config = loadConfig();\n const trackerConfig = config.trackers[trackerType];\n\n if (!trackerConfig) {\n return null;\n }\n\n return {\n type: trackerType,\n apiKeyEnv: (trackerConfig as any).api_key_env,\n team: (trackerConfig as any).team,\n tokenEnv: (trackerConfig as any).token_env,\n owner: (trackerConfig as any).owner,\n repo: (trackerConfig as any).repo,\n projectId: (trackerConfig as any).project_id,\n server: (trackerConfig as any).server,\n workspace: (trackerConfig as any).workspace,\n project: (trackerConfig as any).project,\n };\n}\n\n/**\n * Get all configured trackers\n */\nfunction getConfiguredTrackers(): TrackerType[] {\n const config = loadConfig();\n const trackers: TrackerType[] = [];\n\n if (config.trackers.linear) trackers.push('linear');\n if (config.trackers.github) trackers.push('github');\n if (config.trackers.gitlab) trackers.push('gitlab');\n if (config.trackers.rally) trackers.push('rally');\n\n return trackers;\n}\n\n/**\n * Display issues in a formatted way\n */\nfunction displayIssues(issues: Issue[], trackerName: string): void {\n if (issues.length === 0) {\n console.log(chalk.dim(` No issues found in ${trackerName}`));\n return;\n }\n\n // Group by state\n const byState: Record<string, Issue[]> = {};\n for (const issue of issues) {\n if (!byState[issue.state]) byState[issue.state] = [];\n byState[issue.state].push(issue);\n }\n\n // Display order\n const stateOrder = ['in_progress', 'open', 'closed'];\n\n for (const state of stateOrder) {\n const stateIssues = byState[state];\n if (!stateIssues || stateIssues.length === 0) continue;\n\n const colorFn = STATE_COLORS[state] || chalk.white;\n const displayState = state.replace('_', ' ').replace(/\\b\\w/g, l => l.toUpperCase());\n console.log(colorFn(` ── ${displayState} (${stateIssues.length}) ──`));\n\n for (const issue of stateIssues) {\n const priorityLabel = issue.priority ? PRIORITY_LABELS[issue.priority] || '' : '';\n const assigneeStr = issue.assignee ? chalk.dim(` @${issue.assignee.split(' ')[0]}`) : '';\n const priorityStr = issue.priority && issue.priority < 3 ? ` ${priorityLabel}` : '';\n\n console.log(` ${chalk.cyan(issue.ref)} ${issue.title}${assigneeStr}${priorityStr}`);\n }\n console.log('');\n }\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n const spinner = ora('Fetching issues...').start();\n\n try {\n const config = loadConfig();\n const trackersToQuery: TrackerType[] = [];\n\n // Determine which trackers to query\n if (options.tracker) {\n // Specific tracker requested\n const trackerType = options.tracker as TrackerType;\n if (!['linear', 'github', 'gitlab', 'rally'].includes(trackerType)) {\n spinner.fail(`Unknown tracker: ${options.tracker}`);\n console.log(chalk.dim('Valid trackers: linear, github, gitlab, rally'));\n process.exit(1);\n }\n trackersToQuery.push(trackerType);\n } else if (options.allTrackers) {\n // All configured trackers\n trackersToQuery.push(...getConfiguredTrackers());\n } else {\n // Primary tracker only (default)\n trackersToQuery.push(config.trackers.primary);\n }\n\n if (trackersToQuery.length === 0) {\n spinner.fail('No trackers configured');\n console.log(chalk.dim('Configure trackers in ~/.panopticon/config.toml'));\n process.exit(1);\n }\n\n // Fetch issues from all requested trackers\n const allIssues: { tracker: TrackerType; issues: Issue[] }[] = [];\n\n for (const trackerType of trackersToQuery) {\n spinner.text = `Fetching from ${trackerType}...`;\n\n const trackerConfig = getTrackerConfig(trackerType);\n if (!trackerConfig) {\n console.log(chalk.yellow(`\\nWarning: ${trackerType} not configured, skipping`));\n continue;\n }\n\n try {\n const tracker = createTracker(trackerConfig);\n const issues = await tracker.listIssues({\n includeClosed: options.all,\n assignee: options.mine ? 'me' : undefined,\n });\n allIssues.push({ tracker: trackerType, issues });\n } catch (error: any) {\n console.log(chalk.yellow(`\\nWarning: Failed to fetch from ${trackerType}: ${error.message}`));\n }\n }\n\n spinner.stop();\n\n // JSON output\n if (options.json) {\n const output = allIssues.flatMap(({ tracker, issues }) =>\n issues.map(issue => ({ ...issue, source: tracker }))\n );\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Display results\n const totalIssues = allIssues.reduce((sum, { issues }) => sum + issues.length, 0);\n\n if (totalIssues === 0) {\n console.log(chalk.dim('\\nNo issues found.'));\n return;\n }\n\n for (const { tracker, issues } of allIssues) {\n console.log(chalk.bold(`\\n${tracker.toUpperCase()} (${issues.length} issues)\\n`));\n displayIssues(issues, tracker);\n }\n\n // Footer\n const trackerNames = trackersToQuery.join(', ');\n console.log(chalk.dim(`Showing ${totalIssues} issues from ${trackerNames}.`));\n if (!options.all) {\n console.log(chalk.dim('Use --all to include closed issues.'));\n }\n if (!options.allTrackers && trackersToQuery.length === 1) {\n console.log(chalk.dim('Use --all-trackers to query all configured trackers.'));\n }\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","/**\n * work triage - Triage issues from secondary tracker to primary tracker\n *\n * Uses the tracker abstraction to move issues between trackers.\n */\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { loadConfig } from '../../../lib/config.js';\nimport type { Issue, TrackerType } from '../../../lib/tracker/index.js';\nimport { createTracker, TrackerConfig } from '../../../lib/tracker/index.js';\n\ninterface TriageOptions {\n create?: boolean;\n dismiss?: string;\n}\n\ninterface TriageState {\n dismissed: string[]; // Issue refs that were dismissed\n created: { [sourceRef: string]: string }; // Source ref -> Primary ref\n}\n\n/**\n * Get tracker config by type from panopticon config\n */\nfunction getTrackerConfig(trackerType: TrackerType): TrackerConfig | null {\n const config = loadConfig();\n const trackerConfig = config.trackers[trackerType];\n\n if (!trackerConfig) {\n return null;\n }\n\n return {\n type: trackerType,\n apiKeyEnv: (trackerConfig as any).api_key_env,\n team: (trackerConfig as any).team,\n tokenEnv: (trackerConfig as any).token_env,\n owner: (trackerConfig as any).owner,\n repo: (trackerConfig as any).repo,\n projectId: (trackerConfig as any).project_id,\n };\n}\n\nfunction getTriageStatePath(): string {\n return join(homedir(), '.panopticon', 'triage-state.json');\n}\n\nfunction loadTriageState(): TriageState {\n const path = getTriageStatePath();\n if (existsSync(path)) {\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return { dismissed: [], created: {} };\n }\n }\n return { dismissed: [], created: {} };\n}\n\nfunction saveTriageState(state: TriageState): void {\n const dir = join(homedir(), '.panopticon');\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n const path = getTriageStatePath();\n writeFileSync(path, JSON.stringify(state, null, 2));\n}\n\nexport async function triageCommand(id?: string, options: TriageOptions = {}): Promise<void> {\n const spinner = ora('Loading triage queue...').start();\n\n try {\n const config = loadConfig();\n const primaryType = config.trackers.primary;\n const secondaryType = config.trackers.secondary;\n\n // Check for secondary tracker configuration\n if (!secondaryType) {\n spinner.info('No secondary tracker configured');\n console.log('');\n console.log(chalk.bold('Setup Instructions:'));\n console.log('');\n console.log('Add secondary tracker to ~/.panopticon/config.toml:');\n console.log(chalk.dim(`\n[trackers]\nprimary = \"linear\"\nsecondary = \"github\"\n\n[trackers.github]\ntype = \"github\"\ntoken_env = \"GITHUB_TOKEN\"\nowner = \"your-org\"\nrepo = \"your-repo\"\n`));\n return;\n }\n\n const primaryConfig = getTrackerConfig(primaryType);\n const secondaryConfig = getTrackerConfig(secondaryType);\n\n if (!primaryConfig) {\n spinner.fail(`Primary tracker (${primaryType}) not configured`);\n return;\n }\n\n if (!secondaryConfig) {\n spinner.fail(`Secondary tracker (${secondaryType}) not configured`);\n return;\n }\n\n const triageState = loadTriageState();\n\n // If specific ID provided, handle create/dismiss\n if (id) {\n // Normalize the ID (remove # prefix if present for GitHub)\n const issueRef = id.startsWith('#') ? id : `#${id}`;\n\n if (options.dismiss) {\n if (!triageState.dismissed.includes(issueRef)) {\n triageState.dismissed.push(issueRef);\n saveTriageState(triageState);\n }\n spinner.succeed(`Dismissed ${issueRef}: ${options.dismiss}`);\n return;\n }\n\n if (options.create) {\n spinner.text = `Fetching ${secondaryType} issue ${issueRef}...`;\n\n let secondaryTracker;\n try {\n secondaryTracker = createTracker(secondaryConfig);\n } catch (error: any) {\n spinner.fail(`Failed to connect to ${secondaryType}: ${error.message}`);\n return;\n }\n\n let sourceIssue: Issue;\n try {\n sourceIssue = await secondaryTracker.getIssue(id);\n } catch (error: any) {\n spinner.fail(`Issue ${issueRef} not found in ${secondaryType}`);\n return;\n }\n\n spinner.text = `Creating ${primaryType} issue...`;\n\n let primaryTracker;\n try {\n primaryTracker = createTracker(primaryConfig);\n } catch (error: any) {\n spinner.fail(`Failed to connect to ${primaryType}: ${error.message}`);\n return;\n }\n\n // Create issue in primary tracker with link to secondary\n const newIssue = await primaryTracker.createIssue({\n title: sourceIssue.title,\n description: `${sourceIssue.description}\\n\\n---\\n\\n**From ${secondaryType}:** ${sourceIssue.url}`,\n team: primaryConfig.team,\n });\n\n // Add comment to secondary issue linking to primary\n try {\n await secondaryTracker.addComment(\n id,\n `Internal tracking: ${newIssue.ref} (${primaryType})`\n );\n } catch {\n // Non-fatal - just log warning\n console.log(chalk.yellow('\\nNote: Could not add link comment to source issue'));\n }\n\n triageState.created[sourceIssue.ref] = newIssue.ref;\n saveTriageState(triageState);\n\n spinner.succeed(`Created ${newIssue.ref} from ${sourceIssue.ref}`);\n console.log('');\n console.log(` ${secondaryType}: ${chalk.dim(sourceIssue.url)}`);\n console.log(` ${primaryType}: ${chalk.cyan(newIssue.ref)}`);\n return;\n }\n }\n\n // List all secondary tracker issues needing triage\n spinner.text = `Fetching ${secondaryType} issues...`;\n\n let secondaryTracker;\n try {\n secondaryTracker = createTracker(secondaryConfig);\n } catch (error: any) {\n spinner.fail(`Failed to connect to ${secondaryType}: ${error.message}`);\n return;\n }\n\n const issues = await secondaryTracker.listIssues({ includeClosed: false });\n\n // Filter out dismissed and already created\n const pending = issues.filter(\n (i) => !triageState.dismissed.includes(i.ref) && !triageState.created[i.ref]\n );\n\n spinner.stop();\n\n if (pending.length === 0) {\n console.log(chalk.green('No issues pending triage.'));\n console.log(chalk.dim(`${issues.length} total open, ${triageState.dismissed.length} dismissed, ${Object.keys(triageState.created).length} created`));\n return;\n }\n\n console.log(chalk.bold(`\\n${secondaryType.toUpperCase()} Issues Pending Triage (${pending.length})\\n`));\n\n for (const issue of pending) {\n const labels = issue.labels.map((l) => chalk.dim(`[${l}]`)).join(' ');\n console.log(` ${chalk.cyan(issue.ref)} ${issue.title} ${labels}`);\n console.log(` ${chalk.dim(issue.url)}`);\n }\n\n console.log('');\n console.log(chalk.bold('Commands:'));\n console.log(` ${chalk.dim(`Create ${primaryType} issue:`)} pan work triage <id> --create`);\n console.log(` ${chalk.dim('Dismiss from queue:')} pan work triage <id> --dismiss \"reason\"`);\n console.log('');\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport {\n checkHook,\n pushToHook,\n popFromHook,\n clearHook,\n sendMail,\n generateGUPPPrompt,\n HookItem,\n} from '../../../lib/hooks.js';\n\ninterface HookOptions {\n json?: boolean;\n}\n\nexport async function hookCommand(\n action: string,\n idOrMessage?: string,\n options: HookOptions = {}\n): Promise<void> {\n // Normalize agent ID\n const agentId = process.env.PANOPTICON_AGENT_ID || 'default';\n\n switch (action) {\n case 'check': {\n const result = checkHook(idOrMessage || agentId);\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (!result.hasWork) {\n console.log(chalk.green('✓ No pending work on hook'));\n return;\n }\n\n console.log(chalk.yellow(`⚠ ${result.items.length} item(s) on hook`));\n if (result.urgentCount > 0) {\n console.log(chalk.red(` ${result.urgentCount} URGENT`));\n }\n console.log('');\n\n for (const item of result.items) {\n const priorityColor = {\n urgent: chalk.red,\n high: chalk.yellow,\n normal: chalk.white,\n low: chalk.dim,\n }[item.priority];\n\n console.log(`${priorityColor(`[${item.priority.toUpperCase()}]`)} ${item.id}`);\n console.log(` Type: ${item.type}`);\n console.log(` From: ${item.source}`);\n if (item.payload.message) {\n console.log(` Message: ${item.payload.message}`);\n }\n console.log('');\n }\n break;\n }\n\n case 'push': {\n if (!idOrMessage) {\n console.log(chalk.red('Usage: pan work hook push <agent-id> <message>'));\n process.exit(1);\n }\n\n const [targetAgent, ...messageParts] = idOrMessage.split(' ');\n const message = messageParts.join(' ');\n\n if (!message) {\n console.log(chalk.red('Message required'));\n process.exit(1);\n }\n\n const item = pushToHook(targetAgent.startsWith('agent-') ? targetAgent : `agent-${targetAgent}`, {\n type: 'task',\n priority: 'normal',\n source: 'cli',\n payload: { message },\n });\n\n console.log(chalk.green(`✓ Pushed to hook: ${item.id}`));\n break;\n }\n\n case 'pop': {\n if (!idOrMessage) {\n console.log(chalk.red('Usage: pan work hook pop <item-id>'));\n process.exit(1);\n }\n\n const success = popFromHook(agentId, idOrMessage);\n if (success) {\n console.log(chalk.green(`✓ Popped: ${idOrMessage}`));\n } else {\n console.log(chalk.yellow(`Item not found: ${idOrMessage}`));\n }\n break;\n }\n\n case 'clear': {\n clearHook(idOrMessage || agentId);\n console.log(chalk.green('✓ Hook cleared'));\n break;\n }\n\n case 'mail': {\n if (!idOrMessage) {\n console.log(chalk.red('Usage: pan work hook mail <agent-id> <message>'));\n process.exit(1);\n }\n\n const [targetAgent, ...messageParts] = idOrMessage.split(' ');\n const message = messageParts.join(' ');\n\n if (!message) {\n console.log(chalk.red('Message required'));\n process.exit(1);\n }\n\n sendMail(\n targetAgent.startsWith('agent-') ? targetAgent : `agent-${targetAgent}`,\n 'cli',\n message\n );\n\n console.log(chalk.green(`✓ Mail sent to ${targetAgent}`));\n break;\n }\n\n case 'gupp': {\n const prompt = generateGUPPPrompt(idOrMessage || agentId);\n\n if (!prompt) {\n console.log(chalk.green('No GUPP work found'));\n return;\n }\n\n console.log(prompt);\n break;\n }\n\n default:\n console.log(chalk.bold('Hook Commands:'));\n console.log('');\n console.log(` ${chalk.cyan('pan work hook check [agent-id]')} - Check for pending work`);\n console.log(` ${chalk.cyan('pan work hook push <agent-id> <msg>')} - Push task to hook`);\n console.log(` ${chalk.cyan('pan work hook pop <item-id>')} - Remove completed item`);\n console.log(` ${chalk.cyan('pan work hook clear [agent-id]')} - Clear all hook items`);\n console.log(` ${chalk.cyan('pan work hook mail <agent-id> <msg>')} - Send mail to agent`);\n console.log(` ${chalk.cyan('pan work hook gupp [agent-id]')} - Generate GUPP prompt`);\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport {\n detectCrashedAgents,\n recoverAgent,\n autoRecoverAgents,\n} from '../../../lib/agents.js';\n\ninterface RecoverOptions {\n all?: boolean;\n json?: boolean;\n}\n\nexport async function recoverCommand(id?: string, options: RecoverOptions = {}): Promise<void> {\n const spinner = ora('Checking for crashed agents...').start();\n\n try {\n // Auto-recover all crashed agents\n if (options.all || !id) {\n const crashed = detectCrashedAgents();\n\n if (crashed.length === 0) {\n spinner.succeed('No crashed agents found');\n return;\n }\n\n if (options.json) {\n spinner.stop();\n console.log(JSON.stringify({ crashed: crashed.map((a) => a.id) }, null, 2));\n\n if (!options.all) {\n console.log(chalk.dim('\\nUse --all to auto-recover all crashed agents'));\n return;\n }\n }\n\n if (!options.all) {\n spinner.info(`Found ${crashed.length} crashed agent(s)`);\n console.log('');\n\n for (const agent of crashed) {\n console.log(` ${chalk.red('●')} ${chalk.cyan(agent.id)}`);\n console.log(` Issue: ${agent.issueId}`);\n console.log(` Started: ${agent.startedAt}`);\n console.log('');\n }\n\n console.log(chalk.dim('Use --all to auto-recover, or specify an agent ID'));\n return;\n }\n\n spinner.text = 'Auto-recovering agents...';\n const result = autoRecoverAgents();\n\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (result.recovered.length > 0) {\n console.log(chalk.green(`✓ Recovered ${result.recovered.length} agent(s):`));\n for (const agentId of result.recovered) {\n console.log(` ${chalk.cyan(agentId)}`);\n }\n }\n\n if (result.failed.length > 0) {\n console.log(chalk.red(`✗ Failed to recover ${result.failed.length} agent(s):`));\n for (const agentId of result.failed) {\n console.log(` ${chalk.dim(agentId)}`);\n }\n }\n\n return;\n }\n\n // Recover specific agent\n const agentId = id.startsWith('agent-') ? id : `agent-${id.toLowerCase()}`;\n spinner.text = `Recovering ${agentId}...`;\n\n const state = recoverAgent(agentId);\n\n if (!state) {\n spinner.fail(`Agent not found: ${agentId}`);\n process.exit(1);\n }\n\n spinner.succeed(`Recovered: ${agentId}`);\n console.log('');\n console.log(chalk.bold('Agent Details:'));\n console.log(` Issue: ${chalk.cyan(state.issueId)}`);\n console.log(` Workspace: ${chalk.dim(state.workspace)}`);\n console.log(` Model: ${state.model}`);\n console.log('');\n console.log(chalk.dim('Commands:'));\n console.log(` Attach: tmux attach -t ${state.id}`);\n console.log(` Message: pan work tell ${state.issueId} \"your message\"`);\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport {\n getAgentCV,\n getAgentRankings,\n formatCV,\n startWork,\n completeWork,\n} from '../../../lib/cv.js';\n\ninterface CVOptions {\n json?: boolean;\n rankings?: boolean;\n}\n\nexport async function cvCommand(agentId?: string, options: CVOptions = {}): Promise<void> {\n // Show rankings\n if (options.rankings || !agentId) {\n const rankings = getAgentRankings();\n\n if (options.json) {\n console.log(JSON.stringify(rankings, null, 2));\n return;\n }\n\n if (rankings.length === 0) {\n console.log(chalk.dim('No agent work history yet.'));\n console.log(chalk.dim('CVs are created as agents complete work.'));\n return;\n }\n\n console.log(chalk.bold('\\nAgent Rankings\\n'));\n\n // Header\n console.log(\n `${'Agent'.padEnd(25)} ${'Success'.padStart(8)} ${'Total'.padStart(6)} ${'Avg Time'.padStart(10)}`\n );\n console.log(chalk.dim('─'.repeat(52)));\n\n for (let i = 0; i < rankings.length; i++) {\n const r = rankings[i];\n const medal = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : ' ';\n const successPct = `${(r.successRate * 100).toFixed(0)}%`;\n const avgTime = r.avgDuration > 0 ? `${r.avgDuration}m` : '-';\n\n console.log(\n `${medal} ${r.agentId.padEnd(22)} ${successPct.padStart(8)} ${r.totalIssues\n .toString()\n .padStart(6)} ${avgTime.padStart(10)}`\n );\n }\n\n console.log('');\n console.log(chalk.dim(`Use: pan work cv <agent-id> for details`));\n return;\n }\n\n // Show specific agent CV\n const normalizedId = agentId.startsWith('agent-') ? agentId : `agent-${agentId.toLowerCase()}`;\n const cv = getAgentCV(normalizedId);\n\n if (options.json) {\n console.log(JSON.stringify(cv, null, 2));\n return;\n }\n\n console.log('');\n console.log(formatCV(cv));\n}\n\n// Export helper functions for integration\nexport { startWork, completeWork };\n","import chalk from 'chalk';\nimport {\n readAgentState,\n writeAgentState,\n updateCheckpoint,\n appendSummary,\n logHistory,\n searchHistory,\n getRecentHistory,\n materializeOutput,\n listMaterialized,\n readMaterialized,\n estimateTokens,\n AgentStateContext,\n} from '../../../lib/context.js';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { AGENTS_DIR } from '../../../lib/paths.js';\n\ninterface ContextOptions {\n json?: boolean;\n}\n\nexport async function contextCommand(\n action: string,\n arg1?: string,\n arg2?: string,\n options: ContextOptions = {}\n): Promise<void> {\n // Get agent ID from environment or argument\n const agentId = process.env.PANOPTICON_AGENT_ID || arg1 || 'default';\n\n switch (action) {\n case 'state': {\n // Show or update STATE.md\n const state = readAgentState(agentId);\n\n if (options.json) {\n console.log(JSON.stringify(state, null, 2));\n return;\n }\n\n if (!state) {\n console.log(chalk.dim('No state found for agent.'));\n console.log(chalk.dim('Initialize with: pan work context init <agent-id> <issue-id>'));\n return;\n }\n\n console.log(chalk.bold(`\\nAgent State: ${state.issueId}\\n`));\n console.log(`Status: ${chalk.cyan(state.status)}`);\n console.log(`Last Activity: ${chalk.dim(state.lastActivity)}`);\n\n if (state.lastCheckpoint) {\n console.log('');\n console.log(chalk.bold('Session Continuity:'));\n console.log(` Checkpoint: ${chalk.yellow(state.lastCheckpoint)}`);\n if (state.resumePoint) {\n console.log(` Resume: ${chalk.green(state.resumePoint)}`);\n }\n }\n\n if (state.contextRefs.workspace || state.contextRefs.prd) {\n console.log('');\n console.log(chalk.bold('Context References:'));\n if (state.contextRefs.workspace) {\n console.log(` Workspace: ${chalk.dim(state.contextRefs.workspace)}`);\n }\n if (state.contextRefs.prd) {\n console.log(` PRD: ${chalk.dim(state.contextRefs.prd)}`);\n }\n if (state.contextRefs.beads) {\n console.log(` Beads: ${chalk.dim(state.contextRefs.beads)}`);\n }\n }\n console.log('');\n break;\n }\n\n case 'init': {\n // Initialize STATE.md for an agent\n const issueId = arg2 || arg1 || 'UNKNOWN';\n const targetAgent = arg2 ? arg1 : agentId;\n\n const state: AgentStateContext = {\n issueId: issueId.toUpperCase(),\n status: 'In Progress',\n lastActivity: new Date().toISOString(),\n contextRefs: {},\n };\n\n writeAgentState(targetAgent!, state);\n logHistory(targetAgent!, 'context:init', { issueId });\n\n console.log(chalk.green(`✓ Initialized state for ${targetAgent}`));\n break;\n }\n\n case 'checkpoint': {\n // Update checkpoint\n const checkpoint = arg1;\n const resume = arg2;\n\n if (!checkpoint) {\n console.log(chalk.red('Checkpoint message required'));\n console.log(chalk.dim('Usage: pan work context checkpoint \"message\" [\"resume point\"]'));\n return;\n }\n\n updateCheckpoint(agentId, checkpoint, resume);\n logHistory(agentId, 'context:checkpoint', { checkpoint, resume });\n\n console.log(chalk.green(`✓ Checkpoint saved: \"${checkpoint}\"`));\n if (resume) {\n console.log(chalk.dim(` Resume point: \"${resume}\"`));\n }\n break;\n }\n\n case 'summary': {\n // Add a work summary\n const title = arg1 || 'Work Session';\n\n // Read summary from stdin or prompt\n const summary = {\n title,\n completedAt: new Date().toISOString(),\n whatWasDone: ['Completed assigned work'],\n };\n\n appendSummary(agentId, summary);\n logHistory(agentId, 'context:summary', { title });\n\n console.log(chalk.green(`✓ Summary added: \"${title}\"`));\n break;\n }\n\n case 'history': {\n // Search or show history\n const pattern = arg1;\n\n if (pattern) {\n const results = searchHistory(agentId, pattern);\n if (results.length === 0) {\n console.log(chalk.dim('No matches found.'));\n return;\n }\n\n console.log(chalk.bold(`\\nHistory matches for \"${pattern}\":\\n`));\n for (const line of results.slice(0, 50)) {\n console.log(line);\n }\n } else {\n const recent = getRecentHistory(agentId, 20);\n if (recent.length === 0) {\n console.log(chalk.dim('No history yet.'));\n return;\n }\n\n console.log(chalk.bold('\\nRecent History:\\n'));\n for (const line of recent) {\n console.log(line);\n }\n }\n console.log('');\n break;\n }\n\n case 'materialize': {\n // List or read materialized outputs\n const filepath = arg1;\n\n if (filepath && existsSync(filepath)) {\n const content = readMaterialized(filepath);\n if (content) {\n console.log(content);\n }\n return;\n }\n\n const outputs = listMaterialized(agentId);\n if (outputs.length === 0) {\n console.log(chalk.dim('No materialized outputs.'));\n return;\n }\n\n console.log(chalk.bold('\\nMaterialized Outputs:\\n'));\n for (const out of outputs) {\n const date = new Date(out.timestamp).toLocaleString();\n console.log(` ${chalk.cyan(out.tool)} ${chalk.dim(date)}`);\n console.log(` ${chalk.dim(out.file)}`);\n }\n console.log('');\n break;\n }\n\n case 'tokens': {\n // Estimate tokens for a file or text\n const target = arg1;\n\n if (!target) {\n console.log(chalk.dim('Usage: pan work context tokens <file-or-text>'));\n return;\n }\n\n let text = target;\n if (existsSync(target)) {\n text = readFileSync(target, 'utf-8');\n }\n\n const tokens = estimateTokens(text);\n console.log(`Estimated tokens: ${chalk.cyan(tokens.toLocaleString())}`);\n break;\n }\n\n default:\n console.log(chalk.bold('Context Commands:'));\n console.log('');\n console.log(` ${chalk.cyan('pan work context state [agent-id]')} - Show current state`);\n console.log(` ${chalk.cyan('pan work context init <agent> <issue>')} - Initialize state`);\n console.log(` ${chalk.cyan('pan work context checkpoint \"msg\"')} - Save checkpoint`);\n console.log(` ${chalk.cyan('pan work context summary [title]')} - Add work summary`);\n console.log(` ${chalk.cyan('pan work context history [pattern]')} - Search history`);\n console.log(` ${chalk.cyan('pan work context materialize [file]')} - List/read outputs`);\n console.log(` ${chalk.cyan('pan work context tokens <file>')} - Estimate token count`);\n console.log('');\n }\n}\n","/**\n * Context Engineering System\n *\n * Implements GSD-Plus patterns for structured context management:\n * - STATE.md: Agent state that survives compaction\n * - WORKSPACE.md: Project context\n * - SUMMARY.md: Work artifacts\n * - Queryable history files\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from 'fs';\nimport { join, basename } from 'path';\nimport { AGENTS_DIR } from './paths.js';\n\nexport interface AgentStateContext {\n issueId: string;\n status: string;\n lastActivity: string;\n lastCheckpoint?: string;\n resumePoint?: string;\n contextRefs: {\n workspace?: string;\n prd?: string;\n beads?: string;\n };\n}\n\nexport interface WorkspaceMdContext {\n projectName: string;\n branch: string;\n issueId: string;\n description: string;\n constraints: string[];\n activeWork: string[];\n}\n\nexport interface SummaryEntry {\n title: string;\n completedAt: string;\n duration?: number;\n whatWasDone: string[];\n keyInsights?: string[];\n filesModified?: string[];\n}\n\n// ============== STATE.md ==============\n\nfunction getStateFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'STATE.md');\n}\n\n/**\n * Read current STATE.md for an agent\n */\nexport function readAgentState(agentId: string): AgentStateContext | null {\n const stateFile = getStateFile(agentId);\n if (!existsSync(stateFile)) return null;\n\n try {\n const content = readFileSync(stateFile, 'utf-8');\n return parseStateMd(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Write STATE.md for an agent\n */\nexport function writeAgentState(agentId: string, state: AgentStateContext): void {\n const dir = join(AGENTS_DIR, agentId);\n mkdirSync(dir, { recursive: true });\n\n const content = generateStateMd(state);\n writeFileSync(getStateFile(agentId), content);\n}\n\n/**\n * Update checkpoint in STATE.md\n */\nexport function updateCheckpoint(agentId: string, checkpoint: string, resumePoint?: string): void {\n const state = readAgentState(agentId);\n if (!state) return;\n\n state.lastActivity = new Date().toISOString();\n state.lastCheckpoint = checkpoint;\n if (resumePoint) {\n state.resumePoint = resumePoint;\n }\n\n writeAgentState(agentId, state);\n}\n\nfunction generateStateMd(state: AgentStateContext): string {\n const lines: string[] = [\n `# Agent State: ${state.issueId}`,\n '',\n '## Current Position',\n '',\n `Issue: ${state.issueId}`,\n `Status: ${state.status}`,\n `Last activity: ${state.lastActivity}`,\n '',\n ];\n\n if (state.lastCheckpoint) {\n lines.push('## Session Continuity');\n lines.push('');\n lines.push(`Last checkpoint: \"${state.lastCheckpoint}\"`);\n if (state.resumePoint) {\n lines.push(`Resume point: \"${state.resumePoint}\"`);\n }\n lines.push('');\n }\n\n if (state.contextRefs.workspace || state.contextRefs.prd || state.contextRefs.beads) {\n lines.push('## Context References');\n lines.push('');\n if (state.contextRefs.workspace) {\n lines.push(`- Workspace: ${state.contextRefs.workspace}`);\n }\n if (state.contextRefs.prd) {\n lines.push(`- PRD: ${state.contextRefs.prd}`);\n }\n if (state.contextRefs.beads) {\n lines.push(`- Beads: ${state.contextRefs.beads}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction parseStateMd(content: string): AgentStateContext {\n const state: AgentStateContext = {\n issueId: '',\n status: '',\n lastActivity: '',\n contextRefs: {},\n };\n\n // Parse issue ID from title\n const titleMatch = content.match(/# Agent State: (.+)/);\n if (titleMatch) state.issueId = titleMatch[1].trim();\n\n // Parse status\n const statusMatch = content.match(/Status: (.+)/);\n if (statusMatch) state.status = statusMatch[1].trim();\n\n // Parse last activity\n const activityMatch = content.match(/Last activity: (.+)/);\n if (activityMatch) state.lastActivity = activityMatch[1].trim();\n\n // Parse checkpoint\n const checkpointMatch = content.match(/Last checkpoint: \"(.+)\"/);\n if (checkpointMatch) state.lastCheckpoint = checkpointMatch[1];\n\n // Parse resume point\n const resumeMatch = content.match(/Resume point: \"(.+)\"/);\n if (resumeMatch) state.resumePoint = resumeMatch[1];\n\n // Parse context refs\n const workspaceMatch = content.match(/- Workspace: (.+)/);\n if (workspaceMatch) state.contextRefs.workspace = workspaceMatch[1].trim();\n\n const prdMatch = content.match(/- PRD: (.+)/);\n if (prdMatch) state.contextRefs.prd = prdMatch[1].trim();\n\n const beadsMatch = content.match(/- Beads: (.+)/);\n if (beadsMatch) state.contextRefs.beads = beadsMatch[1].trim();\n\n return state;\n}\n\n// ============== WORKSPACE.md ==============\n\n/**\n * Generate WORKSPACE.md for a workspace\n */\nexport function generateWorkspaceMd(ctx: WorkspaceMdContext): string {\n const lines: string[] = [\n `# ${ctx.projectName}`,\n '',\n ctx.description,\n '',\n '## Core Value',\n '',\n `Working on ${ctx.issueId} to deliver requested functionality.`,\n '',\n '## Active Work',\n '',\n ];\n\n for (const work of ctx.activeWork) {\n lines.push(`- [ ] ${work}`);\n }\n\n lines.push('');\n lines.push('## Constraints');\n lines.push('');\n\n for (const constraint of ctx.constraints) {\n lines.push(`- ${constraint}`);\n }\n\n lines.push('');\n lines.push('## Context');\n lines.push('');\n lines.push(`- Branch: \\`${ctx.branch}\\``);\n lines.push(`- Issue: ${ctx.issueId}`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n// ============== SUMMARY.md ==============\n\nfunction getSummaryFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'SUMMARY.md');\n}\n\n/**\n * Append a work summary to SUMMARY.md\n */\nexport function appendSummary(agentId: string, summary: SummaryEntry): void {\n const dir = join(AGENTS_DIR, agentId);\n mkdirSync(dir, { recursive: true });\n\n const summaryFile = getSummaryFile(agentId);\n const content = generateSummaryEntry(summary);\n\n if (existsSync(summaryFile)) {\n appendFileSync(summaryFile, '\\n---\\n\\n' + content);\n } else {\n writeFileSync(summaryFile, '# Work Summaries\\n\\n' + content);\n }\n}\n\nfunction generateSummaryEntry(summary: SummaryEntry): string {\n const lines: string[] = [\n `## ${summary.title}`,\n '',\n `**Completed:** ${summary.completedAt}`,\n ];\n\n if (summary.duration) {\n lines.push(`**Duration:** ${summary.duration} minutes`);\n }\n\n lines.push('');\n lines.push('### What Was Done');\n lines.push('');\n\n for (let i = 0; i < summary.whatWasDone.length; i++) {\n lines.push(`${i + 1}. ${summary.whatWasDone[i]}`);\n }\n\n if (summary.keyInsights && summary.keyInsights.length > 0) {\n lines.push('');\n lines.push('### Key Insights');\n lines.push('');\n for (let i = 0; i < summary.keyInsights.length; i++) {\n lines.push(`${i + 1}. ${summary.keyInsights[i]}`);\n }\n }\n\n if (summary.filesModified && summary.filesModified.length > 0) {\n lines.push('');\n lines.push('### Files Modified');\n lines.push('');\n for (const file of summary.filesModified) {\n lines.push(`- ${file}`);\n }\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\n// ============== History Files ==============\n\nfunction getHistoryDir(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'history');\n}\n\n/**\n * Log an action to queryable history\n */\nexport function logHistory(\n agentId: string,\n action: string,\n details?: Record<string, any>\n): void {\n const historyDir = getHistoryDir(agentId);\n mkdirSync(historyDir, { recursive: true });\n\n const date = new Date();\n const dateStr = date.toISOString().split('T')[0];\n const historyFile = join(historyDir, `${dateStr}.log`);\n\n const timestamp = date.toISOString();\n const detailsStr = details ? ` ${JSON.stringify(details)}` : '';\n const logLine = `[${timestamp}] ${action}${detailsStr}\\n`;\n\n appendFileSync(historyFile, logLine);\n}\n\n/**\n * Search history files for a pattern\n */\nexport function searchHistory(agentId: string, pattern: string): string[] {\n const historyDir = getHistoryDir(agentId);\n if (!existsSync(historyDir)) return [];\n\n const results: string[] = [];\n const regex = new RegExp(pattern, 'i');\n\n const files = readdirSync(historyDir).filter((f) => f.endsWith('.log'));\n files.sort().reverse(); // Most recent first\n\n for (const file of files) {\n const content = readFileSync(join(historyDir, file), 'utf-8');\n const lines = content.split('\\n');\n\n for (const line of lines) {\n if (regex.test(line)) {\n results.push(line);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get recent history entries\n */\nexport function getRecentHistory(agentId: string, limit: number = 20): string[] {\n const historyDir = getHistoryDir(agentId);\n if (!existsSync(historyDir)) return [];\n\n const results: string[] = [];\n\n const files = readdirSync(historyDir).filter((f) => f.endsWith('.log'));\n files.sort().reverse(); // Most recent first\n\n for (const file of files) {\n if (results.length >= limit) break;\n\n const content = readFileSync(join(historyDir, file), 'utf-8');\n const lines = content.split('\\n').filter((l) => l.trim());\n\n for (const line of lines.reverse()) {\n if (results.length >= limit) break;\n results.push(line);\n }\n }\n\n return results;\n}\n\n// ============== Context Budget ==============\n\nexport interface ContextBudget {\n maxTokens: number;\n usedTokens: number;\n warningThreshold: number; // e.g., 0.8 = warn at 80%\n}\n\n/**\n * Estimate token count (rough approximation: ~4 chars per token)\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Check if context budget allows adding more content\n */\nexport function checkContextBudget(\n budget: ContextBudget,\n newContent: string\n): { allowed: boolean; warning: boolean; remaining: number } {\n const newTokens = estimateTokens(newContent);\n const totalUsed = budget.usedTokens + newTokens;\n const remaining = budget.maxTokens - totalUsed;\n const usageRatio = totalUsed / budget.maxTokens;\n\n return {\n allowed: totalUsed <= budget.maxTokens,\n warning: usageRatio >= budget.warningThreshold,\n remaining,\n };\n}\n\n/**\n * Create a context budget for a session\n */\nexport function createContextBudget(maxTokens: number = 100000): ContextBudget {\n return {\n maxTokens,\n usedTokens: 0,\n warningThreshold: 0.8,\n };\n}\n\n// ============== Context Materialization ==============\n\nfunction getMaterializedDir(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'materialized');\n}\n\n/**\n * Materialize tool output for later retrieval\n */\nexport function materializeOutput(\n agentId: string,\n toolName: string,\n output: string,\n metadata?: Record<string, any>\n): string {\n const dir = getMaterializedDir(agentId);\n mkdirSync(dir, { recursive: true });\n\n const timestamp = Date.now();\n const filename = `${toolName}-${timestamp}.md`;\n const filepath = join(dir, filename);\n\n const lines: string[] = [\n `# Tool Output: ${toolName}`,\n '',\n `**Timestamp:** ${new Date(timestamp).toISOString()}`,\n ];\n\n if (metadata) {\n for (const [key, value] of Object.entries(metadata)) {\n lines.push(`**${key}:** ${value}`);\n }\n }\n\n lines.push('');\n lines.push('## Output');\n lines.push('');\n lines.push('```');\n lines.push(output);\n lines.push('```');\n lines.push('');\n\n writeFileSync(filepath, lines.join('\\n'));\n\n // Log to history\n logHistory(agentId, `materialized:${toolName}`, { file: filename });\n\n return filepath;\n}\n\n/**\n * List materialized outputs for an agent\n */\nexport function listMaterialized(agentId: string): Array<{\n tool: string;\n timestamp: number;\n file: string;\n}> {\n const dir = getMaterializedDir(agentId);\n if (!existsSync(dir)) return [];\n\n return readdirSync(dir)\n .filter((f) => f.endsWith('.md'))\n .map((f) => {\n const match = f.match(/^(.+)-(\\d+)\\.md$/);\n if (!match) return null;\n return {\n tool: match[1],\n timestamp: parseInt(match[2], 10),\n file: join(dir, f),\n };\n })\n .filter(Boolean) as Array<{ tool: string; timestamp: number; file: string }>;\n}\n\n/**\n * Read materialized output\n */\nexport function readMaterialized(filepath: string): string | null {\n if (!existsSync(filepath)) return null;\n return readFileSync(filepath, 'utf-8');\n}\n","import chalk from 'chalk';\nimport {\n getAgentHealth,\n pingAgent,\n handleStuckAgent,\n runHealthCheck,\n startHealthDaemon,\n formatHealthStatus,\n DEFAULT_PING_TIMEOUT_MS,\n DEFAULT_CONSECUTIVE_FAILURES,\n DEFAULT_COOLDOWN_MS,\n DEFAULT_CHECK_INTERVAL_MS,\n type HealthConfig,\n} from '../../../lib/health.js';\nimport { listRunningAgents } from '../../../lib/agents.js';\n\ninterface HealthOptions {\n json?: boolean;\n daemon?: boolean;\n interval?: number;\n}\n\nexport async function healthCommand(\n action?: string,\n arg?: string,\n options: HealthOptions = {}\n): Promise<void> {\n const config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: options.interval ? options.interval * 1000 : DEFAULT_CHECK_INTERVAL_MS,\n };\n\n switch (action) {\n case 'check': {\n // Run a single health check\n console.log(chalk.bold('Running health check...\\n'));\n\n const results = await runHealthCheck(config);\n\n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n\n console.log(`Checked: ${results.checked} agents`);\n console.log(` ${chalk.green('\\u2705 Healthy:')} ${results.healthy}`);\n console.log(` ${chalk.yellow('\\u26a0\\ufe0f Warning:')} ${results.warning}`);\n console.log(` ${chalk.hex('#FFA500')('\\u{1f7e0} Stuck:')} ${results.stuck}`);\n console.log(` ${chalk.red('\\u274c Dead:')} ${results.dead}`);\n\n if (results.recovered.length > 0) {\n console.log('');\n console.log(chalk.green('Recovered agents:'));\n for (const agentId of results.recovered) {\n console.log(` - ${agentId}`);\n }\n }\n break;\n }\n\n case 'status': {\n // Show health status of all agents\n const agents = listRunningAgents();\n\n if (agents.length === 0) {\n console.log(chalk.dim('No agents found.'));\n return;\n }\n\n const healthData = agents.map((agent) => {\n const health = getAgentHealth(agent.id);\n return { agent, health };\n });\n\n if (options.json) {\n console.log(JSON.stringify(healthData.map((d) => d.health), null, 2));\n return;\n }\n\n console.log(chalk.bold('Agent Health Status:\\n'));\n\n for (const { health } of healthData) {\n console.log(formatHealthStatus(health));\n console.log('');\n }\n break;\n }\n\n case 'ping': {\n // Ping a specific agent\n if (!arg) {\n console.log(chalk.red('Agent ID required'));\n console.log(chalk.dim('Usage: pan work health ping <agent-id>'));\n return;\n }\n\n const agentId = arg.startsWith('agent-') ? arg : `agent-${arg.toLowerCase()}`;\n console.log(chalk.dim(`Pinging ${agentId}...`));\n\n const health = pingAgent(agentId, config);\n\n if (options.json) {\n console.log(JSON.stringify(health, null, 2));\n return;\n }\n\n console.log('');\n console.log(formatHealthStatus(health));\n break;\n }\n\n case 'recover': {\n // Force recovery of a specific agent\n if (!arg) {\n console.log(chalk.red('Agent ID required'));\n console.log(chalk.dim('Usage: pan work health recover <agent-id>'));\n return;\n }\n\n const agentId = arg.startsWith('agent-') ? arg : `agent-${arg.toLowerCase()}`;\n console.log(chalk.dim(`Attempting recovery of ${agentId}...`));\n\n // Override config to allow immediate recovery\n const forceConfig = { ...config, consecutiveFailures: 0 };\n const result = await handleStuckAgent(agentId, forceConfig);\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (result.action === 'recovered') {\n console.log(chalk.green(`\\u2705 ${result.reason}`));\n } else if (result.action === 'cooldown') {\n console.log(chalk.yellow(`\\u26a0\\ufe0f ${result.reason}`));\n } else {\n console.log(chalk.dim(result.reason));\n }\n break;\n }\n\n case 'daemon': {\n // Start the health monitoring daemon\n console.log(chalk.bold('Starting Panopticon Health Daemon'));\n console.log(chalk.dim(`Check interval: ${config.checkIntervalMs / 1000}s`));\n console.log(chalk.dim(`Failure threshold: ${config.consecutiveFailures}`));\n console.log(chalk.dim(`Cooldown: ${config.cooldownMs / (1000 * 60)}m`));\n console.log('');\n console.log(chalk.dim('Press Ctrl+C to stop...\\n'));\n\n const stop = startHealthDaemon(config, (results) => {\n const timestamp = new Date().toLocaleTimeString();\n const statusParts = [\n `[${timestamp}]`,\n `\\u2705${results.healthy}`,\n `\\u26a0\\ufe0f${results.warning}`,\n `\\u{1f7e0}${results.stuck}`,\n `\\u274c${results.dead}`,\n ];\n\n if (results.recovered.length > 0) {\n statusParts.push(chalk.green(`+${results.recovered.length} recovered`));\n }\n\n console.log(statusParts.join(' '));\n });\n\n // Handle graceful shutdown\n process.on('SIGINT', () => {\n console.log('\\n' + chalk.dim('Stopping health daemon...'));\n stop();\n process.exit(0);\n });\n\n // Keep process running\n await new Promise(() => {});\n break;\n }\n\n default:\n console.log(chalk.bold('Health Monitoring Commands:'));\n console.log('');\n console.log(` ${chalk.cyan('pan work health check')} - Run single health check`);\n console.log(` ${chalk.cyan('pan work health status')} - Show all agent health`);\n console.log(` ${chalk.cyan('pan work health ping <id>')} - Ping specific agent`);\n console.log(` ${chalk.cyan('pan work health recover <id>')} - Force recover agent`);\n console.log(` ${chalk.cyan('pan work health daemon')} - Start health daemon`);\n console.log('');\n console.log(chalk.bold('Options:'));\n console.log(` ${chalk.dim('--json')} Output as JSON`);\n console.log(` ${chalk.dim('--interval <sec>')} Check interval for daemon (default: 30)`);\n console.log('');\n console.log(chalk.bold('Deacon Pattern Defaults:'));\n console.log(` Ping timeout: ${DEFAULT_PING_TIMEOUT_MS / 1000}s`);\n console.log(` Consecutive failures: ${DEFAULT_CONSECUTIVE_FAILURES}`);\n console.log(` Cooldown after kill: ${DEFAULT_COOLDOWN_MS / (1000 * 60)}m`);\n console.log('');\n }\n}\n","/**\n * Health Monitoring System (Deacon Pattern)\n *\n * Implements stuck detection and auto-recovery with cooldown:\n * - Default ping timeout: 30 seconds\n * - Default consecutive failures: 3\n * - Default cooldown: 5 minutes\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { AGENTS_DIR } from './paths.js';\nimport { recoverAgent, stopAgent, getAgentState } from './agents.js';\n\n// Deacon pattern defaults\nexport const DEFAULT_PING_TIMEOUT_MS = 30 * 1000; // 30 seconds\nexport const DEFAULT_CONSECUTIVE_FAILURES = 3;\nexport const DEFAULT_COOLDOWN_MS = 5 * 60 * 1000; // 5 minutes\nexport const DEFAULT_CHECK_INTERVAL_MS = 30 * 1000; // 30 seconds\n\nexport interface AgentHealth {\n agentId: string;\n status: 'healthy' | 'warning' | 'stuck' | 'dead';\n lastActivity?: string;\n lastPing?: string;\n lastPingResponse?: string;\n consecutiveFailures: number;\n lastForceKill?: string;\n forceKillCount: number;\n recoveryCount: number;\n inCooldown: boolean;\n}\n\nexport interface HealthConfig {\n pingTimeoutMs: number;\n consecutiveFailures: number;\n cooldownMs: number;\n checkIntervalMs: number;\n}\n\nfunction getHealthFile(agentId: string): string {\n return join(AGENTS_DIR, agentId, 'health.json');\n}\n\n/**\n * Get or create health record for an agent\n */\nexport function getAgentHealth(agentId: string): AgentHealth {\n const healthFile = getHealthFile(agentId);\n\n const defaultHealth: AgentHealth = {\n agentId,\n status: 'healthy',\n consecutiveFailures: 0,\n forceKillCount: 0,\n recoveryCount: 0,\n inCooldown: false,\n };\n\n if (existsSync(healthFile)) {\n try {\n const stored = JSON.parse(readFileSync(healthFile, 'utf-8'));\n return { ...defaultHealth, ...stored };\n } catch {}\n }\n\n return defaultHealth;\n}\n\n/**\n * Save health record for an agent\n */\nexport function saveAgentHealth(health: AgentHealth): void {\n const dir = join(AGENTS_DIR, health.agentId);\n mkdirSync(dir, { recursive: true });\n writeFileSync(getHealthFile(health.agentId), JSON.stringify(health, null, 2));\n}\n\n/**\n * Check if agent's tmux session is alive\n */\nexport function isAgentAlive(agentId: string): boolean {\n try {\n execSync(`tmux has-session -t \"${agentId}\" 2>/dev/null`, { encoding: 'utf-8' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get recent output from agent's terminal\n */\nexport function getAgentOutput(agentId: string, lines: number = 20): string | null {\n try {\n const output = execSync(\n `tmux capture-pane -t \"${agentId}\" -p -S -${lines} 2>/dev/null`,\n { encoding: 'utf-8', maxBuffer: 1024 * 1024 }\n );\n return output.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Send a health check nudge to the agent\n * Returns true if we detect activity, false otherwise\n */\nexport function sendHealthNudge(agentId: string): boolean {\n if (!isAgentAlive(agentId)) {\n return false;\n }\n\n // Capture output before nudge\n const outputBefore = getAgentOutput(agentId, 5);\n\n // Send a gentle nudge - just check if the session is responsive\n // We don't want to interrupt actual work, just verify the session exists\n try {\n // Check if there's been any recent output change\n // For now, we consider alive = responsive\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Ping an agent and update health status\n */\nexport function pingAgent(\n agentId: string,\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n }\n): AgentHealth {\n const health = getAgentHealth(agentId);\n health.lastPing = new Date().toISOString();\n\n // Check if session is alive\n const alive = isAgentAlive(agentId);\n\n if (!alive) {\n // Session is dead\n health.status = 'dead';\n health.consecutiveFailures++;\n } else {\n // Session is alive - check for activity\n const state = getAgentState(agentId);\n const lastActivity = state?.lastActivity ? new Date(state.lastActivity) : null;\n\n if (lastActivity) {\n const ageMs = Date.now() - lastActivity.getTime();\n const ageMinutes = ageMs / (1000 * 60);\n\n if (ageMinutes > 30) {\n health.status = 'stuck';\n health.consecutiveFailures++;\n } else if (ageMinutes > 15) {\n health.status = 'warning';\n // Don't increment failures for warning, just monitor\n } else {\n health.status = 'healthy';\n health.consecutiveFailures = 0;\n }\n } else {\n // No activity tracking, assume healthy if alive\n health.status = 'healthy';\n health.consecutiveFailures = 0;\n }\n\n health.lastPingResponse = new Date().toISOString();\n }\n\n // Check cooldown status\n if (health.lastForceKill) {\n const timeSinceKill = Date.now() - new Date(health.lastForceKill).getTime();\n health.inCooldown = timeSinceKill < config.cooldownMs;\n } else {\n health.inCooldown = false;\n }\n\n saveAgentHealth(health);\n return health;\n}\n\n/**\n * Handle a stuck agent - force kill and respawn with context\n */\nexport async function handleStuckAgent(\n agentId: string,\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n }\n): Promise<{ action: 'recovered' | 'cooldown' | 'skipped'; reason: string }> {\n const health = getAgentHealth(agentId);\n\n // Check if failures meet threshold\n if (health.consecutiveFailures < config.consecutiveFailures) {\n return {\n action: 'skipped',\n reason: `Only ${health.consecutiveFailures} failures (need ${config.consecutiveFailures})`,\n };\n }\n\n // Check cooldown\n if (health.lastForceKill) {\n const timeSinceKill = Date.now() - new Date(health.lastForceKill).getTime();\n if (timeSinceKill < config.cooldownMs) {\n const remainingMs = config.cooldownMs - timeSinceKill;\n const remainingMin = Math.ceil(remainingMs / (1000 * 60));\n return {\n action: 'cooldown',\n reason: `In cooldown (${remainingMin}m remaining)`,\n };\n }\n }\n\n // Force kill the agent\n try {\n stopAgent(agentId);\n } catch {}\n\n // Record the force kill\n health.lastForceKill = new Date().toISOString();\n health.forceKillCount++;\n health.consecutiveFailures = 0;\n health.status = 'dead';\n health.inCooldown = true;\n saveAgentHealth(health);\n\n // Attempt recovery\n try {\n const recovered = recoverAgent(agentId);\n if (recovered) {\n health.status = 'healthy';\n health.recoveryCount++;\n saveAgentHealth(health);\n return { action: 'recovered', reason: 'Force killed and respawned' };\n }\n } catch {}\n\n return { action: 'recovered', reason: 'Force killed (respawn failed)' };\n}\n\n/**\n * Run a single health check cycle for all agents\n */\nexport async function runHealthCheck(\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n }\n): Promise<{\n checked: number;\n healthy: number;\n warning: number;\n stuck: number;\n dead: number;\n recovered: string[];\n}> {\n const results = {\n checked: 0,\n healthy: 0,\n warning: 0,\n stuck: 0,\n dead: 0,\n recovered: [] as string[],\n };\n\n // Get all agent sessions\n let sessions: string[] = [];\n try {\n const output = execSync(\n 'tmux list-sessions -F \"#{session_name}\" 2>/dev/null || true',\n { encoding: 'utf-8' }\n );\n sessions = output\n .trim()\n .split('\\n')\n .filter((s) => s.startsWith('agent-'));\n } catch {}\n\n // Also check agents dir for crashed agents\n if (existsSync(AGENTS_DIR)) {\n const { readdirSync } = await import('fs');\n const dirs = readdirSync(AGENTS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory() && d.name.startsWith('agent-'))\n .map((d) => d.name);\n\n for (const dir of dirs) {\n if (!sessions.includes(dir)) {\n sessions.push(dir);\n }\n }\n }\n\n // Check each agent\n for (const agentId of sessions) {\n results.checked++;\n\n const health = pingAgent(agentId, config);\n\n switch (health.status) {\n case 'healthy':\n results.healthy++;\n break;\n case 'warning':\n results.warning++;\n break;\n case 'stuck':\n results.stuck++;\n // Handle stuck agent\n const result = await handleStuckAgent(agentId, config);\n if (result.action === 'recovered') {\n results.recovered.push(agentId);\n }\n break;\n case 'dead':\n results.dead++;\n // Handle dead agent\n const deadResult = await handleStuckAgent(agentId, config);\n if (deadResult.action === 'recovered') {\n results.recovered.push(agentId);\n }\n break;\n }\n }\n\n return results;\n}\n\n/**\n * Start the health monitoring daemon\n * Returns a stop function\n */\nexport function startHealthDaemon(\n config: HealthConfig = {\n pingTimeoutMs: DEFAULT_PING_TIMEOUT_MS,\n consecutiveFailures: DEFAULT_CONSECUTIVE_FAILURES,\n cooldownMs: DEFAULT_COOLDOWN_MS,\n checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS,\n },\n onCheck?: (results: Awaited<ReturnType<typeof runHealthCheck>>) => void\n): () => void {\n let running = true;\n\n const runLoop = async () => {\n while (running) {\n try {\n const results = await runHealthCheck(config);\n if (onCheck) {\n onCheck(results);\n }\n } catch (error) {\n console.error('Health check error:', error);\n }\n\n // Wait for next interval\n await new Promise((resolve) => setTimeout(resolve, config.checkIntervalMs));\n }\n };\n\n // Start the loop\n runLoop();\n\n // Return stop function\n return () => {\n running = false;\n };\n}\n\n/**\n * Format health status for display\n */\nexport function formatHealthStatus(health: AgentHealth): string {\n const statusIcons = {\n healthy: '\\u2705',\n warning: '\\u26a0\\ufe0f',\n stuck: '\\u{1f7e0}',\n dead: '\\u274c',\n };\n\n const lines: string[] = [\n `${statusIcons[health.status]} ${health.agentId}: ${health.status.toUpperCase()}`,\n ];\n\n if (health.lastPing) {\n lines.push(` Last ping: ${health.lastPing}`);\n }\n\n if (health.consecutiveFailures > 0) {\n lines.push(` Consecutive failures: ${health.consecutiveFailures}`);\n }\n\n if (health.forceKillCount > 0) {\n lines.push(` Force kills: ${health.forceKillCount}`);\n }\n\n if (health.recoveryCount > 0) {\n lines.push(` Recoveries: ${health.recoveryCount}`);\n }\n\n if (health.inCooldown) {\n lines.push(` Status: IN COOLDOWN`);\n }\n\n return lines.join('\\n');\n}\n","import { Command } from 'commander';\nimport { issueCommand } from './issue.js';\nimport { statusCommand } from './status.js';\nimport { tellCommand } from './tell.js';\nimport { killCommand } from './kill.js';\nimport { pendingCommand } from './pending.js';\nimport { approveCommand } from './approve.js';\nimport { planCommand } from './plan.js';\nimport { listCommand } from './list.js';\nimport { triageCommand } from './triage.js';\nimport { hookCommand } from './hook.js';\nimport { recoverCommand } from './recover.js';\nimport { cvCommand } from './cv.js';\nimport { contextCommand } from './context.js';\nimport { healthCommand } from './health.js';\n\nexport function registerWorkCommands(program: Command): void {\n const work = program\n .command('work')\n .description('Agent and work management');\n\n work\n .command('issue <id>')\n .description('Spawn agent for Linear issue')\n .option('--model <model>', 'Claude model (sonnet/opus/haiku)', 'sonnet')\n .option('--runtime <runtime>', 'AI runtime (claude/codex)', 'claude')\n .option('--dry-run', 'Show what would be created')\n .action(issueCommand);\n\n work\n .command('status')\n .description('Show all running agents')\n .option('--json', 'Output as JSON')\n .action(statusCommand);\n\n work\n .command('tell <id> <message>')\n .description('Send message to running agent')\n .action(tellCommand);\n\n work\n .command('kill <id>')\n .description('Kill an agent')\n .option('--force', 'Kill without confirmation')\n .action(killCommand);\n\n work\n .command('pending')\n .description('Show completed work awaiting review')\n .action(pendingCommand);\n\n work\n .command('approve <id>')\n .description('Approve agent work, merge MR, update Linear')\n .option('--no-merge', 'Skip MR merge')\n .option('--no-linear', 'Skip Linear status update')\n .action(approveCommand);\n\n work\n .command('plan <id>')\n .description('Create execution plan before spawning')\n .option('-o, --output <path>', 'Output file path')\n .option('--json', 'Output as JSON')\n .option('--skip-discovery', 'Skip interactive discovery phase')\n .option('--force', 'Force planning even for simple issues')\n .action(planCommand);\n\n work\n .command('list')\n .description('List issues from configured trackers')\n .option('--all', 'Include closed issues')\n .option('--mine', 'Show only my assigned issues')\n .option('--json', 'Output as JSON')\n .option('--tracker <type>', 'Query specific tracker (linear/github/gitlab)')\n .option('--all-trackers', 'Query all configured trackers')\n .action(listCommand);\n\n work\n .command('triage [id]')\n .description('Triage secondary tracker issues')\n .option('--create', 'Create primary issue from secondary')\n .option('--dismiss <reason>', 'Dismiss from triage')\n .action(triageCommand);\n\n work\n .command('hook [action] [idOrMessage...]')\n .description('GUPP hooks: check, push, pop, clear, mail, gupp')\n .option('--json', 'Output as JSON')\n .action((action, idOrMessage, options) => {\n hookCommand(action || 'help', idOrMessage?.join(' '), options);\n });\n\n work\n .command('recover [id]')\n .description('Recover crashed agents')\n .option('--all', 'Auto-recover all crashed agents')\n .option('--json', 'Output as JSON')\n .action(recoverCommand);\n\n work\n .command('cv [agentId]')\n .description('View agent CVs (work history) and rankings')\n .option('--json', 'Output as JSON')\n .option('--rankings', 'Show agent rankings')\n .action(cvCommand);\n\n work\n .command('context [action] [arg1] [arg2]')\n .description('Context engineering: state, checkpoint, history, materialize')\n .option('--json', 'Output as JSON')\n .action((action, arg1, arg2, options) => {\n contextCommand(action || 'help', arg1, arg2, options);\n });\n\n work\n .command('health [action] [id]')\n .description('Health monitoring: check, status, ping, recover, daemon')\n .option('--json', 'Output as JSON')\n .option('--interval <seconds>', 'Daemon check interval', '30')\n .action((action, id, options) => {\n healthCommand(action || 'help', id, {\n json: options.json,\n interval: parseInt(options.interval, 10),\n });\n });\n}\n\n// Re-export individual commands for direct use\nexport { statusCommand } from './status.js';\nexport { issueCommand } from './issue.js';\nexport { tellCommand } from './tell.js';\nexport { killCommand } from './kill.js';\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { join, basename } from 'path';\nimport { createWorktree, removeWorktree, listWorktrees } from '../../lib/worktree.js';\nimport { generateClaudeMd, TemplateVariables } from '../../lib/template.js';\nimport { mergeSkillsIntoWorkspace } from '../../lib/skills-merge.js';\nimport {\n resolveProjectFromIssue,\n hasProjects,\n PROJECTS_CONFIG_FILE,\n} from '../../lib/projects.js';\n\nexport function registerWorkspaceCommands(program: Command): void {\n const workspace = program.command('workspace').description('Workspace management');\n\n workspace\n .command('create <issueId>')\n .description('Create workspace for issue')\n .option('--dry-run', 'Show what would be created')\n .option('--no-skills', 'Skip skills symlink setup')\n .option('--labels <labels>', 'Comma-separated labels for routing (e.g., docs,marketing)')\n .option('--project <path>', 'Explicit project path (overrides registry)')\n .action(createCommand);\n\n workspace\n .command('list')\n .description('List all workspaces')\n .option('--json', 'Output as JSON')\n .option('--all', 'List workspaces across all registered projects')\n .action(listCommand);\n\n workspace\n .command('destroy <issueId>')\n .description('Destroy workspace')\n .option('--force', 'Force removal even with uncommitted changes')\n .option('--project <path>', 'Explicit project path (overrides registry)')\n .action(destroyCommand);\n}\n\ninterface CreateOptions {\n dryRun?: boolean;\n skills?: boolean;\n labels?: string;\n project?: string;\n}\n\nasync function createCommand(issueId: string, options: CreateOptions): Promise<void> {\n const spinner = ora('Creating workspace...').start();\n\n try {\n // Normalize issue ID (e.g., MIN-123 -> min-123)\n const normalizedId = issueId.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n const branchName = `feature/${normalizedId}`;\n const folderName = `feature-${normalizedId}`;\n\n // Parse labels if provided\n const labels = options.labels\n ? options.labels.split(',').map((l) => l.trim())\n : [];\n\n // Resolve project root - try registry first, fall back to cwd\n let projectRoot: string;\n let projectName: string | undefined;\n\n if (options.project) {\n // Explicit project path provided\n projectRoot = options.project;\n } else {\n // Try to resolve from project registry\n const resolved = resolveProjectFromIssue(issueId, labels);\n if (resolved) {\n projectRoot = resolved.projectPath;\n projectName = resolved.projectName;\n spinner.text = `Resolved project: ${projectName} (${projectRoot})`;\n } else if (hasProjects()) {\n // Registry exists but no match found - warn user\n spinner.warn(`No project found for ${issueId} in registry. Using current directory.`);\n spinner.start('Creating workspace...');\n projectRoot = process.cwd();\n } else {\n // No registry - use cwd (backward compatible)\n projectRoot = process.cwd();\n }\n }\n\n const workspacesDir = join(projectRoot, 'workspaces');\n const workspacePath = join(workspacesDir, folderName);\n\n if (options.dryRun) {\n spinner.info('Dry run mode');\n console.log('');\n console.log(chalk.bold('Would create:'));\n if (projectName) {\n console.log(` Project: ${chalk.green(projectName)}`);\n }\n console.log(` Root: ${chalk.dim(projectRoot)}`);\n console.log(` Workspace: ${chalk.cyan(workspacePath)}`);\n console.log(` Branch: ${chalk.cyan(branchName)}`);\n console.log(` CLAUDE.md: ${chalk.dim(join(workspacePath, 'CLAUDE.md'))}`);\n if (options.skills !== false) {\n console.log(` Skills: ${chalk.dim(join(workspacePath, '.claude', 'skills'))}`);\n }\n return;\n }\n\n // Check if already exists\n if (existsSync(workspacePath)) {\n spinner.fail(`Workspace already exists: ${workspacePath}`);\n process.exit(1);\n }\n\n // Check if we're in a git repo\n if (!existsSync(join(projectRoot, '.git'))) {\n spinner.fail('Not a git repository. Run this from the project root.');\n process.exit(1);\n }\n\n // Create worktree\n spinner.text = 'Creating git worktree...';\n createWorktree(projectRoot, workspacePath, branchName);\n\n // Generate CLAUDE.md\n spinner.text = 'Generating CLAUDE.md...';\n const variables: TemplateVariables = {\n FEATURE_FOLDER: folderName,\n BRANCH_NAME: branchName,\n ISSUE_ID: issueId.toUpperCase(),\n WORKSPACE_PATH: workspacePath,\n FRONTEND_URL: `https://${folderName}.localhost:3000`,\n API_URL: `https://api-${folderName}.localhost:8080`,\n PROJECT_NAME: projectName,\n };\n\n const claudeMd = generateClaudeMd(projectRoot, variables);\n writeFileSync(join(workspacePath, 'CLAUDE.md'), claudeMd);\n\n // Merge skills (unless disabled)\n let skillsResult = { added: [] as string[], skipped: [] as string[] };\n if (options.skills !== false) {\n spinner.text = 'Merging skills...';\n mkdirSync(join(workspacePath, '.claude', 'skills'), { recursive: true });\n skillsResult = mergeSkillsIntoWorkspace(workspacePath);\n }\n\n spinner.succeed('Workspace created!');\n\n console.log('');\n console.log(chalk.bold('Workspace Details:'));\n if (projectName) {\n console.log(` Project: ${chalk.green(projectName)}`);\n }\n console.log(` Path: ${chalk.cyan(workspacePath)}`);\n console.log(` Branch: ${chalk.dim(branchName)}`);\n console.log('');\n\n if (options.skills !== false) {\n console.log(chalk.bold('Skills:'));\n console.log(` Added: ${skillsResult.added.length} Panopticon skills`);\n if (skillsResult.skipped.length > 0) {\n console.log(` Skipped: ${chalk.dim(skillsResult.skipped.join(', '))}`);\n }\n console.log('');\n }\n\n console.log(chalk.dim(`Next: cd ${workspacePath}`));\n\n } catch (error: any) {\n spinner.fail(error.message);\n process.exit(1);\n }\n}\n\ninterface ListOptions {\n json?: boolean;\n all?: boolean;\n}\n\nasync function listCommand(options: ListOptions): Promise<void> {\n const { listProjects } = await import('../../lib/projects.js');\n const projects = listProjects();\n\n // If we have registered projects and --all is specified, list across all projects\n if (projects.length > 0 && options.all) {\n const allWorkspaces: Array<{\n projectName: string;\n projectPath: string;\n workspaces: ReturnType<typeof listWorktrees>;\n }> = [];\n\n for (const { key, config } of projects) {\n if (!existsSync(join(config.path, '.git'))) {\n continue;\n }\n\n const worktrees = listWorktrees(config.path);\n const workspaces = worktrees.filter(\n (w) => w.path.includes('/workspaces/') || w.path.includes('\\\\workspaces\\\\')\n );\n\n if (workspaces.length > 0) {\n allWorkspaces.push({\n projectName: config.name,\n projectPath: config.path,\n workspaces,\n });\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(allWorkspaces, null, 2));\n return;\n }\n\n if (allWorkspaces.length === 0) {\n console.log(chalk.dim('No workspaces found in any registered project.'));\n console.log(chalk.dim('Create one with: pan workspace create <issue-id>'));\n return;\n }\n\n for (const proj of allWorkspaces) {\n console.log(chalk.bold(`\\n${proj.projectName}\\n`));\n for (const ws of proj.workspaces) {\n const name = basename(ws.path);\n const status = ws.prunable ? chalk.yellow(' (prunable)') : '';\n console.log(` ${chalk.cyan(name)}${status}`);\n console.log(` Branch: ${ws.branch || chalk.dim('(detached)')}`);\n console.log(` Path: ${chalk.dim(ws.path)}`);\n }\n }\n return;\n }\n\n // Default behavior: list from current directory\n const projectRoot = process.cwd();\n\n // Check if we're in a git repo\n if (!existsSync(join(projectRoot, '.git'))) {\n console.error(chalk.red('Not a git repository.'));\n if (projects.length > 0) {\n console.log(chalk.dim('Tip: Use --all to list workspaces across all registered projects.'));\n }\n process.exit(1);\n }\n\n const worktrees = listWorktrees(projectRoot);\n\n // Filter to workspaces directory only\n const workspaces = worktrees.filter((w) =>\n w.path.includes('/workspaces/') || w.path.includes('\\\\workspaces\\\\')\n );\n\n if (options.json) {\n console.log(JSON.stringify(workspaces, null, 2));\n return;\n }\n\n if (workspaces.length === 0) {\n console.log(chalk.dim('No workspaces found.'));\n console.log(chalk.dim('Create one with: pan workspace create <issue-id>'));\n if (projects.length > 0) {\n console.log(chalk.dim('Tip: Use --all to list workspaces across all registered projects.'));\n }\n return;\n }\n\n console.log(chalk.bold('\\nWorkspaces\\n'));\n\n for (const ws of workspaces) {\n const name = basename(ws.path);\n const status = ws.prunable ? chalk.yellow(' (prunable)') : '';\n console.log(`${chalk.cyan(name)}${status}`);\n console.log(` Branch: ${ws.branch || chalk.dim('(detached)')}`);\n console.log(` Path: ${chalk.dim(ws.path)}`);\n console.log('');\n }\n}\n\ninterface DestroyOptions {\n force?: boolean;\n project?: string;\n}\n\nasync function destroyCommand(issueId: string, options: DestroyOptions): Promise<void> {\n const spinner = ora('Destroying workspace...').start();\n\n try {\n const normalizedId = issueId.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n const folderName = `feature-${normalizedId}`;\n\n // Resolve project root - try registry first, then explicit option, then cwd\n let projectRoot: string;\n\n if (options.project) {\n projectRoot = options.project;\n } else {\n // Try to resolve from project registry\n const resolved = resolveProjectFromIssue(issueId);\n if (resolved) {\n projectRoot = resolved.projectPath;\n } else {\n projectRoot = process.cwd();\n }\n }\n\n const workspacePath = join(projectRoot, 'workspaces', folderName);\n\n if (!existsSync(workspacePath)) {\n // If not found and we resolved from registry, also check cwd\n const cwdPath = join(process.cwd(), 'workspaces', folderName);\n if (projectRoot !== process.cwd() && existsSync(cwdPath)) {\n projectRoot = process.cwd();\n } else {\n spinner.fail(`Workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n }\n\n const finalWorkspacePath = join(projectRoot, 'workspaces', folderName);\n\n spinner.text = 'Removing git worktree...';\n removeWorktree(projectRoot, finalWorkspacePath);\n\n spinner.succeed(`Workspace destroyed: ${folderName}`);\n } catch (error: any) {\n spinner.fail(error.message);\n if (!options.force) {\n console.log(chalk.dim('Tip: Use --force to remove even with uncommitted changes'));\n }\n process.exit(1);\n }\n}\n","import { execSync } from 'child_process';\nimport { mkdirSync } from 'fs';\nimport { dirname } from 'path';\n\nexport interface WorktreeInfo {\n path: string;\n branch: string;\n head: string;\n prunable: boolean;\n}\n\nexport function listWorktrees(repoPath: string): WorktreeInfo[] {\n const output = execSync('git worktree list --porcelain', {\n cwd: repoPath,\n encoding: 'utf8',\n });\n\n const worktrees: WorktreeInfo[] = [];\n let current: Partial<WorktreeInfo> = {};\n\n for (const line of output.split('\\n')) {\n if (line.startsWith('worktree ')) {\n if (current.path) worktrees.push(current as WorktreeInfo);\n current = { path: line.slice(9), prunable: false };\n } else if (line.startsWith('HEAD ')) {\n current.head = line.slice(5);\n } else if (line.startsWith('branch ')) {\n current.branch = line.slice(7).replace('refs/heads/', '');\n } else if (line === 'prunable') {\n current.prunable = true;\n }\n }\n if (current.path) worktrees.push(current as WorktreeInfo);\n\n return worktrees;\n}\n\nexport function createWorktree(\n repoPath: string,\n targetPath: string,\n branchName: string\n): void {\n // Ensure parent directory exists\n mkdirSync(dirname(targetPath), { recursive: true });\n\n // Check if branch exists\n try {\n execSync(`git show-ref --verify --quiet refs/heads/${branchName}`, {\n cwd: repoPath,\n });\n // Branch exists, just add worktree\n execSync(`git worktree add \"${targetPath}\" \"${branchName}\"`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n } catch {\n // Branch doesn't exist, create it\n execSync(`git worktree add -b \"${branchName}\" \"${targetPath}\"`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n }\n}\n\nexport function removeWorktree(repoPath: string, worktreePath: string): void {\n execSync(`git worktree remove \"${worktreePath}\" --force`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n}\n\nexport function pruneWorktrees(repoPath: string): void {\n execSync('git worktree prune', { cwd: repoPath, stdio: 'pipe' });\n}\n","import { readFileSync, existsSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { CLAUDE_MD_TEMPLATES } from './paths.js';\n\nexport interface TemplateVariables {\n FEATURE_FOLDER: string;\n BRANCH_NAME: string;\n ISSUE_ID: string;\n WORKSPACE_PATH: string;\n FRONTEND_URL?: string;\n API_URL?: string;\n PROJECT_NAME?: string;\n PROJECT_DOMAIN?: string;\n [key: string]: string | undefined;\n}\n\nexport function loadTemplate(templatePath: string): string {\n if (!existsSync(templatePath)) {\n throw new Error(`Template not found: ${templatePath}`);\n }\n return readFileSync(templatePath, 'utf8');\n}\n\nexport function substituteVariables(\n template: string,\n variables: TemplateVariables\n): string {\n let result = template;\n\n for (const [key, value] of Object.entries(variables)) {\n if (value !== undefined) {\n // Replace {{KEY}} and ${KEY} patterns\n result = result.replace(new RegExp(`\\\\{\\\\{${key}\\\\}\\\\}`, 'g'), value);\n result = result.replace(new RegExp(`\\\\$\\\\{${key}\\\\}`, 'g'), value);\n }\n }\n\n return result;\n}\n\nexport function generateClaudeMd(\n projectPath: string,\n variables: TemplateVariables\n): string {\n const sections: string[] = [];\n\n // Layer 1: Panopticon default sections\n const defaultOrder = [\n 'workspace-info.md',\n 'beads.md',\n 'commands-skills.md',\n 'warnings.md',\n ];\n\n for (const section of defaultOrder) {\n const sectionPath = join(CLAUDE_MD_TEMPLATES, section);\n if (existsSync(sectionPath)) {\n const content = loadTemplate(sectionPath);\n sections.push(substituteVariables(content, variables));\n }\n }\n\n // Layer 2: Project-specific sections\n const projectSections = join(projectPath, '.panopticon', 'claude-md', 'sections');\n if (existsSync(projectSections)) {\n const projectFiles = readdirSync(projectSections)\n .filter((f) => f.endsWith('.md'))\n .sort();\n\n for (const file of projectFiles) {\n const content = loadTemplate(join(projectSections, file));\n sections.push(substituteVariables(content, variables));\n }\n }\n\n // If no sections found, return minimal CLAUDE.md\n if (sections.length === 0) {\n return `# Workspace: ${variables.FEATURE_FOLDER}\n\n**Issue:** ${variables.ISSUE_ID}\n**Branch:** ${variables.BRANCH_NAME}\n**Path:** ${variables.WORKSPACE_PATH}\n\n## Getting Started\n\nThis workspace was created by Panopticon. Use \\`bd\\` commands to track your work.\n`;\n }\n\n return sections.join('\\n\\n---\\n\\n');\n}\n","import {\n existsSync,\n readdirSync,\n lstatSync,\n readlinkSync,\n symlinkSync,\n mkdirSync,\n appendFileSync,\n} from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { SKILLS_DIR } from './paths.js';\n\ntype ContentOrigin = 'git-tracked' | 'panopticon' | 'user-untracked';\n\nfunction detectContentOrigin(path: string, repoPath: string): ContentOrigin {\n try {\n const stat = lstatSync(path);\n\n // Check if symlink pointing to panopticon\n if (stat.isSymbolicLink()) {\n const target = readlinkSync(path);\n if (target.includes('.panopticon')) {\n return 'panopticon';\n }\n }\n\n // Check if git-tracked\n try {\n execSync(`git ls-files --error-unmatch \"${path}\" 2>/dev/null`, {\n cwd: repoPath,\n stdio: 'pipe',\n });\n return 'git-tracked';\n } catch {\n return 'user-untracked';\n }\n } catch {\n return 'user-untracked';\n }\n}\n\nexport function mergeSkillsIntoWorkspace(workspacePath: string): {\n added: string[];\n skipped: string[];\n} {\n const skillsTarget = join(workspacePath, '.claude', 'skills');\n const added: string[] = [];\n const skipped: string[] = [];\n\n // Ensure target directory exists\n mkdirSync(skillsTarget, { recursive: true });\n\n // Get existing skills in workspace\n const existingSkills = new Set<string>();\n if (existsSync(skillsTarget)) {\n for (const item of readdirSync(skillsTarget)) {\n existingSkills.add(item);\n }\n }\n\n // Get panopticon skills\n if (!existsSync(SKILLS_DIR)) return { added, skipped };\n\n const panopticonSkills = readdirSync(SKILLS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n for (const skill of panopticonSkills) {\n const targetPath = join(skillsTarget, skill);\n const sourcePath = join(SKILLS_DIR, skill);\n\n // Skip if exists and is git-tracked\n if (existingSkills.has(skill)) {\n const origin = detectContentOrigin(targetPath, workspacePath);\n if (origin === 'git-tracked') {\n skipped.push(`${skill} (git-tracked)`);\n continue;\n }\n if (origin === 'panopticon') {\n // Already ours, skip silently\n continue;\n }\n }\n\n // Create symlink\n try {\n symlinkSync(sourcePath, targetPath);\n added.push(skill);\n } catch (error: any) {\n if (error.code !== 'EEXIST') {\n // If exists but not symlink, skip\n skipped.push(`${skill} (exists)`);\n }\n }\n }\n\n // Update .gitignore if we added anything\n if (added.length > 0) {\n updateGitignore(skillsTarget, added);\n }\n\n return { added, skipped };\n}\n\nfunction updateGitignore(skillsDir: string, skills: string[]): void {\n const gitignorePath = join(skillsDir, '.gitignore');\n\n const content = `# Panopticon-managed symlinks (not committed)\n${skills.join('\\n')}\n`;\n\n try {\n appendFileSync(gitignorePath, content);\n } catch {\n // Ignore errors writing .gitignore\n }\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { execSync } from 'child_process';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { homedir, platform } from 'os';\nimport {\n PANOPTICON_HOME,\n INIT_DIRS,\n CERTS_DIR,\n TRAEFIK_DIR,\n TRAEFIK_DYNAMIC_DIR,\n TRAEFIK_CERTS_DIR,\n SOURCE_TRAEFIK_TEMPLATES\n} from '../../lib/paths.js';\nimport { getDefaultConfig, saveConfig } from '../../lib/config.js';\n\nexport function registerInstallCommand(program: Command): void {\n program\n .command('install')\n .description('Install Panopticon prerequisites')\n .option('--check', 'Check prerequisites only')\n .option('--minimal', 'Skip Traefik and mkcert (use port-based routing)')\n .option('--skip-mkcert', 'Skip mkcert/HTTPS setup')\n .option('--skip-docker', 'Skip Docker network setup')\n .action(installCommand);\n}\n\ninterface InstallOptions {\n check?: boolean;\n minimal?: boolean;\n skipMkcert?: boolean;\n skipDocker?: boolean;\n}\n\ninterface PrereqResult {\n name: string;\n passed: boolean;\n message: string;\n fix?: string;\n}\n\nfunction detectPlatform(): 'linux' | 'darwin' | 'win32' | 'wsl' {\n const os = platform();\n if (os === 'linux') {\n // Check for WSL\n try {\n const release = readFileSync('/proc/version', 'utf8').toLowerCase();\n if (release.includes('microsoft') || release.includes('wsl')) {\n return 'wsl';\n }\n } catch {}\n return 'linux';\n }\n return os as 'darwin' | 'win32';\n}\n\n/**\n * Recursively copy directory contents\n */\nfunction copyDirectoryRecursive(source: string, dest: string): void {\n if (!existsSync(source)) {\n throw new Error(`Source directory not found: ${source}`);\n }\n\n mkdirSync(dest, { recursive: true });\n\n const entries = readdirSync(source);\n for (const entry of entries) {\n const sourcePath = join(source, entry);\n const destPath = join(dest, entry);\n const stat = statSync(sourcePath);\n\n if (stat.isDirectory()) {\n copyDirectoryRecursive(sourcePath, destPath);\n } else {\n copyFileSync(sourcePath, destPath);\n }\n }\n}\n\nfunction checkCommand(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction checkPrerequisites(): { results: PrereqResult[]; allPassed: boolean } {\n const results: PrereqResult[] = [];\n\n // Node.js\n const nodeVersion = process.version;\n const nodeMajor = parseInt(nodeVersion.slice(1).split('.')[0]);\n results.push({\n name: 'Node.js',\n passed: nodeMajor >= 18,\n message: nodeMajor >= 18 ? `v${nodeVersion}` : `v${nodeVersion} (need v18+)`,\n fix: 'Install Node.js 18+ from https://nodejs.org',\n });\n\n // Git\n const hasGit = checkCommand('git');\n results.push({\n name: 'Git',\n passed: hasGit,\n message: hasGit ? 'installed' : 'not found',\n fix: 'Install git from your package manager',\n });\n\n // Docker\n const hasDocker = checkCommand('docker');\n let dockerRunning = false;\n if (hasDocker) {\n try {\n execSync('docker info', { stdio: 'pipe' });\n dockerRunning = true;\n } catch {}\n }\n results.push({\n name: 'Docker',\n passed: dockerRunning,\n message: dockerRunning ? 'running' : hasDocker ? 'not running' : 'not found',\n fix: hasDocker ? 'Start Docker Desktop or docker service' : 'Install Docker',\n });\n\n // tmux\n const hasTmux = checkCommand('tmux');\n results.push({\n name: 'tmux',\n passed: hasTmux,\n message: hasTmux ? 'installed' : 'not found',\n fix: 'apt install tmux / brew install tmux',\n });\n\n // mkcert (optional but recommended)\n const hasMkcert = checkCommand('mkcert');\n results.push({\n name: 'mkcert',\n passed: hasMkcert,\n message: hasMkcert ? 'installed' : 'not found (optional)',\n fix: 'brew install mkcert / apt install mkcert',\n });\n\n // Beads CLI\n const hasBeads = checkCommand('bd');\n results.push({\n name: 'Beads CLI (bd)',\n passed: hasBeads,\n message: hasBeads ? 'installed' : 'not found',\n fix: 'cargo install beads-cli',\n });\n\n // ttyd (web terminal for planning sessions)\n const hasTtyd = checkCommand('ttyd') || existsSync(join(homedir(), 'bin', 'ttyd'));\n results.push({\n name: 'ttyd',\n passed: hasTtyd,\n message: hasTtyd ? 'installed' : 'not found',\n fix: 'brew install ttyd / Download from https://github.com/tsl0922/ttyd/releases',\n });\n\n return {\n results,\n allPassed: results.filter((r) => r.name !== 'mkcert' && r.name !== 'ttyd').every((r) => r.passed),\n };\n}\n\nfunction printPrereqStatus(prereqs: { results: PrereqResult[]; allPassed: boolean }): void {\n console.log(chalk.bold('Prerequisites:\\n'));\n\n for (const result of prereqs.results) {\n const icon = result.passed ? chalk.green('✓') : chalk.red('✗');\n const msg = result.passed ? chalk.dim(result.message) : chalk.yellow(result.message);\n console.log(` ${icon} ${result.name}: ${msg}`);\n if (!result.passed && result.fix) {\n console.log(` ${chalk.dim('→ ' + result.fix)}`);\n }\n }\n console.log('');\n}\n\nasync function installCommand(options: InstallOptions): Promise<void> {\n console.log(chalk.bold('\\nPanopticon Installation\\n'));\n\n const plat = detectPlatform();\n console.log(`Platform: ${chalk.cyan(plat)}\\n`);\n\n // Step 1: Check prerequisites\n const prereqs = checkPrerequisites();\n\n if (options.check) {\n printPrereqStatus(prereqs);\n process.exit(prereqs.allPassed ? 0 : 1);\n }\n\n printPrereqStatus(prereqs);\n\n if (!prereqs.allPassed) {\n console.log(chalk.red('Fix prerequisites above before continuing.'));\n console.log(chalk.dim('Tip: Run with --minimal to skip optional components'));\n process.exit(1);\n }\n\n // Step 2: Initialize directories\n const spinner = ora('Initializing Panopticon directories...').start();\n for (const dir of INIT_DIRS) {\n mkdirSync(dir, { recursive: true });\n }\n spinner.succeed('Directories initialized');\n\n // Step 3: Docker network\n if (!options.skipDocker) {\n spinner.start('Creating Docker network...');\n try {\n execSync('docker network create panopticon 2>/dev/null || true', { stdio: 'pipe' });\n spinner.succeed('Docker network ready');\n } catch (error) {\n spinner.warn('Docker network setup failed (may already exist)');\n }\n }\n\n // Step 4: mkcert setup\n if (!options.skipMkcert && !options.minimal) {\n const hasMkcert = checkCommand('mkcert');\n if (hasMkcert) {\n spinner.start('Setting up mkcert CA...');\n try {\n execSync('mkcert -install', { stdio: 'pipe' });\n spinner.succeed('mkcert CA installed');\n\n // Generate wildcard certificates\n spinner.start('Generating wildcard certificates...');\n const traefikCertFile = join(TRAEFIK_CERTS_DIR, '_wildcard.pan.localhost.pem');\n const traefikKeyFile = join(TRAEFIK_CERTS_DIR, '_wildcard.pan.localhost-key.pem');\n\n execSync(\n `mkcert -cert-file \"${traefikCertFile}\" -key-file \"${traefikKeyFile}\" \"*.pan.localhost\" \"*.localhost\" localhost 127.0.0.1 ::1`,\n { stdio: 'pipe' }\n );\n\n // Also copy to legacy certs directory for backwards compatibility\n const legacyCertFile = join(CERTS_DIR, 'localhost.pem');\n const legacyKeyFile = join(CERTS_DIR, 'localhost-key.pem');\n copyFileSync(traefikCertFile, legacyCertFile);\n copyFileSync(traefikKeyFile, legacyKeyFile);\n\n spinner.succeed('Wildcard certificates generated (*.pan.localhost, *.localhost)');\n } catch (error) {\n spinner.warn('mkcert setup failed (HTTPS may not work)');\n }\n } else {\n spinner.info('Skipping mkcert (not installed)');\n }\n }\n\n // Step 5: Install ttyd (web terminal for planning sessions)\n const hasTtyd = checkCommand('ttyd') || existsSync(join(homedir(), 'bin', 'ttyd'));\n if (!hasTtyd) {\n spinner.start('Installing ttyd (web terminal)...');\n try {\n const binDir = join(homedir(), 'bin');\n mkdirSync(binDir, { recursive: true });\n const ttydPath = join(binDir, 'ttyd');\n\n // Determine platform and download appropriate binary\n const plat = detectPlatform();\n let downloadUrl = '';\n if (plat === 'darwin') {\n // macOS - try homebrew first\n try {\n execSync('brew install ttyd', { stdio: 'pipe' });\n spinner.succeed('ttyd installed via Homebrew');\n } catch {\n spinner.warn('ttyd installation failed - install manually: brew install ttyd');\n }\n } else {\n // Linux/WSL - download binary\n downloadUrl = 'https://github.com/tsl0922/ttyd/releases/latest/download/ttyd.x86_64';\n try {\n execSync(`curl -sL \"${downloadUrl}\" -o \"${ttydPath}\" && chmod +x \"${ttydPath}\"`, {\n stdio: 'pipe',\n timeout: 60000,\n });\n spinner.succeed(`ttyd installed to ${ttydPath}`);\n } catch (error) {\n spinner.warn('ttyd download failed - install manually from https://github.com/tsl0922/ttyd/releases');\n }\n }\n } catch (error) {\n spinner.warn('ttyd installation failed (planning sessions will not work)');\n }\n } else {\n spinner.info('ttyd already installed');\n }\n\n // Step 6: Setup Traefik configuration\n if (!options.minimal) {\n spinner.start('Setting up Traefik configuration...');\n\n try {\n // Copy Traefik templates from package to ~/.panopticon/traefik/\n // Only copy if files don't already exist\n if (!existsSync(join(TRAEFIK_DIR, 'docker-compose.yml'))) {\n copyDirectoryRecursive(SOURCE_TRAEFIK_TEMPLATES, TRAEFIK_DIR);\n spinner.succeed('Traefik configuration created from templates');\n } else {\n spinner.info('Traefik configuration already exists (skipping)');\n }\n } catch (error) {\n spinner.fail(`Failed to set up Traefik configuration: ${error}`);\n console.log(chalk.yellow('You can set up Traefik manually later'));\n }\n }\n\n // Step 6: Create config file if doesn't exist\n const configFile = join(PANOPTICON_HOME, 'config.toml');\n if (!existsSync(configFile)) {\n spinner.start('Creating default config...');\n\n // Get default config and customize based on install options\n const config = getDefaultConfig();\n\n // Configure Traefik based on minimal flag\n if (options.minimal) {\n config.traefik = {\n enabled: false,\n };\n } else {\n config.traefik = {\n enabled: true,\n dashboard_port: 8080,\n domain: 'pan.localhost',\n };\n }\n\n saveConfig(config);\n spinner.succeed('Config created');\n }\n\n // Done!\n console.log('');\n console.log(chalk.green.bold('Installation complete!'));\n console.log('');\n console.log(chalk.bold('Next steps:'));\n console.log(` 1. Run ${chalk.cyan('pan sync')} to sync skills to ~/.claude/`);\n\n if (!options.minimal) {\n console.log(` 2. Add to ${chalk.yellow('/etc/hosts')}: ${chalk.cyan('127.0.0.1 pan.localhost')}`);\n console.log(` 3. Run ${chalk.cyan('pan up')} to start Traefik and dashboard`);\n console.log(` 4. Access dashboard at ${chalk.cyan('https://pan.localhost')}`);\n } else {\n console.log(` 2. Run ${chalk.cyan('pan up')} to start the dashboard`);\n console.log(` 3. Access dashboard at ${chalk.cyan('http://localhost:3001')}`);\n }\n\n console.log(` ${!options.minimal ? '5' : '4'}. Create a workspace with ${chalk.cyan('pan workspace create <issue-id>')}`);\n console.log('');\n}\n","/**\n * pan cloister status command\n *\n * Display Cloister service status and agent health summary.\n */\n\nimport chalk from 'chalk';\nimport { getCloisterService } from '../../../lib/cloister/service.js';\nimport { getHealthEmoji, getHealthLabel } from '../../../lib/cloister/health.js';\n\ninterface StatusOptions {\n json?: boolean;\n}\n\nexport async function statusCommand(options: StatusOptions): Promise<void> {\n const service = getCloisterService();\n const status = service.getStatus();\n\n if (options.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n\n console.log(chalk.bold('\\n🔔 Cloister Agent Watchdog\\n'));\n\n // Service status\n const runningStatus = status.running ? chalk.green('Running') : chalk.red('Stopped');\n console.log(`Status: ${runningStatus}`);\n\n if (status.lastCheck) {\n const lastCheck = new Date(status.lastCheck);\n const timeSince = Math.floor((Date.now() - lastCheck.getTime()) / 1000);\n console.log(`Last check: ${timeSince}s ago`);\n }\n\n console.log('');\n\n // Agent summary\n console.log(chalk.bold('Agent Health Summary:'));\n console.log(` 🟢 Active: ${chalk.green(status.summary.active)}`);\n console.log(` 🟡 Stale: ${chalk.yellow(status.summary.stale)}`);\n console.log(` 🟠 Warning: ${chalk.hex('#FFA500')(status.summary.warning)}`);\n console.log(` 🔴 Stuck: ${chalk.red(status.summary.stuck)}`);\n console.log(` Total: ${status.summary.total}`);\n\n console.log('');\n\n // Agents needing attention\n if (status.agentsNeedingAttention.length > 0) {\n console.log(chalk.bold('⚠️ Agents Needing Attention:'));\n for (const agentId of status.agentsNeedingAttention) {\n const health = service.getAgentHealth(agentId);\n if (health) {\n const emoji = getHealthEmoji(health.state);\n const label = getHealthLabel(health.state);\n const color = health.state === 'warning' ? chalk.hex('#FFA500') : chalk.red;\n console.log(` ${emoji} ${color(agentId)} - ${label}`);\n }\n }\n console.log('');\n }\n\n // Configuration\n console.log(chalk.bold('Configuration:'));\n console.log(` Auto-start: ${status.config.startup.auto_start ? 'enabled' : 'disabled'}`);\n console.log(` Thresholds: stale=${status.config.thresholds.stale}m, warning=${status.config.thresholds.warning}m, stuck=${status.config.thresholds.stuck}m`);\n console.log(` Auto-actions:`);\n console.log(` - Poke on warning: ${status.config.auto_actions.poke_on_warning ? 'enabled' : 'disabled'}`);\n console.log(` - Kill on stuck: ${status.config.auto_actions.kill_on_stuck ? chalk.red('enabled') : 'disabled'}`);\n\n console.log('');\n}\n","/**\n * Cloister Configuration\n *\n * Loads and manages Cloister configuration from ~/.panopticon/cloister.toml\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { parse, stringify } from '@iarna/toml';\nimport { join } from 'path';\nimport { PANOPTICON_HOME } from '../paths.js';\n\nconst CLOISTER_CONFIG_FILE = join(PANOPTICON_HOME, 'cloister.toml');\n\n/**\n * Health threshold configuration (in minutes)\n */\nexport interface HealthThresholds {\n stale: number;\n warning: number;\n stuck: number;\n}\n\n/**\n * Automatic action configuration\n */\nexport interface AutoActions {\n poke_on_warning: boolean;\n kill_on_stuck: boolean;\n restart_on_kill: boolean;\n}\n\n/**\n * Monitoring configuration\n */\nexport interface MonitoringConfig {\n check_interval: number; // seconds between health checks\n heartbeat_sources: ('jsonl_mtime' | 'tmux_activity' | 'git_activity' | 'active_heartbeat')[];\n}\n\n/**\n * Startup configuration\n */\nexport interface StartupConfig {\n auto_start: boolean; // Start Cloister when dashboard starts\n}\n\n/**\n * Notification configuration (future feature)\n */\nexport interface NotificationConfig {\n slack_webhook?: string;\n email?: string;\n}\n\n/**\n * Specialist agent configuration\n */\nexport interface SpecialistConfig {\n enabled: boolean;\n auto_wake: boolean;\n}\n\n/**\n * All specialist agents configuration\n */\nexport interface SpecialistsConfig {\n merge_agent?: SpecialistConfig;\n review_agent?: SpecialistConfig;\n test_agent?: SpecialistConfig;\n}\n\n/**\n * Model selection configuration\n */\nexport interface ModelSelectionConfig {\n default_model: 'opus' | 'sonnet' | 'haiku';\n complexity_routing: {\n trivial: 'opus' | 'sonnet' | 'haiku';\n simple: 'opus' | 'sonnet' | 'haiku';\n medium: 'opus' | 'sonnet' | 'haiku';\n complex: 'opus' | 'sonnet' | 'haiku';\n expert: 'opus' | 'sonnet' | 'haiku';\n };\n specialist_models: {\n merge_agent: 'opus' | 'sonnet' | 'haiku';\n review_agent: 'opus' | 'sonnet' | 'haiku';\n test_agent: 'opus' | 'sonnet' | 'haiku';\n planning_agent: 'opus' | 'sonnet' | 'haiku';\n };\n}\n\n/**\n * Handoff trigger configuration\n */\nexport interface HandoffTriggersConfig {\n planning_complete?: {\n enabled: boolean;\n from_model: 'opus' | 'sonnet' | 'haiku';\n to_model: 'opus' | 'sonnet' | 'haiku';\n };\n stuck_escalation?: {\n enabled: boolean;\n haiku_to_sonnet_minutes: number;\n sonnet_to_opus_minutes: number;\n };\n test_failure?: {\n enabled: boolean;\n from_model: 'opus' | 'sonnet' | 'haiku';\n to_model: 'opus' | 'sonnet' | 'haiku';\n trigger_on: 'any_failure' | '2_consecutive';\n };\n implementation_complete?: {\n enabled: boolean;\n to_specialist: string; // e.g., 'test-agent'\n };\n}\n\n/**\n * Handoff configuration\n */\nexport interface HandoffConfig {\n auto_triggers: HandoffTriggersConfig;\n}\n\n/**\n * Cost tracking configuration\n */\nexport interface CostTrackingConfig {\n display_enabled: boolean;\n log_to_jsonl: boolean;\n}\n\n/**\n * Complete Cloister configuration\n */\nexport interface CloisterConfig {\n startup: StartupConfig;\n thresholds: HealthThresholds;\n auto_actions: AutoActions;\n monitoring: MonitoringConfig;\n notifications?: NotificationConfig;\n specialists?: SpecialistsConfig;\n model_selection?: ModelSelectionConfig;\n handoffs?: HandoffConfig;\n cost_tracking?: CostTrackingConfig;\n}\n\n/**\n * Default Cloister configuration\n */\nexport const DEFAULT_CLOISTER_CONFIG: CloisterConfig = {\n startup: {\n auto_start: true,\n },\n thresholds: {\n stale: 5,\n warning: 15,\n stuck: 30,\n },\n auto_actions: {\n poke_on_warning: true,\n kill_on_stuck: false, // Manual by default for safety\n restart_on_kill: false,\n },\n monitoring: {\n check_interval: 60, // 1 minute\n heartbeat_sources: ['jsonl_mtime', 'tmux_activity', 'git_activity'],\n },\n notifications: {\n slack_webhook: undefined,\n email: undefined,\n },\n specialists: {\n merge_agent: {\n enabled: true,\n auto_wake: false, // Only wake on explicit \"Approve & Merge\" click\n },\n review_agent: {\n enabled: true,\n auto_wake: false, // Only wake on explicit request\n },\n test_agent: {\n enabled: false, // Not yet implemented\n auto_wake: false,\n },\n },\n model_selection: {\n default_model: 'sonnet',\n complexity_routing: {\n trivial: 'haiku',\n simple: 'haiku',\n medium: 'sonnet',\n complex: 'sonnet',\n expert: 'opus',\n },\n specialist_models: {\n merge_agent: 'sonnet',\n review_agent: 'sonnet',\n test_agent: 'haiku',\n planning_agent: 'opus',\n },\n },\n handoffs: {\n auto_triggers: {\n planning_complete: {\n enabled: true,\n from_model: 'opus',\n to_model: 'sonnet',\n },\n stuck_escalation: {\n enabled: true,\n haiku_to_sonnet_minutes: 10,\n sonnet_to_opus_minutes: 20,\n },\n test_failure: {\n enabled: true,\n from_model: 'haiku',\n to_model: 'sonnet',\n trigger_on: 'any_failure',\n },\n implementation_complete: {\n enabled: true, // Auto-handoff to test-agent when implementation done\n to_specialist: 'test-agent',\n },\n },\n },\n cost_tracking: {\n display_enabled: true,\n log_to_jsonl: true,\n },\n};\n\n/**\n * Deep merge utility that recursively merges objects.\n * - Recursively merges nested objects\n * - Arrays in overrides replace defaults (not concatenated)\n * - User values take precedence over defaults\n */\nfunction deepMerge<T extends object>(defaults: T, overrides: Partial<T>): T {\n const result = { ...defaults };\n\n for (const key of Object.keys(overrides) as (keyof T)[]) {\n const defaultVal = defaults[key];\n const overrideVal = overrides[key];\n\n // Skip undefined values in overrides\n if (overrideVal === undefined) continue;\n\n // Deep merge if both values are non-array objects\n if (\n typeof defaultVal === 'object' &&\n defaultVal !== null &&\n !Array.isArray(defaultVal) &&\n typeof overrideVal === 'object' &&\n overrideVal !== null &&\n !Array.isArray(overrideVal)\n ) {\n result[key] = deepMerge(defaultVal as any, overrideVal as any);\n } else {\n // Direct override for primitives and arrays\n result[key] = overrideVal as T[keyof T];\n }\n }\n\n return result;\n}\n\n/**\n * Load Cloister configuration\n *\n * Reads from ~/.panopticon/cloister.toml and merges with defaults.\n * Creates default config file if it doesn't exist.\n */\nexport function loadCloisterConfig(): CloisterConfig {\n // Ensure panopticon home exists\n if (!existsSync(PANOPTICON_HOME)) {\n mkdirSync(PANOPTICON_HOME, { recursive: true });\n }\n\n // If config file doesn't exist, create it with defaults\n if (!existsSync(CLOISTER_CONFIG_FILE)) {\n saveCloisterConfig(DEFAULT_CLOISTER_CONFIG);\n return DEFAULT_CLOISTER_CONFIG;\n }\n\n try {\n const content = readFileSync(CLOISTER_CONFIG_FILE, 'utf-8');\n const parsed = parse(content) as unknown as Partial<CloisterConfig>;\n\n // Deep merge with defaults\n return deepMerge(DEFAULT_CLOISTER_CONFIG, parsed);\n } catch (error) {\n console.error('Failed to load Cloister config:', error);\n console.error('Using default configuration');\n return DEFAULT_CLOISTER_CONFIG;\n }\n}\n\n/**\n * Save Cloister configuration\n *\n * Writes configuration to ~/.panopticon/cloister.toml\n */\nexport function saveCloisterConfig(config: CloisterConfig): void {\n // Ensure panopticon home exists\n if (!existsSync(PANOPTICON_HOME)) {\n mkdirSync(PANOPTICON_HOME, { recursive: true });\n }\n\n try {\n const content = stringify(config as any);\n writeFileSync(CLOISTER_CONFIG_FILE, content, 'utf-8');\n } catch (error) {\n console.error('Failed to save Cloister config:', error);\n throw error;\n }\n}\n\n/**\n * Update Cloister configuration\n *\n * Merges partial config updates with existing config.\n */\nexport function updateCloisterConfig(updates: Partial<CloisterConfig>): CloisterConfig {\n const current = loadCloisterConfig();\n const updated = deepMerge(current, updates);\n saveCloisterConfig(updated);\n return updated;\n}\n\n/**\n * Get the path to the Cloister config file\n */\nexport function getCloisterConfigPath(): string {\n return CLOISTER_CONFIG_FILE;\n}\n\n/**\n * Check if Cloister should auto-start\n */\nexport function shouldAutoStart(): boolean {\n const config = loadCloisterConfig();\n return config.startup.auto_start;\n}\n\n/**\n * Get health thresholds in milliseconds\n */\nexport function getHealthThresholdsMs(): {\n stale: number;\n warning: number;\n stuck: number;\n} {\n const config = loadCloisterConfig();\n return {\n stale: config.thresholds.stale * 60 * 1000,\n warning: config.thresholds.warning * 60 * 1000,\n stuck: config.thresholds.stuck * 60 * 1000,\n };\n}\n","/**\n * Cloister Health Evaluator\n *\n * Evaluates agent health based on heartbeats and activity timestamps.\n */\n\nimport type { HealthState, Heartbeat, AgentRuntime } from '../runtimes/types.js';\nimport type { HealthThresholds } from './config.js';\nimport { getHealthThresholdsMs } from './config.js';\n\n/**\n * Agent health status\n */\nexport interface AgentHealth {\n agentId: string;\n state: HealthState;\n lastActivity: Date | null;\n timeSinceActivity: number | null; // milliseconds\n heartbeat: Heartbeat | null;\n isRunning: boolean;\n}\n\n/**\n * Health summary for all agents\n */\nexport interface HealthSummary {\n active: number;\n stale: number;\n warning: number;\n stuck: number;\n total: number;\n}\n\n/**\n * Evaluate health state based on time since last activity\n *\n * @param timeSinceActivityMs - Milliseconds since last activity\n * @param thresholds - Health thresholds in milliseconds\n * @returns Health state\n */\nexport function evaluateHealthState(\n timeSinceActivityMs: number,\n thresholds: { stale: number; warning: number; stuck: number }\n): HealthState {\n if (timeSinceActivityMs < thresholds.stale) {\n return 'active';\n } else if (timeSinceActivityMs < thresholds.warning) {\n return 'stale';\n } else if (timeSinceActivityMs < thresholds.stuck) {\n return 'warning';\n } else {\n return 'stuck';\n }\n}\n\n/**\n * Get health status for a single agent\n *\n * @param agentId - Agent identifier\n * @param runtime - Runtime to query for heartbeat\n * @param thresholds - Health thresholds (optional, uses config if not provided)\n * @returns Agent health status\n */\nexport function getAgentHealth(\n agentId: string,\n runtime: AgentRuntime,\n thresholds?: { stale: number; warning: number; stuck: number }\n): AgentHealth {\n const thresholdsMs = thresholds || getHealthThresholdsMs();\n\n // Check if agent is running\n const isRunning = runtime.isRunning(agentId);\n\n if (!isRunning) {\n return {\n agentId,\n state: 'stuck',\n lastActivity: null,\n timeSinceActivity: null,\n heartbeat: null,\n isRunning: false,\n };\n }\n\n // Get heartbeat\n const heartbeat = runtime.getHeartbeat(agentId);\n\n if (!heartbeat) {\n // No heartbeat available - agent might be starting up\n return {\n agentId,\n state: 'active', // Assume active if no heartbeat yet\n lastActivity: null,\n timeSinceActivity: null,\n heartbeat: null,\n isRunning: true,\n };\n }\n\n // Calculate time since last activity\n const now = new Date();\n const timeSinceActivity = now.getTime() - heartbeat.timestamp.getTime();\n\n // Evaluate health state\n const state = evaluateHealthState(timeSinceActivity, thresholdsMs);\n\n return {\n agentId,\n state,\n lastActivity: heartbeat.timestamp,\n timeSinceActivity,\n heartbeat,\n isRunning: true,\n };\n}\n\n/**\n * Get health status for multiple agents\n *\n * @param agentIds - Array of agent identifiers\n * @param runtime - Runtime to query for heartbeats\n * @param thresholds - Health thresholds (optional, uses config if not provided)\n * @returns Array of agent health statuses\n */\nexport function getMultipleAgentHealth(\n agentIds: string[],\n runtime: AgentRuntime,\n thresholds?: { stale: number; warning: number; stuck: number }\n): AgentHealth[] {\n return agentIds.map((agentId) => getAgentHealth(agentId, runtime, thresholds));\n}\n\n/**\n * Generate health summary from agent health statuses\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Health summary with counts by state\n */\nexport function generateHealthSummary(agentHealths: AgentHealth[]): HealthSummary {\n const summary: HealthSummary = {\n active: 0,\n stale: 0,\n warning: 0,\n stuck: 0,\n total: agentHealths.length,\n };\n\n for (const health of agentHealths) {\n summary[health.state]++;\n }\n\n return summary;\n}\n\n/**\n * Check if an agent needs attention (warning or stuck)\n *\n * @param health - Agent health status\n * @returns True if agent needs attention\n */\nexport function needsAttention(health: AgentHealth): boolean {\n return health.state === 'warning' || health.state === 'stuck';\n}\n\n/**\n * Check if an agent should be poked (warning state)\n *\n * @param health - Agent health status\n * @returns True if agent should be poked\n */\nexport function shouldPoke(health: AgentHealth): boolean {\n return health.state === 'warning';\n}\n\n/**\n * Check if an agent should be killed (stuck state)\n *\n * @param health - Agent health status\n * @returns True if agent should be killed\n */\nexport function shouldKill(health: AgentHealth): boolean {\n return health.state === 'stuck';\n}\n\n/**\n * Get agents that need attention\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Array of agents needing attention\n */\nexport function getAgentsNeedingAttention(agentHealths: AgentHealth[]): AgentHealth[] {\n return agentHealths.filter(needsAttention);\n}\n\n/**\n * Get agents that should be poked\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Array of agents to poke\n */\nexport function getAgentsToPoke(agentHealths: AgentHealth[]): AgentHealth[] {\n return agentHealths.filter(shouldPoke);\n}\n\n/**\n * Get agents that should be killed\n *\n * @param agentHealths - Array of agent health statuses\n * @returns Array of agents to kill\n */\nexport function getAgentsToKill(agentHealths: AgentHealth[]): AgentHealth[] {\n return agentHealths.filter(shouldKill);\n}\n\n/**\n * Format time duration in human-readable format\n *\n * @param ms - Milliseconds\n * @returns Human-readable duration (e.g., \"5m\", \"2h\", \"1d\")\n */\nexport function formatDuration(ms: number | null): string {\n if (ms === null) {\n return 'unknown';\n }\n\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}d`;\n } else if (hours > 0) {\n return `${hours}h`;\n } else if (minutes > 0) {\n return `${minutes}m`;\n } else {\n return `${seconds}s`;\n }\n}\n\n/**\n * Get health emoji for a health state\n *\n * @param state - Health state\n * @returns Emoji representing the state\n */\nexport function getHealthEmoji(state: HealthState): string {\n switch (state) {\n case 'active':\n return '🟢';\n case 'stale':\n return '🟡';\n case 'warning':\n return '🟠';\n case 'stuck':\n return '🔴';\n }\n}\n\n/**\n * Get health label for a health state\n *\n * @param state - Health state\n * @returns Human-readable label\n */\nexport function getHealthLabel(state: HealthState): string {\n switch (state) {\n case 'active':\n return 'Active';\n case 'stale':\n return 'Stale';\n case 'warning':\n return 'Warning';\n case 'stuck':\n return 'Stuck';\n }\n}\n","/**\n * Cloister Health History Database\n *\n * SQLite storage for agent health events and history.\n * Stores health state transitions for visualization and analysis.\n */\n\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync, mkdirSync } from 'fs';\nimport { PANOPTICON_HOME } from '../paths.js';\nimport type { HealthState } from '../runtimes/types.js';\n\nconst CLOISTER_DB_PATH = join(PANOPTICON_HOME, 'cloister.db');\nconst RETENTION_DAYS = 7;\n\n/**\n * Health event stored in database\n */\nexport interface HealthEvent {\n id?: number;\n agentId: string;\n timestamp: string; // ISO 8601\n state: HealthState;\n previousState?: string;\n source?: string; // jsonl_mtime, tmux_activity, git_activity, active_heartbeat\n metadata?: string; // JSON string\n}\n\n/**\n * Health event with parsed metadata\n */\nexport interface HealthEventWithMetadata extends Omit<HealthEvent, 'metadata'> {\n metadata?: Record<string, any>;\n}\n\nlet db: Database.Database | null = null;\n\n/**\n * Initialize the health history database\n *\n * Creates the database file and schema if they don't exist.\n * Safe to call multiple times - idempotent.\n */\nexport function initHealthDatabase(): Database.Database {\n // Ensure panopticon home exists\n if (!existsSync(PANOPTICON_HOME)) {\n mkdirSync(PANOPTICON_HOME, { recursive: true });\n }\n\n // Open or create database\n db = new Database(CLOISTER_DB_PATH);\n\n // Enable WAL mode for better concurrency\n db.pragma('journal_mode = WAL');\n\n // Create schema\n db.exec(`\n CREATE TABLE IF NOT EXISTS health_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n agent_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n state TEXT NOT NULL,\n previous_state TEXT,\n source TEXT,\n metadata TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_agent_timestamp\n ON health_events(agent_id, timestamp);\n\n CREATE INDEX IF NOT EXISTS idx_timestamp\n ON health_events(timestamp);\n `);\n\n // Run cleanup on initialization\n cleanupOldEvents(db);\n\n return db;\n}\n\n/**\n * Get the database instance, initializing if necessary\n */\nexport function getHealthDatabase(): Database.Database {\n if (!db) {\n return initHealthDatabase();\n }\n return db;\n}\n\n/**\n * Close the database connection\n */\nexport function closeHealthDatabase(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n\n/**\n * Write a health event to the database\n *\n * @param event - Health event to store\n * @returns The ID of the inserted event\n */\nexport function writeHealthEvent(event: Omit<HealthEvent, 'id'>): number {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n INSERT INTO health_events (agent_id, timestamp, state, previous_state, source, metadata)\n VALUES (?, ?, ?, ?, ?, ?)\n `);\n\n const result = stmt.run(\n event.agentId,\n event.timestamp,\n event.state,\n event.previousState || null,\n event.source || null,\n event.metadata || null\n );\n\n return result.lastInsertRowid as number;\n}\n\n/**\n * Write multiple health events in a transaction\n *\n * @param events - Array of health events to store\n * @returns Number of events inserted\n */\nexport function writeHealthEvents(events: Omit<HealthEvent, 'id'>[]): number {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n INSERT INTO health_events (agent_id, timestamp, state, previous_state, source, metadata)\n VALUES (?, ?, ?, ?, ?, ?)\n `);\n\n const insertMany = database.transaction((eventsToInsert: Omit<HealthEvent, 'id'>[]) => {\n for (const event of eventsToInsert) {\n stmt.run(\n event.agentId,\n event.timestamp,\n event.state,\n event.previousState || null,\n event.source || null,\n event.metadata || null\n );\n }\n return eventsToInsert.length;\n });\n\n return insertMany(events);\n}\n\n/**\n * Get health events for an agent within a time range\n *\n * @param agentId - Agent identifier\n * @param startTime - Start of time range (ISO 8601)\n * @param endTime - End of time range (ISO 8601)\n * @returns Array of health events, ordered by timestamp\n */\nexport function getHealthHistory(\n agentId: string,\n startTime: string,\n endTime: string\n): HealthEventWithMetadata[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE agent_id = ? AND timestamp >= ? AND timestamp <= ?\n ORDER BY timestamp ASC\n `);\n\n const events = stmt.all(agentId, startTime, endTime) as HealthEvent[];\n\n // Parse metadata JSON\n return events.map((event) => ({\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n }));\n}\n\n/**\n * Get recent health events for an agent\n *\n * @param agentId - Agent identifier\n * @param limit - Maximum number of events to return (default: 100)\n * @returns Array of health events, ordered by timestamp descending\n */\nexport function getRecentHealthHistory(\n agentId: string,\n limit: number = 100\n): HealthEventWithMetadata[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE agent_id = ?\n ORDER BY timestamp DESC\n LIMIT ?\n `);\n\n const events = stmt.all(agentId, limit) as HealthEvent[];\n\n // Parse metadata JSON and reverse to get chronological order\n return events\n .map((event) => ({\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n }))\n .reverse();\n}\n\n/**\n * Get health events for all agents within a time range\n *\n * @param startTime - Start of time range (ISO 8601)\n * @param endTime - End of time range (ISO 8601)\n * @returns Array of health events, ordered by timestamp\n */\nexport function getAllHealthHistory(\n startTime: string,\n endTime: string\n): HealthEventWithMetadata[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE timestamp >= ? AND timestamp <= ?\n ORDER BY timestamp ASC\n `);\n\n const events = stmt.all(startTime, endTime) as HealthEvent[];\n\n // Parse metadata JSON\n return events.map((event) => ({\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n }));\n}\n\n/**\n * Get the latest health event for an agent\n *\n * @param agentId - Agent identifier\n * @returns Latest health event or null if none exist\n */\nexport function getLatestHealthEvent(agentId: string): HealthEventWithMetadata | null {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT id, agent_id as agentId, timestamp, state, previous_state as previousState,\n source, metadata\n FROM health_events\n WHERE agent_id = ?\n ORDER BY timestamp DESC\n LIMIT 1\n `);\n\n const event = stmt.get(agentId) as HealthEvent | undefined;\n\n if (!event) {\n return null;\n }\n\n return {\n ...event,\n metadata: event.metadata ? JSON.parse(event.metadata) : undefined,\n };\n}\n\n/**\n * Get list of all agents with health history\n *\n * @returns Array of unique agent IDs\n */\nexport function getAgentsWithHistory(): string[] {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n SELECT DISTINCT agent_id as agentId\n FROM health_events\n ORDER BY agent_id ASC\n `);\n\n const results = stmt.all() as { agentId: string }[];\n return results.map((r) => r.agentId);\n}\n\n/**\n * Delete health events older than the retention period\n *\n * @param database - Database instance\n * @param retentionDays - Number of days to retain (default: 7)\n * @returns Number of events deleted\n */\nexport function cleanupOldEvents(\n database: Database.Database = getHealthDatabase(),\n retentionDays: number = RETENTION_DAYS\n): number {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - retentionDays);\n const cutoffTimestamp = cutoffDate.toISOString();\n\n const stmt = database.prepare(`\n DELETE FROM health_events\n WHERE timestamp < ?\n `);\n\n const result = stmt.run(cutoffTimestamp);\n return result.changes;\n}\n\n/**\n * Delete all health events for a specific agent\n *\n * @param agentId - Agent identifier\n * @returns Number of events deleted\n */\nexport function deleteAgentHistory(agentId: string): number {\n const database = getHealthDatabase();\n\n const stmt = database.prepare(`\n DELETE FROM health_events\n WHERE agent_id = ?\n `);\n\n const result = stmt.run(agentId);\n return result.changes;\n}\n\n/**\n * Get database statistics\n *\n * @returns Statistics about the health history database\n */\nexport function getDatabaseStats(): {\n totalEvents: number;\n uniqueAgents: number;\n oldestEvent: string | null;\n newestEvent: string | null;\n} {\n const database = getHealthDatabase();\n\n const countStmt = database.prepare('SELECT COUNT(*) as count FROM health_events');\n const agentStmt = database.prepare('SELECT COUNT(DISTINCT agent_id) as count FROM health_events');\n const oldestStmt = database.prepare('SELECT MIN(timestamp) as oldest FROM health_events');\n const newestStmt = database.prepare('SELECT MAX(timestamp) as newest FROM health_events');\n\n const totalEvents = (countStmt.get() as { count: number }).count;\n const uniqueAgents = (agentStmt.get() as { count: number }).count;\n const oldestEvent = (oldestStmt.get() as { oldest: string | null }).oldest;\n const newestEvent = (newestStmt.get() as { newest: string | null }).newest;\n\n return {\n totalEvents,\n uniqueAgents,\n oldestEvent,\n newestEvent,\n };\n}\n","/**\n * Cloister Specialist Agents\n *\n * Manages long-running specialist agents that can be woken up on demand.\n * Specialists maintain context across invocations via session files.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'fs';\nimport { join, basename } from 'path';\nimport { execSync } from 'child_process';\nimport { PANOPTICON_HOME } from '../paths.js';\nimport { getAllSessionFiles, parseClaudeSession } from '../cost-parsers/jsonl-parser.js';\n\nconst SPECIALISTS_DIR = join(PANOPTICON_HOME, 'specialists');\nconst REGISTRY_FILE = join(SPECIALISTS_DIR, 'registry.json');\n\n/**\n * Supported specialist types\n */\nexport type SpecialistType = 'merge-agent' | 'review-agent' | 'test-agent';\n\n/**\n * Specialist state\n */\nexport type SpecialistState = 'sleeping' | 'active' | 'uninitialized';\n\n/**\n * Specialist metadata\n */\nexport interface SpecialistMetadata {\n name: SpecialistType;\n displayName: string;\n description: string;\n enabled: boolean;\n autoWake: boolean;\n sessionId?: string;\n lastWake?: string; // ISO 8601 timestamp\n contextTokens?: number;\n}\n\n/**\n * Specialist status including runtime state\n */\nexport interface SpecialistStatus extends SpecialistMetadata {\n state: SpecialistState;\n isRunning: boolean;\n tmuxSession?: string;\n}\n\n/**\n * Registry of all specialist agents\n */\nexport interface SpecialistRegistry {\n version: string;\n specialists: SpecialistMetadata[];\n lastUpdated: string; // ISO 8601 timestamp\n}\n\n/**\n * Default specialist definitions\n */\nconst DEFAULT_SPECIALISTS: SpecialistMetadata[] = [\n {\n name: 'merge-agent',\n displayName: 'Merge Agent',\n description: 'PR merging and conflict resolution',\n enabled: true,\n autoWake: true,\n },\n {\n name: 'review-agent',\n displayName: 'Review Agent',\n description: 'Code review and quality checks',\n enabled: true,\n autoWake: true,\n },\n {\n name: 'test-agent',\n displayName: 'Test Agent',\n description: 'Test execution and analysis',\n enabled: false,\n autoWake: false,\n },\n];\n\n/**\n * Initialize specialists directory and registry\n *\n * Creates directory structure and default registry.json if needed.\n * Safe to call multiple times - idempotent.\n */\nexport function initSpecialistsDirectory(): void {\n // Ensure specialists directory exists\n if (!existsSync(SPECIALISTS_DIR)) {\n mkdirSync(SPECIALISTS_DIR, { recursive: true });\n }\n\n // Create default registry if it doesn't exist\n if (!existsSync(REGISTRY_FILE)) {\n const registry: SpecialistRegistry = {\n version: '1.0',\n specialists: DEFAULT_SPECIALISTS,\n lastUpdated: new Date().toISOString(),\n };\n saveRegistry(registry);\n }\n}\n\n/**\n * Load the specialist registry\n *\n * @returns Specialist registry\n */\nexport function loadRegistry(): SpecialistRegistry {\n initSpecialistsDirectory();\n\n try {\n const content = readFileSync(REGISTRY_FILE, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n console.error('Failed to load specialist registry:', error);\n // Return default registry\n return {\n version: '1.0',\n specialists: DEFAULT_SPECIALISTS,\n lastUpdated: new Date().toISOString(),\n };\n }\n}\n\n/**\n * Save the specialist registry\n *\n * @param registry - Registry to save\n */\nexport function saveRegistry(registry: SpecialistRegistry): void {\n // Only ensure directory exists, don't call initSpecialistsDirectory to avoid recursion\n if (!existsSync(SPECIALISTS_DIR)) {\n mkdirSync(SPECIALISTS_DIR, { recursive: true });\n }\n\n registry.lastUpdated = new Date().toISOString();\n\n try {\n const content = JSON.stringify(registry, null, 2);\n writeFileSync(REGISTRY_FILE, content, 'utf-8');\n } catch (error) {\n console.error('Failed to save specialist registry:', error);\n throw error;\n }\n}\n\n/**\n * Get session file path for a specialist\n *\n * @param name - Specialist name\n * @returns Path to session file\n */\nexport function getSessionFilePath(name: SpecialistType): string {\n return join(SPECIALISTS_DIR, `${name}.session`);\n}\n\n/**\n * Read session ID from file\n *\n * @param name - Specialist name\n * @returns Session ID or null if not found\n */\nexport function getSessionId(name: SpecialistType): string | null {\n const sessionFile = getSessionFilePath(name);\n\n if (!existsSync(sessionFile)) {\n return null;\n }\n\n try {\n return readFileSync(sessionFile, 'utf-8').trim();\n } catch (error) {\n console.error(`Failed to read session file for ${name}:`, error);\n return null;\n }\n}\n\n/**\n * Write session ID to file\n *\n * @param name - Specialist name\n * @param sessionId - Session ID to store\n */\nexport function setSessionId(name: SpecialistType, sessionId: string): void {\n initSpecialistsDirectory();\n\n const sessionFile = getSessionFilePath(name);\n\n try {\n writeFileSync(sessionFile, sessionId.trim(), 'utf-8');\n } catch (error) {\n console.error(`Failed to write session file for ${name}:`, error);\n throw error;\n }\n}\n\n/**\n * Delete session file\n *\n * @param name - Specialist name\n * @returns True if file was deleted, false if it didn't exist\n */\nexport function clearSessionId(name: SpecialistType): boolean {\n const sessionFile = getSessionFilePath(name);\n\n if (!existsSync(sessionFile)) {\n return false;\n }\n\n try {\n unlinkSync(sessionFile);\n return true;\n } catch (error) {\n console.error(`Failed to delete session file for ${name}:`, error);\n throw error;\n }\n}\n\n/**\n * Get metadata for a specific specialist\n *\n * @param name - Specialist name\n * @returns Specialist metadata or null if not found\n */\nexport function getSpecialistMetadata(name: SpecialistType): SpecialistMetadata | null {\n const registry = loadRegistry();\n return registry.specialists.find((s) => s.name === name) || null;\n}\n\n/**\n * Update specialist metadata\n *\n * @param name - Specialist name\n * @param updates - Partial metadata to update\n */\nexport function updateSpecialistMetadata(\n name: SpecialistType,\n updates: Partial<SpecialistMetadata>\n): void {\n const registry = loadRegistry();\n\n const index = registry.specialists.findIndex((s) => s.name === name);\n\n if (index === -1) {\n throw new Error(`Specialist ${name} not found in registry`);\n }\n\n registry.specialists[index] = {\n ...registry.specialists[index],\n ...updates,\n name, // Ensure name doesn't change\n };\n\n saveRegistry(registry);\n}\n\n/**\n * Get all specialist metadata\n *\n * @returns Array of all specialists\n */\nexport function getAllSpecialists(): SpecialistMetadata[] {\n const registry = loadRegistry();\n return registry.specialists;\n}\n\n/**\n * Check if a specialist is initialized (has session file)\n *\n * @param name - Specialist name\n * @returns True if specialist has a session file\n */\nexport function isInitialized(name: SpecialistType): boolean {\n return getSessionId(name) !== null;\n}\n\n/**\n * Get the state of a specialist based on session file\n *\n * Note: This only checks if session exists, not if it's actually running.\n * Use getSpecialistStatus() for runtime state.\n *\n * @param name - Specialist name\n * @returns Specialist state\n */\nexport function getSpecialistState(name: SpecialistType): Exclude<SpecialistState, 'active'> {\n return isInitialized(name) ? 'sleeping' : 'uninitialized';\n}\n\n/**\n * Get tmux session name for a specialist\n *\n * @param name - Specialist name\n * @returns Expected tmux session name\n */\nexport function getTmuxSessionName(name: SpecialistType): string {\n return `specialist-${name}`;\n}\n\n/**\n * Record wake event in metadata\n *\n * @param name - Specialist name\n * @param sessionId - New session ID (if changed)\n */\nexport function recordWake(name: SpecialistType, sessionId?: string): void {\n const updates: Partial<SpecialistMetadata> = {\n lastWake: new Date().toISOString(),\n };\n\n if (sessionId) {\n updates.sessionId = sessionId;\n }\n\n updateSpecialistMetadata(name, updates);\n}\n\n/**\n * Update context token count for a specialist\n *\n * @param name - Specialist name\n * @param tokens - Total context tokens\n */\nexport function updateContextTokens(name: SpecialistType, tokens: number): void {\n updateSpecialistMetadata(name, { contextTokens: tokens });\n}\n\n/**\n * List all session files in the specialists directory\n *\n * @returns Array of specialist names that have session files\n */\nexport function listSessionFiles(): SpecialistType[] {\n initSpecialistsDirectory();\n\n try {\n const files = readdirSync(SPECIALISTS_DIR);\n const sessionFiles = files.filter((f) => f.endsWith('.session'));\n\n return sessionFiles.map((f) => f.replace('.session', '') as SpecialistType);\n } catch (error) {\n console.error('Failed to list session files:', error);\n return [];\n }\n}\n\n/**\n * Enable a specialist\n *\n * @param name - Specialist name\n */\nexport function enableSpecialist(name: SpecialistType): void {\n updateSpecialistMetadata(name, { enabled: true });\n}\n\n/**\n * Disable a specialist\n *\n * @param name - Specialist name\n */\nexport function disableSpecialist(name: SpecialistType): void {\n updateSpecialistMetadata(name, { enabled: false });\n}\n\n/**\n * Check if a specialist is enabled\n *\n * @param name - Specialist name\n * @returns True if specialist is enabled\n */\nexport function isEnabled(name: SpecialistType): boolean {\n const metadata = getSpecialistMetadata(name);\n return metadata?.enabled ?? false;\n}\n\n/**\n * Get all enabled specialists\n *\n * @returns Array of enabled specialists\n */\nexport function getEnabledSpecialists(): SpecialistMetadata[] {\n return getAllSpecialists().filter((s) => s.enabled);\n}\n\n/**\n * Find JSONL file for a session ID\n *\n * Searches through Claude Code project directories to find the JSONL file.\n *\n * @param sessionId - Session ID to find\n * @returns Path to JSONL file or null if not found\n */\nexport function findSessionFile(sessionId: string): string | null {\n try {\n const allFiles = getAllSessionFiles();\n\n for (const file of allFiles) {\n const fileSessionId = basename(file, '.jsonl');\n if (fileSessionId === sessionId) {\n return file;\n }\n }\n } catch {\n // Session files not available\n }\n\n return null;\n}\n\n/**\n * Count context tokens for a specialist session\n *\n * Reads the JSONL file for the specialist's session and sums all token usage.\n * This gives an approximate count of context size.\n *\n * @param name - Specialist name\n * @returns Total token count or null if session not found\n */\nexport function countContextTokens(name: SpecialistType): number | null {\n const sessionId = getSessionId(name);\n\n if (!sessionId) {\n return null;\n }\n\n const sessionFile = findSessionFile(sessionId);\n\n if (!sessionFile) {\n return null;\n }\n\n const sessionUsage = parseClaudeSession(sessionFile);\n\n if (!sessionUsage) {\n return null;\n }\n\n // Sum all token types for total context\n return (\n sessionUsage.usage.inputTokens +\n sessionUsage.usage.outputTokens +\n (sessionUsage.usage.cacheReadTokens || 0) +\n (sessionUsage.usage.cacheWriteTokens || 0)\n );\n}\n\n/**\n * Check if a specialist is currently running in tmux\n *\n * @param name - Specialist name\n * @returns True if specialist has an active tmux session\n */\nexport function isRunning(name: SpecialistType): boolean {\n const tmuxSession = getTmuxSessionName(name);\n\n try {\n execSync(`tmux has-session -t ${tmuxSession}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get complete status for a specialist\n *\n * Combines metadata, session info, and runtime state.\n *\n * @param name - Specialist name\n * @returns Complete specialist status\n */\nexport function getSpecialistStatus(name: SpecialistType): SpecialistStatus {\n const metadata = getSpecialistMetadata(name) || {\n name,\n displayName: name,\n description: '',\n enabled: false,\n autoWake: false,\n };\n\n const sessionId = getSessionId(name);\n const running = isRunning(name);\n const contextTokens = countContextTokens(name);\n\n // Determine state\n let state: SpecialistState;\n if (running) {\n state = 'active';\n } else if (sessionId) {\n state = 'sleeping';\n } else {\n state = 'uninitialized';\n }\n\n return {\n ...metadata,\n sessionId: sessionId || undefined,\n contextTokens: contextTokens || undefined,\n state,\n isRunning: running,\n tmuxSession: getTmuxSessionName(name),\n };\n}\n\n/**\n * Get status for all specialists\n *\n * @returns Array of specialist statuses\n */\nexport function getAllSpecialistStatus(): SpecialistStatus[] {\n return getAllSpecialists().map((metadata) => getSpecialistStatus(metadata.name));\n}\n\n/**\n * Initialize a specialist agent\n *\n * Creates a tmux session and starts Claude Code with an identity prompt.\n * This is for first-time initialization of specialists that don't have session files.\n *\n * @param name - Specialist name\n * @returns Promise with initialization result\n */\nexport async function initializeSpecialist(name: SpecialistType): Promise<{\n success: boolean;\n message: string;\n tmuxSession?: string;\n error?: string;\n}> {\n // Check if already running\n if (isRunning(name)) {\n return {\n success: false,\n message: `Specialist ${name} is already running`,\n error: 'already_running',\n };\n }\n\n // Check if already initialized\n if (getSessionId(name)) {\n return {\n success: false,\n message: `Specialist ${name} is already initialized. Use wake to start it.`,\n error: 'already_initialized',\n };\n }\n\n const tmuxSession = getTmuxSessionName(name);\n const cwd = process.env.HOME || '/home/eltmon';\n\n // Create identity prompt for the specialist\n const identityPrompt = `You are the ${name} specialist agent for Panopticon.\nYour role: ${name === 'merge-agent' ? 'Resolve merge conflicts and ensure clean integrations' :\n name === 'review-agent' ? 'Review code changes and provide quality feedback' :\n name === 'test-agent' ? 'Execute and analyze test results' : 'Assist with development tasks'}\n\nYou will be woken up when your services are needed. For now, acknowledge your initialization and wait.\nSay: \"I am the ${name} specialist, ready and waiting for tasks.\"`;\n\n try {\n // Spawn Claude Code fresh in tmux\n execSync(\n `tmux new-session -d -s \"${tmuxSession}\" -c \"${cwd}\" \"claude --dangerously-skip-permissions\"`,\n { encoding: 'utf-8' }\n );\n\n // Wait for Claude to start, then send identity prompt\n await new Promise(resolve => setTimeout(resolve, 3000));\n\n const escapedPrompt = identityPrompt.replace(/'/g, \"'\\\\''\");\n // Send text and Enter SEPARATELY to avoid Enter being interpreted as newline\n execSync(`tmux send-keys -t \"${tmuxSession}\" '${escapedPrompt}'`, { encoding: 'utf-8' });\n await new Promise(resolve => setTimeout(resolve, 500));\n execSync(`tmux send-keys -t \"${tmuxSession}\" C-m`, { encoding: 'utf-8' });\n\n // Record wake event\n recordWake(name);\n\n return {\n success: true,\n message: `Specialist ${name} initialized and started`,\n tmuxSession,\n };\n } catch (error: any) {\n return {\n success: false,\n message: `Failed to initialize specialist ${name}: ${error.message}`,\n error: error.message,\n };\n }\n}\n\n/**\n * Initialize all enabled but uninitialized specialists\n *\n * Called during Cloister startup to ensure specialists are ready.\n *\n * @returns Promise with array of initialization results\n */\nexport async function initializeEnabledSpecialists(): Promise<Array<{\n name: SpecialistType;\n success: boolean;\n message: string;\n}>> {\n const enabled = getEnabledSpecialists();\n const results: Array<{ name: SpecialistType; success: boolean; message: string }> = [];\n\n for (const specialist of enabled) {\n const sessionId = getSessionId(specialist.name);\n\n if (!sessionId) {\n // Specialist is enabled but not initialized\n console.log(` → Auto-initializing specialist: ${specialist.name}`);\n const result = await initializeSpecialist(specialist.name);\n results.push({\n name: specialist.name,\n success: result.success,\n message: result.message,\n });\n\n // Small delay between initializations to avoid overwhelming the system\n if (results.length < enabled.length) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n } else {\n results.push({\n name: specialist.name,\n success: true,\n message: `Already initialized with session ${sessionId.substring(0, 8)}...`,\n });\n }\n }\n\n return results;\n}\n","/**\n * Claude Code JSONL Parser\n *\n * Parse token usage from Claude Code session files.\n * Session files are stored at: ~/.claude/projects/<project-path-hash>/<session-id>.jsonl\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync } from 'fs';\nimport { join, basename } from 'path';\nimport { homedir } from 'os';\nimport { TokenUsage, calculateCost, getPricing, AIProvider, logCost, CostEntry } from '../cost.js';\n\n// Claude Code JSONL message format\nexport interface ClaudeMessage {\n sessionId?: string;\n timestamp?: string;\n parentMessageId?: string;\n message?: {\n id?: string;\n role?: 'user' | 'assistant';\n model?: string;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n };\n // Some messages have usage at top level\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n };\n model?: string;\n}\n\n// Parsed session usage\nexport interface SessionUsage {\n sessionId: string;\n sessionFile: string;\n startTime: string;\n endTime: string;\n model: string;\n usage: TokenUsage;\n cost: number;\n messageCount: number;\n}\n\n// Claude projects directory\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\n/**\n * Get all Claude Code project directories\n */\nexport function getProjectDirs(): string[] {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) {\n return [];\n }\n\n return readdirSync(CLAUDE_PROJECTS_DIR)\n .map(name => join(CLAUDE_PROJECTS_DIR, name))\n .filter(path => {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n });\n}\n\n/**\n * Get session JSONL files for a project directory\n */\nexport function getSessionFiles(projectDir: string): string[] {\n if (!existsSync(projectDir)) {\n return [];\n }\n\n return readdirSync(projectDir)\n .filter(name => name.endsWith('.jsonl'))\n .map(name => join(projectDir, name))\n .sort((a, b) => {\n try {\n return statSync(b).mtime.getTime() - statSync(a).mtime.getTime();\n } catch {\n return 0;\n }\n });\n}\n\n/**\n * Get all session files across all projects\n */\nexport function getAllSessionFiles(): string[] {\n const files: string[] = [];\n\n for (const projectDir of getProjectDirs()) {\n files.push(...getSessionFiles(projectDir));\n }\n\n return files.sort((a, b) => {\n try {\n return statSync(b).mtime.getTime() - statSync(a).mtime.getTime();\n } catch {\n return 0;\n }\n });\n}\n\n/**\n * Normalize model name for pricing lookup\n */\nfunction normalizeModelName(model: string): { provider: AIProvider; model: string } {\n // Claude models\n if (model.includes('claude')) {\n let normalizedModel = model;\n\n // Map full model IDs to pricing model names\n if (model.includes('opus-4-5') || model.includes('opus-4.5')) {\n normalizedModel = 'claude-opus-4';\n } else if (model.includes('opus-4') || model.includes('opus')) {\n normalizedModel = 'claude-opus-4';\n } else if (model.includes('sonnet-4') || model.includes('sonnet')) {\n normalizedModel = 'claude-sonnet-4';\n } else if (model.includes('haiku')) {\n normalizedModel = 'claude-haiku-3.5';\n }\n\n return { provider: 'anthropic', model: normalizedModel };\n }\n\n // OpenAI models\n if (model.includes('gpt')) {\n return { provider: 'openai', model };\n }\n\n // Google models\n if (model.includes('gemini')) {\n return { provider: 'google', model };\n }\n\n // Default to anthropic/claude\n return { provider: 'anthropic', model: 'claude-sonnet-4' };\n}\n\n/**\n * Parse a Claude Code session JSONL file and extract usage\n */\nexport function parseClaudeSession(sessionFile: string): SessionUsage | null {\n if (!existsSync(sessionFile)) {\n return null;\n }\n\n const content = readFileSync(sessionFile, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n\n let sessionId = '';\n let startTime = '';\n let endTime = '';\n let primaryModel = '';\n let messageCount = 0;\n\n const totalUsage: TokenUsage = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n\n for (const line of lines) {\n try {\n const msg: ClaudeMessage = JSON.parse(line);\n\n // Extract session ID from first message\n if (msg.sessionId && !sessionId) {\n sessionId = msg.sessionId;\n }\n\n // Track timestamps\n if (msg.timestamp) {\n if (!startTime || msg.timestamp < startTime) {\n startTime = msg.timestamp;\n }\n if (!endTime || msg.timestamp > endTime) {\n endTime = msg.timestamp;\n }\n }\n\n // Extract usage - can be in message.usage or top-level usage\n const usage = msg.message?.usage || msg.usage;\n const model = msg.message?.model || msg.model;\n\n if (usage) {\n totalUsage.inputTokens += usage.input_tokens || 0;\n totalUsage.outputTokens += usage.output_tokens || 0;\n totalUsage.cacheReadTokens = (totalUsage.cacheReadTokens || 0) + (usage.cache_read_input_tokens || 0);\n totalUsage.cacheWriteTokens = (totalUsage.cacheWriteTokens || 0) + (usage.cache_creation_input_tokens || 0);\n messageCount++;\n }\n\n // Track primary model (most frequently used)\n if (model && !primaryModel) {\n primaryModel = model;\n }\n } catch {\n // Skip invalid JSON lines\n }\n }\n\n // If no usage found, return null\n if (totalUsage.inputTokens === 0 && totalUsage.outputTokens === 0) {\n return null;\n }\n\n // Use filename as session ID if not found in messages\n if (!sessionId) {\n sessionId = basename(sessionFile, '.jsonl');\n }\n\n // Default model if not found\n if (!primaryModel) {\n primaryModel = 'claude-sonnet-4';\n }\n\n // Calculate cost\n const { provider, model } = normalizeModelName(primaryModel);\n const pricing = getPricing(provider, model);\n const cost = pricing ? calculateCost(totalUsage, pricing) : 0;\n\n return {\n sessionId,\n sessionFile,\n startTime: startTime || new Date().toISOString(),\n endTime: endTime || new Date().toISOString(),\n model: primaryModel,\n usage: totalUsage,\n cost,\n messageCount,\n };\n}\n\n/**\n * Parse all sessions and return usage summaries\n */\nexport function parseAllSessions(maxAge?: number): SessionUsage[] {\n const sessions: SessionUsage[] = [];\n const cutoffTime = maxAge ? Date.now() - maxAge : 0;\n\n for (const file of getAllSessionFiles()) {\n try {\n const stat = statSync(file);\n if (cutoffTime && stat.mtime.getTime() < cutoffTime) {\n continue;\n }\n\n const usage = parseClaudeSession(file);\n if (usage) {\n sessions.push(usage);\n }\n } catch {\n // Skip files that can't be read\n }\n }\n\n return sessions;\n}\n\n/**\n * Get recent sessions (last N days)\n */\nexport function getRecentSessions(days: number = 7): SessionUsage[] {\n const maxAge = days * 24 * 60 * 60 * 1000;\n return parseAllSessions(maxAge);\n}\n\n/**\n * Import session usage to cost log\n */\nexport function importSessionToCostLog(\n session: SessionUsage,\n options: {\n issueId?: string;\n agentId?: string;\n operation?: string;\n } = {}\n): CostEntry | null {\n const { provider, model } = normalizeModelName(session.model);\n const pricing = getPricing(provider, model);\n\n if (!pricing) {\n console.warn(`No pricing found for ${session.model}`);\n return null;\n }\n\n return logCost({\n provider,\n model,\n usage: session.usage,\n cost: session.cost,\n currency: 'USD',\n operation: options.operation || 'claude_session',\n issueId: options.issueId,\n agentId: options.agentId,\n metadata: {\n sessionId: session.sessionId,\n sessionFile: session.sessionFile,\n startTime: session.startTime,\n endTime: session.endTime,\n messageCount: session.messageCount,\n },\n });\n}\n","/**\n * Cost Tracking System\n *\n * Track AI usage costs per feature, issue, and project.\n * Supports multiple AI providers with configurable pricing.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { COSTS_DIR } from './paths.js';\n\n// ============== Types ==============\n\nexport type AIProvider = 'anthropic' | 'openai' | 'google' | 'custom';\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n}\n\nexport interface CostEntry {\n id: string;\n timestamp: string;\n provider: AIProvider;\n model: string;\n issueId?: string;\n featureId?: string;\n agentId?: string;\n operation: string;\n usage: TokenUsage;\n cost: number;\n currency: string;\n metadata?: Record<string, any>;\n}\n\nexport interface CostSummary {\n totalCost: number;\n currency: string;\n period: {\n start: string;\n end: string;\n };\n byProvider: Record<AIProvider, number>;\n byModel: Record<string, number>;\n byIssue: Record<string, number>;\n byFeature: Record<string, number>;\n entryCount: number;\n totalTokens: {\n input: number;\n output: number;\n total: number;\n };\n}\n\nexport interface CostBudget {\n id: string;\n name: string;\n type: 'issue' | 'feature' | 'project' | 'daily' | 'monthly';\n limit: number;\n currency: string;\n spent: number;\n alertThreshold: number; // e.g., 0.8 = alert at 80%\n enabled: boolean;\n}\n\nexport interface ModelPricing {\n provider: AIProvider;\n model: string;\n inputPer1k: number;\n outputPer1k: number;\n cacheReadPer1k?: number;\n cacheWritePer1k?: number;\n currency: string;\n}\n\n// ============== Pricing Data ==============\n\nexport const DEFAULT_PRICING: ModelPricing[] = [\n // Anthropic\n { provider: 'anthropic', model: 'claude-opus-4', inputPer1k: 0.015, outputPer1k: 0.075, cacheReadPer1k: 0.00175, cacheWritePer1k: 0.01875, currency: 'USD' },\n { provider: 'anthropic', model: 'claude-sonnet-4', inputPer1k: 0.003, outputPer1k: 0.015, cacheReadPer1k: 0.0003, cacheWritePer1k: 0.00375, currency: 'USD' },\n { provider: 'anthropic', model: 'claude-haiku-3.5', inputPer1k: 0.0008, outputPer1k: 0.004, cacheReadPer1k: 0.00008, cacheWritePer1k: 0.001, currency: 'USD' },\n // OpenAI\n { provider: 'openai', model: 'gpt-4-turbo', inputPer1k: 0.01, outputPer1k: 0.03, currency: 'USD' },\n { provider: 'openai', model: 'gpt-4o', inputPer1k: 0.005, outputPer1k: 0.015, currency: 'USD' },\n { provider: 'openai', model: 'gpt-4o-mini', inputPer1k: 0.00015, outputPer1k: 0.0006, currency: 'USD' },\n // Google\n { provider: 'google', model: 'gemini-1.5-pro', inputPer1k: 0.00125, outputPer1k: 0.005, currency: 'USD' },\n { provider: 'google', model: 'gemini-1.5-flash', inputPer1k: 0.000075, outputPer1k: 0.0003, currency: 'USD' },\n];\n\n// ============== Cost Calculation ==============\n\n/**\n * Calculate cost for token usage\n */\nexport function calculateCost(usage: TokenUsage, pricing: ModelPricing): number {\n let cost = 0;\n\n // Input tokens\n cost += (usage.inputTokens / 1000) * pricing.inputPer1k;\n\n // Output tokens\n cost += (usage.outputTokens / 1000) * pricing.outputPer1k;\n\n // Cache tokens (if applicable)\n if (usage.cacheReadTokens && pricing.cacheReadPer1k) {\n cost += (usage.cacheReadTokens / 1000) * pricing.cacheReadPer1k;\n }\n if (usage.cacheWriteTokens && pricing.cacheWritePer1k) {\n cost += (usage.cacheWriteTokens / 1000) * pricing.cacheWritePer1k;\n }\n\n return Math.round(cost * 1000000) / 1000000; // Round to 6 decimal places\n}\n\n/**\n * Get pricing for a model\n */\nexport function getPricing(provider: AIProvider, model: string): ModelPricing | null {\n // Try exact match first\n let pricing = DEFAULT_PRICING.find(\n p => p.provider === provider && p.model === model\n );\n\n if (!pricing) {\n // Try partial match (e.g., \"claude-sonnet-4-20250101\" matches \"claude-sonnet-4\")\n pricing = DEFAULT_PRICING.find(\n p => p.provider === provider && model.startsWith(p.model)\n );\n }\n\n return pricing || null;\n}\n\n// ============== Cost Logging ==============\n\nfunction getCostFile(date: string): string {\n return join(COSTS_DIR, `costs-${date}.jsonl`);\n}\n\nfunction getCurrentDateString(): string {\n return new Date().toISOString().split('T')[0];\n}\n\n/**\n * Log a cost entry\n */\nexport function logCost(entry: Omit<CostEntry, 'id' | 'timestamp'>): CostEntry {\n mkdirSync(COSTS_DIR, { recursive: true });\n\n const fullEntry: CostEntry = {\n ...entry,\n id: `cost-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n };\n\n const costFile = getCostFile(getCurrentDateString());\n appendFileSync(costFile, JSON.stringify(fullEntry) + '\\n');\n\n return fullEntry;\n}\n\n/**\n * Log cost from token usage\n */\nexport function logUsage(\n provider: AIProvider,\n model: string,\n usage: TokenUsage,\n options: {\n issueId?: string;\n featureId?: string;\n agentId?: string;\n operation?: string;\n metadata?: Record<string, any>;\n } = {}\n): CostEntry | null {\n const pricing = getPricing(provider, model);\n if (!pricing) {\n console.warn(`No pricing found for ${provider}/${model}`);\n return null;\n }\n\n const cost = calculateCost(usage, pricing);\n\n return logCost({\n provider,\n model,\n usage,\n cost,\n currency: pricing.currency,\n operation: options.operation || 'api_call',\n issueId: options.issueId,\n featureId: options.featureId,\n agentId: options.agentId,\n metadata: options.metadata,\n });\n}\n\n// ============== Cost Reading ==============\n\n/**\n * Read cost entries for a date range\n */\nexport function readCosts(startDate: string, endDate: string): CostEntry[] {\n const entries: CostEntry[] = [];\n\n const start = new Date(startDate);\n const end = new Date(endDate);\n\n for (let date = start; date <= end; date.setDate(date.getDate() + 1)) {\n const dateStr = date.toISOString().split('T')[0];\n const costFile = getCostFile(dateStr);\n\n if (existsSync(costFile)) {\n const content = readFileSync(costFile, 'utf-8');\n const lines = content.split('\\n').filter(line => line.trim());\n\n for (const line of lines) {\n try {\n entries.push(JSON.parse(line));\n } catch {\n // Skip invalid entries\n }\n }\n }\n }\n\n return entries;\n}\n\n/**\n * Read costs for today\n */\nexport function readTodayCosts(): CostEntry[] {\n const today = getCurrentDateString();\n return readCosts(today, today);\n}\n\n/**\n * Read costs for an issue\n */\nexport function readIssueCosts(issueId: string, days: number = 30): CostEntry[] {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - days);\n\n const allCosts = readCosts(\n start.toISOString().split('T')[0],\n end.toISOString().split('T')[0]\n );\n\n return allCosts.filter(entry => entry.issueId === issueId);\n}\n\n// ============== Cost Aggregation ==============\n\n/**\n * Calculate cost summary for a set of entries\n */\nexport function summarizeCosts(entries: CostEntry[]): CostSummary {\n const summary: CostSummary = {\n totalCost: 0,\n currency: 'USD',\n period: {\n start: entries[0]?.timestamp || new Date().toISOString(),\n end: entries[entries.length - 1]?.timestamp || new Date().toISOString(),\n },\n byProvider: {} as Record<AIProvider, number>,\n byModel: {},\n byIssue: {},\n byFeature: {},\n entryCount: entries.length,\n totalTokens: {\n input: 0,\n output: 0,\n total: 0,\n },\n };\n\n for (const entry of entries) {\n summary.totalCost += entry.cost;\n\n // By provider\n summary.byProvider[entry.provider] =\n (summary.byProvider[entry.provider] || 0) + entry.cost;\n\n // By model\n summary.byModel[entry.model] =\n (summary.byModel[entry.model] || 0) + entry.cost;\n\n // By issue\n if (entry.issueId) {\n summary.byIssue[entry.issueId] =\n (summary.byIssue[entry.issueId] || 0) + entry.cost;\n }\n\n // By feature\n if (entry.featureId) {\n summary.byFeature[entry.featureId] =\n (summary.byFeature[entry.featureId] || 0) + entry.cost;\n }\n\n // Tokens\n summary.totalTokens.input += entry.usage.inputTokens;\n summary.totalTokens.output += entry.usage.outputTokens;\n }\n\n summary.totalTokens.total = summary.totalTokens.input + summary.totalTokens.output;\n summary.totalCost = Math.round(summary.totalCost * 100) / 100;\n\n return summary;\n}\n\n/**\n * Get daily cost summary\n */\nexport function getDailySummary(date?: string): CostSummary {\n const targetDate = date || getCurrentDateString();\n const entries = readCosts(targetDate, targetDate);\n return summarizeCosts(entries);\n}\n\n/**\n * Get weekly cost summary\n */\nexport function getWeeklySummary(): CostSummary {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n\n const entries = readCosts(\n start.toISOString().split('T')[0],\n end.toISOString().split('T')[0]\n );\n\n return summarizeCosts(entries);\n}\n\n/**\n * Get monthly cost summary\n */\nexport function getMonthlySummary(): CostSummary {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 30);\n\n const entries = readCosts(\n start.toISOString().split('T')[0],\n end.toISOString().split('T')[0]\n );\n\n return summarizeCosts(entries);\n}\n\n// ============== Cost Budgets ==============\n\nconst BUDGETS_FILE = join(COSTS_DIR, 'budgets.json');\n\nfunction loadBudgets(): CostBudget[] {\n if (!existsSync(BUDGETS_FILE)) {\n return [];\n }\n\n try {\n const content = readFileSync(BUDGETS_FILE, 'utf-8');\n return JSON.parse(content);\n } catch {\n return [];\n }\n}\n\nfunction saveBudgets(budgets: CostBudget[]): void {\n mkdirSync(COSTS_DIR, { recursive: true });\n writeFileSync(BUDGETS_FILE, JSON.stringify(budgets, null, 2));\n}\n\n/**\n * Create a cost budget\n */\nexport function createBudget(budget: Omit<CostBudget, 'id' | 'spent'>): CostBudget {\n const budgets = loadBudgets();\n\n const newBudget: CostBudget = {\n ...budget,\n id: `budget-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n spent: 0,\n };\n\n budgets.push(newBudget);\n saveBudgets(budgets);\n\n return newBudget;\n}\n\n/**\n * Get a budget by ID\n */\nexport function getBudget(id: string): CostBudget | null {\n const budgets = loadBudgets();\n return budgets.find(b => b.id === id) || null;\n}\n\n/**\n * Get all budgets\n */\nexport function getAllBudgets(): CostBudget[] {\n return loadBudgets();\n}\n\n/**\n * Update budget spent amount\n */\nexport function updateBudgetSpent(id: string, spent: number): boolean {\n const budgets = loadBudgets();\n const budget = budgets.find(b => b.id === id);\n\n if (!budget) return false;\n\n budget.spent = spent;\n saveBudgets(budgets);\n\n return true;\n}\n\n/**\n * Check budget status\n */\nexport function checkBudget(id: string): {\n budget: CostBudget | null;\n remaining: number;\n percentUsed: number;\n exceeded: boolean;\n alert: boolean;\n} {\n const budget = getBudget(id);\n\n if (!budget) {\n return {\n budget: null,\n remaining: 0,\n percentUsed: 0,\n exceeded: false,\n alert: false,\n };\n }\n\n const remaining = budget.limit - budget.spent;\n const percentUsed = budget.spent / budget.limit;\n\n return {\n budget,\n remaining,\n percentUsed,\n exceeded: percentUsed >= 1,\n alert: percentUsed >= budget.alertThreshold,\n };\n}\n\n/**\n * Delete a budget\n */\nexport function deleteBudget(id: string): boolean {\n const budgets = loadBudgets();\n const index = budgets.findIndex(b => b.id === id);\n\n if (index === -1) return false;\n\n budgets.splice(index, 1);\n saveBudgets(budgets);\n\n return true;\n}\n\n// ============== Reports ==============\n\n/**\n * Generate a cost report\n */\nexport function generateReport(startDate: string, endDate: string): string {\n const entries = readCosts(startDate, endDate);\n const summary = summarizeCosts(entries);\n\n const lines: string[] = [\n '# Cost Report',\n '',\n `**Period:** ${startDate} to ${endDate}`,\n '',\n '## Summary',\n '',\n `- **Total Cost:** $${summary.totalCost.toFixed(2)}`,\n `- **Total Entries:** ${summary.entryCount}`,\n `- **Total Tokens:** ${summary.totalTokens.total.toLocaleString()}`,\n ` - Input: ${summary.totalTokens.input.toLocaleString()}`,\n ` - Output: ${summary.totalTokens.output.toLocaleString()}`,\n '',\n '## By Provider',\n '',\n ];\n\n for (const [provider, cost] of Object.entries(summary.byProvider)) {\n lines.push(`- **${provider}:** $${cost.toFixed(2)}`);\n }\n\n lines.push('');\n lines.push('## By Model');\n lines.push('');\n\n for (const [model, cost] of Object.entries(summary.byModel)) {\n lines.push(`- **${model}:** $${cost.toFixed(2)}`);\n }\n\n if (Object.keys(summary.byIssue).length > 0) {\n lines.push('');\n lines.push('## By Issue');\n lines.push('');\n\n const sortedIssues = Object.entries(summary.byIssue)\n .sort(([, a], [, b]) => b - a);\n\n for (const [issue, cost] of sortedIssues.slice(0, 10)) {\n lines.push(`- **${issue}:** $${cost.toFixed(2)}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Format cost for display\n */\nexport function formatCost(cost: number, currency: string = 'USD'): string {\n if (currency === 'USD') {\n return `$${cost.toFixed(4)}`;\n }\n return `${cost.toFixed(4)} ${currency}`;\n}\n","/**\n * Claude Code Runtime Implementation\n *\n * Implements AgentRuntime for Claude Code CLI.\n *\n * Session storage: ~/.claude/projects/<workspace-hash>/<session-id>.jsonl\n * Session index: ~/.claude/projects/<workspace-hash>/sessions-index.json\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync, mkdirSync, writeFileSync } from 'fs';\nimport { join, basename } from 'path';\nimport { homedir } from 'os';\nimport type {\n AgentRuntime,\n Heartbeat,\n TokenUsage,\n CostBreakdown,\n Session,\n SpawnConfig,\n Agent,\n ActivitySource,\n} from './types.js';\nimport { getAgentState, getAgentDir, spawnAgent as spawnAgentImpl, saveAgentState } from '../agents.js';\nimport { sessionExists, killSession, sendKeys, getAgentSessions } from '../tmux.js';\nimport { parseClaudeSession, getSessionFiles, getProjectDirs } from '../cost-parsers/jsonl-parser.js';\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\n/**\n * Claude Code session index entry\n */\ninterface SessionIndexEntry {\n sessionId: string;\n createdAt: string;\n updatedAt: string;\n filePath: string;\n}\n\n/**\n * Claude Code Runtime implementation\n */\nexport class ClaudeCodeRuntime implements AgentRuntime {\n readonly name = 'claude-code' as const;\n\n /**\n * Get the project directory for a workspace\n *\n * Claude Code hashes the workspace path to create project directories.\n * We need to find the project directory that contains sessions for this workspace.\n */\n private getProjectDirForWorkspace(workspace: string): string | null {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) {\n return null;\n }\n\n // Get all project directories\n const projectDirs = getProjectDirs();\n\n for (const projectDir of projectDirs) {\n // Check if this project's sessions-index.json references the workspace\n const indexPath = join(projectDir, 'sessions-index.json');\n if (existsSync(indexPath)) {\n try {\n const indexContent = readFileSync(indexPath, 'utf-8');\n // Sessions index contains the workspace path\n if (indexContent.includes(workspace)) {\n return projectDir;\n }\n } catch {\n // Skip invalid index files\n }\n }\n }\n\n return null;\n }\n\n /**\n * Get the active session ID for an agent from the sessions index\n */\n private getActiveSessionId(projectDir: string): string | null {\n const indexPath = join(projectDir, 'sessions-index.json');\n if (!existsSync(indexPath)) {\n return null;\n }\n\n try {\n const indexContent = readFileSync(indexPath, 'utf-8');\n const index = JSON.parse(indexContent);\n\n // The sessions-index.json has a structure like:\n // { \"sessions\": [{ \"sessionId\": \"...\", \"filePath\": \"...\", ... }] }\n // Find the most recent session\n if (index.sessions && Array.isArray(index.sessions)) {\n const sessions = index.sessions as SessionIndexEntry[];\n if (sessions.length === 0) return null;\n\n // Sort by updatedAt and get the most recent\n const sorted = sessions.sort((a, b) => {\n return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();\n });\n\n return sorted[0].sessionId;\n }\n } catch {\n // Skip invalid index files\n }\n\n return null;\n }\n\n /**\n * Get the most recent JSONL file for a project\n */\n private getMostRecentJSONL(projectDir: string): string | null {\n const files = getSessionFiles(projectDir);\n return files.length > 0 ? files[0] : null;\n }\n\n /**\n * Get the session path for an agent\n */\n getSessionPath(agentId: string): string | null {\n const state = getAgentState(agentId);\n if (!state) {\n return null;\n }\n\n const projectDir = this.getProjectDirForWorkspace(state.workspace);\n if (!projectDir) {\n return null;\n }\n\n // Try to get active session from index\n const sessionId = this.getActiveSessionId(projectDir);\n if (sessionId) {\n const sessionPath = join(projectDir, `${sessionId}.jsonl`);\n if (existsSync(sessionPath)) {\n return sessionPath;\n }\n }\n\n // Fall back to most recent JSONL file\n return this.getMostRecentJSONL(projectDir);\n }\n\n /**\n * Get last activity timestamp for an agent\n *\n * Uses passive detection via JSONL file modification time.\n */\n getLastActivity(agentId: string): Date | null {\n const sessionPath = this.getSessionPath(agentId);\n if (!sessionPath || !existsSync(sessionPath)) {\n return null;\n }\n\n try {\n const stat = statSync(sessionPath);\n return stat.mtime;\n } catch {\n return null;\n }\n }\n\n /**\n * Read active heartbeat file if it exists\n */\n private getActiveHeartbeat(agentId: string): Heartbeat | null {\n // Heartbeats are now in shared directory: ~/.panopticon/heartbeats/\n const heartbeatPath = join(homedir(), '.panopticon', 'heartbeats', `${agentId}.json`);\n if (!existsSync(heartbeatPath)) {\n return null;\n }\n\n try {\n const content = readFileSync(heartbeatPath, 'utf-8');\n const data = JSON.parse(content);\n\n // Check if heartbeat is recent (within 5 minutes)\n const timestamp = new Date(data.timestamp);\n const now = new Date();\n const ageMs = now.getTime() - timestamp.getTime();\n if (ageMs > 5 * 60 * 1000) {\n // Heartbeat is stale\n return null;\n }\n\n return {\n timestamp,\n agentId: data.agent_id || agentId,\n source: 'active-heartbeat',\n confidence: 'high',\n toolName: data.tool_name,\n lastAction: data.last_action,\n currentTask: data.current_task,\n gitBranch: data.git_branch,\n workspace: data.workspace,\n pid: data.pid,\n sessionId: data.session_id,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Get passive heartbeat from file timestamps\n */\n private getPassiveHeartbeat(agentId: string): Heartbeat | null {\n const lastActivity = this.getLastActivity(agentId);\n if (!lastActivity) {\n return null;\n }\n\n return {\n timestamp: lastActivity,\n agentId,\n source: 'jsonl',\n confidence: 'medium',\n };\n }\n\n /**\n * Get heartbeat for an agent\n *\n * Tries active heartbeat first (if hooks configured), falls back to passive.\n */\n getHeartbeat(agentId: string): Heartbeat | null {\n // Try active heartbeat first\n const activeHeartbeat = this.getActiveHeartbeat(agentId);\n if (activeHeartbeat) {\n return activeHeartbeat;\n }\n\n // Fall back to passive detection\n return this.getPassiveHeartbeat(agentId);\n }\n\n /**\n * Get token usage for an agent's current session\n */\n getTokenUsage(agentId: string): TokenUsage | null {\n const sessionPath = this.getSessionPath(agentId);\n if (!sessionPath) {\n return null;\n }\n\n const sessionUsage = parseClaudeSession(sessionPath);\n if (!sessionUsage) {\n return null;\n }\n\n return sessionUsage.usage;\n }\n\n /**\n * Get cost breakdown for an agent's current session\n */\n getSessionCost(agentId: string): CostBreakdown | null {\n const sessionPath = this.getSessionPath(agentId);\n if (!sessionPath) {\n return null;\n }\n\n const sessionUsage = parseClaudeSession(sessionPath);\n if (!sessionUsage) {\n return null;\n }\n\n // Calculate breakdown based on token usage\n // Prices for Claude Sonnet 4 (most common)\n // TODO: Use actual model pricing from session\n const inputPrice = 3.0 / 1_000_000; // $3 per 1M input tokens\n const outputPrice = 15.0 / 1_000_000; // $15 per 1M output tokens\n const cacheReadPrice = 0.3 / 1_000_000; // $0.30 per 1M cache read tokens\n const cacheWritePrice = 3.75 / 1_000_000; // $3.75 per 1M cache write tokens\n\n const usage = sessionUsage.usage;\n const inputCost = usage.inputTokens * inputPrice;\n const outputCost = usage.outputTokens * outputPrice;\n const cacheReadCost = (usage.cacheReadTokens || 0) * cacheReadPrice;\n const cacheWriteCost = (usage.cacheWriteTokens || 0) * cacheWritePrice;\n\n return {\n inputCost,\n outputCost,\n cacheReadCost,\n cacheWriteCost,\n totalCost: inputCost + outputCost + cacheReadCost + cacheWriteCost,\n currency: 'USD',\n };\n }\n\n /**\n * Send a message to a running agent\n */\n sendMessage(agentId: string, message: string): void {\n if (!sessionExists(agentId)) {\n throw new Error(`Agent ${agentId} is not running`);\n }\n\n sendKeys(agentId, message);\n\n // Also save to mail queue for persistence\n const mailDir = join(getAgentDir(agentId), 'mail');\n mkdirSync(mailDir, { recursive: true });\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n writeFileSync(\n join(mailDir, `${timestamp}.md`),\n `# Message\\n\\n${message}\\n`\n );\n }\n\n /**\n * Kill an agent\n */\n killAgent(agentId: string): void {\n if (!sessionExists(agentId)) {\n throw new Error(`Agent ${agentId} is not running`);\n }\n\n killSession(agentId);\n\n // Update agent state\n const state = getAgentState(agentId);\n if (state) {\n state.status = 'stopped';\n saveAgentState(state);\n }\n }\n\n /**\n * Spawn a new agent\n */\n spawnAgent(config: SpawnConfig): Agent {\n // Use the existing spawnAgent implementation from agents.ts\n const state = spawnAgentImpl({\n issueId: config.agentId.replace(/^agent-/, ''),\n workspace: config.workspace,\n runtime: 'claude',\n model: config.model || 'sonnet',\n prompt: config.prompt,\n });\n\n // Get the session ID (we'll need to look it up from the workspace)\n const projectDir = this.getProjectDirForWorkspace(config.workspace);\n const sessionId = projectDir ? this.getActiveSessionId(projectDir) : undefined;\n\n return {\n id: state.id,\n sessionId: sessionId || 'unknown',\n runtime: 'claude-code',\n model: state.model,\n workspace: state.workspace,\n startedAt: new Date(state.startedAt),\n };\n }\n\n /**\n * List all sessions for this runtime\n */\n listSessions(workspace?: string): Session[] {\n const sessions: Session[] = [];\n\n if (workspace) {\n // Get sessions for specific workspace\n const projectDir = this.getProjectDirForWorkspace(workspace);\n if (projectDir) {\n const files = getSessionFiles(projectDir);\n for (const file of files) {\n const session = this.parseSessionFile(file, workspace);\n if (session) {\n sessions.push(session);\n }\n }\n }\n } else {\n // Get all sessions\n const projectDirs = getProjectDirs();\n for (const projectDir of projectDirs) {\n const files = getSessionFiles(projectDir);\n for (const file of files) {\n const session = this.parseSessionFile(file);\n if (session) {\n sessions.push(session);\n }\n }\n }\n }\n\n return sessions;\n }\n\n /**\n * Parse a session file into a Session object\n */\n private parseSessionFile(file: string, workspace?: string): Session | null {\n const sessionUsage = parseClaudeSession(file);\n if (!sessionUsage) {\n return null;\n }\n\n const stat = statSync(file);\n\n return {\n id: sessionUsage.sessionId,\n agentId: 'unknown', // We'd need to reverse-lookup from agent state\n workspace: workspace || 'unknown',\n model: sessionUsage.model,\n startedAt: new Date(sessionUsage.startTime),\n lastActivity: stat.mtime,\n tokenUsage: sessionUsage.usage,\n };\n }\n\n /**\n * Check if an agent is running\n */\n isRunning(agentId: string): boolean {\n return sessionExists(agentId);\n }\n}\n\n/**\n * Create a Claude Code runtime instance\n */\nexport function createClaudeCodeRuntime(): ClaudeCodeRuntime {\n return new ClaudeCodeRuntime();\n}\n","/**\n * Cloister Runtime Abstraction\n *\n * Export all runtime types and provide a unified registry for managing\n * multiple AI coding assistant runtimes.\n */\n\nexport * from './types.js';\nexport { ClaudeCodeRuntime, createClaudeCodeRuntime } from './claude-code.js';\n\nimport type {\n AgentRuntime,\n RuntimeName,\n RuntimeRegistry as RuntimeRegistryInterface,\n} from './types.js';\nimport { getAgentState } from '../agents.js';\nimport { createClaudeCodeRuntime } from './claude-code.js';\n\n/**\n * Runtime registry implementation\n *\n * Manages multiple runtime adapters and provides lookup by agent ID.\n */\nexport class RuntimeRegistry implements RuntimeRegistryInterface {\n private runtimes: Map<RuntimeName, AgentRuntime> = new Map();\n\n /**\n * Register a runtime adapter\n */\n register(runtime: AgentRuntime): void {\n this.runtimes.set(runtime.name, runtime);\n }\n\n /**\n * Get a runtime by name\n */\n get(name: RuntimeName): AgentRuntime | undefined {\n return this.runtimes.get(name);\n }\n\n /**\n * Get all registered runtimes\n */\n getAll(): AgentRuntime[] {\n return Array.from(this.runtimes.values());\n }\n\n /**\n * Get the runtime for a specific agent\n *\n * Looks up the agent's state file to determine which runtime it's using.\n */\n getRuntimeForAgent(agentId: string): AgentRuntime | null {\n const state = getAgentState(agentId);\n if (!state) {\n return null;\n }\n\n // Map the state.runtime to a RuntimeName\n // The state.runtime may be 'claude', 'opencode', etc.\n let runtimeName: RuntimeName;\n\n switch (state.runtime) {\n case 'claude':\n case 'claude-code':\n runtimeName = 'claude-code';\n break;\n case 'opencode':\n runtimeName = 'opencode';\n break;\n case 'codex':\n runtimeName = 'codex';\n break;\n default:\n // Default to claude-code if unknown\n runtimeName = 'claude-code';\n }\n\n return this.get(runtimeName) || null;\n }\n}\n\n/**\n * Global runtime registry instance\n */\nlet globalRegistry: RuntimeRegistry | null = null;\n\n/**\n * Get the global runtime registry\n *\n * Creates a new registry if one doesn't exist.\n * Registers Claude Code runtime by default.\n */\nexport function getGlobalRegistry(): RuntimeRegistry {\n if (!globalRegistry) {\n globalRegistry = new RuntimeRegistry();\n\n // Register Claude Code runtime by default\n globalRegistry.register(createClaudeCodeRuntime());\n\n // TODO: Register other runtimes (OpenCode, Codex) when implemented\n }\n return globalRegistry;\n}\n\n/**\n * Set the global runtime registry\n *\n * Useful for testing or custom configurations.\n */\nexport function setGlobalRegistry(registry: RuntimeRegistry): void {\n globalRegistry = registry;\n}\n\n/**\n * Helper to get a runtime by name from the global registry\n */\nexport function getRuntime(name: RuntimeName): AgentRuntime | undefined {\n return getGlobalRegistry().get(name);\n}\n\n/**\n * Helper to get the runtime for an agent from the global registry\n */\nexport function getRuntimeForAgent(agentId: string): AgentRuntime | null {\n return getGlobalRegistry().getRuntimeForAgent(agentId);\n}\n","/**\n * Handoff Triggers\n *\n * Detects conditions that should trigger model handoffs:\n * 1. Stuck escalation - Agent inactive for too long\n * 2. Planning complete - Planning phase finished, ready for implementation\n * 3. Test failure - Tests failing, need more powerful model\n * 4. Task completion - Implementation done, ready for specialist testing\n */\n\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport type { AgentHealth } from './health.js';\nimport type { CloisterConfig } from './config.js';\nimport { loadCloisterConfig } from './config.js';\n\n/**\n * Trigger type\n */\nexport type TriggerType =\n | 'stuck_escalation'\n | 'planning_complete'\n | 'test_failure'\n | 'task_complete'\n | 'manual';\n\n/**\n * Trigger detection result\n */\nexport interface TriggerDetection {\n triggered: boolean;\n type: TriggerType;\n reason: string;\n suggestedModel?: string;\n confidence: 'high' | 'medium' | 'low';\n}\n\n/**\n * Check if agent should be handed off due to stuck escalation\n *\n * Model-specific thresholds:\n * - Haiku: Stuck after 10 minutes → escalate to Sonnet\n * - Sonnet: Stuck after 20 minutes → escalate to Opus\n * - Opus: Stuck after 30 minutes → alert user (no auto-escalation)\n *\n * @param health - Agent health state\n * @param currentModel - Current model\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkStuckEscalation(\n health: AgentHealth,\n currentModel: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get stuck escalation config\n const stuckConfig = conf.handoffs?.auto_triggers?.stuck_escalation;\n if (!stuckConfig?.enabled) {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: 'Stuck escalation disabled in config',\n confidence: 'high',\n };\n }\n\n // Check if agent is stuck based on health state\n if (health.state !== 'stuck') {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: `Agent is ${health.state}, not stuck`,\n confidence: 'high',\n };\n }\n\n // Get minutes since last activity\n if (!health.lastActivity) {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: 'No last activity timestamp available',\n confidence: 'low',\n };\n }\n const minutesSinceActivity = (Date.now() - health.lastActivity.getTime()) / (1000 * 60);\n\n // Check model-specific thresholds\n if (currentModel === 'haiku' && minutesSinceActivity >= stuckConfig.haiku_to_sonnet_minutes) {\n return {\n triggered: true,\n type: 'stuck_escalation',\n reason: `Haiku agent stuck for ${Math.round(minutesSinceActivity)} minutes`,\n suggestedModel: 'sonnet',\n confidence: 'high',\n };\n }\n\n if (currentModel === 'sonnet' && minutesSinceActivity >= stuckConfig.sonnet_to_opus_minutes) {\n return {\n triggered: true,\n type: 'stuck_escalation',\n reason: `Sonnet agent stuck for ${Math.round(minutesSinceActivity)} minutes`,\n suggestedModel: 'opus',\n confidence: 'high',\n };\n }\n\n if (currentModel === 'opus') {\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: 'Opus agent stuck - no higher model available, manual intervention needed',\n confidence: 'high',\n };\n }\n\n return {\n triggered: false,\n type: 'stuck_escalation',\n reason: `Agent stuck but threshold not reached (${Math.round(minutesSinceActivity)} minutes)`,\n confidence: 'medium',\n };\n}\n\n/**\n * Check if planning phase is complete\n *\n * Multi-signal detection:\n * 1. Primary: Beads task with \"plan\" in title is closed\n * 2. Secondary: PRD file created at docs/prds/active/{issue}-plan.md\n * 3. Tertiary: Agent used ExitPlanMode tool (if detectable)\n *\n * @param agentId - Agent ID\n * @param workspace - Workspace path\n * @param issueId - Issue ID\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkPlanningComplete(\n agentId: string,\n workspace: string,\n issueId: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get planning complete config\n const planningConfig = conf.handoffs?.auto_triggers?.planning_complete;\n if (!planningConfig?.enabled) {\n return {\n triggered: false,\n type: 'planning_complete',\n reason: 'Planning complete detection disabled in config',\n confidence: 'high',\n };\n }\n\n const signals: string[] = [];\n let signalCount = 0;\n\n // Signal 1: Check for closed beads task with \"plan\" in title\n try {\n const output = execSync(`bd list --json -l ${issueId.toLowerCase()} --status closed`, {\n encoding: 'utf-8',\n });\n const tasks = JSON.parse(output);\n const planTask = tasks.find((t: any) =>\n t.title.toLowerCase().includes('plan') ||\n t.labels?.includes('planning')\n );\n if (planTask) {\n signals.push(`Beads planning task closed: ${planTask.id}`);\n signalCount++;\n }\n } catch (error) {\n // Beads not available or error querying\n }\n\n // Signal 2: Check for PRD file\n const prdPath = join(workspace, `docs/prds/active/${issueId.toLowerCase()}-plan.md`);\n if (existsSync(prdPath)) {\n signals.push('PRD file exists');\n signalCount++;\n }\n\n // Signal 3: Check for ExitPlanMode usage (TODO: requires hook integration)\n // This would require reading the session JSONL and checking for ExitPlanMode tool use\n // Skipping for now\n\n // Trigger if we have at least 2 signals\n if (signalCount >= 2) {\n return {\n triggered: true,\n type: 'planning_complete',\n reason: `Planning complete detected: ${signals.join(', ')}`,\n suggestedModel: planningConfig.to_model,\n confidence: 'high',\n };\n }\n\n if (signalCount === 1) {\n return {\n triggered: false,\n type: 'planning_complete',\n reason: `Planning possibly complete (${signals.join(', ')}) but need more signals`,\n confidence: 'medium',\n };\n }\n\n return {\n triggered: false,\n type: 'planning_complete',\n reason: 'No planning completion signals detected',\n confidence: 'high',\n };\n}\n\n/**\n * Check if test failures should trigger escalation\n *\n * Aggressive escalation: Any test failure from Haiku escalates to Sonnet\n * Reasoning: Haiku is for simple tasks - if tests fail, the task isn't simple\n *\n * @param workspace - Workspace path\n * @param currentModel - Current model\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkTestFailure(\n workspace: string,\n currentModel: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get test failure config\n const testConfig = conf.handoffs?.auto_triggers?.test_failure;\n if (!testConfig?.enabled) {\n return {\n triggered: false,\n type: 'test_failure',\n reason: 'Test failure escalation disabled in config',\n confidence: 'high',\n };\n }\n\n // Only escalate from Haiku or configured from_model\n if (currentModel !== testConfig.from_model) {\n return {\n triggered: false,\n type: 'test_failure',\n reason: `Test failure escalation only applies to ${testConfig.from_model} model`,\n confidence: 'high',\n };\n }\n\n // Check for test failures\n // Look for common test result files/patterns\n const testFailure = detectTestFailure(workspace);\n\n if (testFailure.failed) {\n return {\n triggered: true,\n type: 'test_failure',\n reason: `Test failures detected: ${testFailure.reason}`,\n suggestedModel: testConfig.to_model,\n confidence: testFailure.confidence,\n };\n }\n\n return {\n triggered: false,\n type: 'test_failure',\n reason: 'No test failures detected',\n confidence: 'medium',\n };\n}\n\n/**\n * Detect test failures in workspace\n *\n * Checks for:\n * - npm test output\n * - Jest results\n * - pytest results\n * - cargo test results\n *\n * @param workspace - Workspace path\n * @returns Test failure detection\n */\nfunction detectTestFailure(workspace: string): {\n failed: boolean;\n reason: string;\n confidence: 'high' | 'medium' | 'low';\n} {\n // TODO: Implement proper test result detection\n // For now, this is a placeholder that checks for common test result files\n\n // Check for .test-results or similar\n const commonTestPaths = [\n '.test-results',\n 'test-results',\n 'junit.xml',\n 'coverage',\n '.nyc_output',\n ];\n\n // This is a simplified check - in reality we'd parse test output\n return {\n failed: false,\n reason: 'Test result detection not yet implemented',\n confidence: 'low',\n };\n}\n\n/**\n * Check if implementation is complete and ready for testing\n *\n * Detection:\n * - Beads task with \"implement\" in title is closed\n * - No remaining implementation tasks\n *\n * @param issueId - Issue ID\n * @param config - Cloister configuration\n * @returns Trigger detection result\n */\nexport function checkTaskCompletion(\n issueId: string,\n config?: CloisterConfig\n): TriggerDetection {\n const conf = config || loadCloisterConfig();\n\n // Get task completion config\n const completionConfig = conf.handoffs?.auto_triggers?.implementation_complete;\n if (!completionConfig?.enabled) {\n return {\n triggered: false,\n type: 'task_complete',\n reason: 'Task completion detection disabled in config',\n confidence: 'high',\n };\n }\n\n // Check for closed implementation task\n try {\n const output = execSync(`bd list --json -l ${issueId.toLowerCase()} --status closed`, {\n encoding: 'utf-8',\n });\n const tasks = JSON.parse(output);\n const implementTask = tasks.find((t: any) =>\n t.title.toLowerCase().includes('implement') ||\n t.labels?.includes('implementation')\n );\n\n if (implementTask) {\n // Check if there are remaining open tasks\n const openOutput = execSync(`bd list --json -l ${issueId.toLowerCase()} --status open`, {\n encoding: 'utf-8',\n });\n const openTasks = JSON.parse(openOutput);\n\n if (openTasks.length === 0) {\n return {\n triggered: true,\n type: 'task_complete',\n reason: 'Implementation task closed, no remaining tasks',\n suggestedModel: completionConfig.to_specialist,\n confidence: 'high',\n };\n } else {\n return {\n triggered: false,\n type: 'task_complete',\n reason: `Implementation task closed but ${openTasks.length} tasks remain`,\n confidence: 'medium',\n };\n }\n }\n } catch (error) {\n // Beads not available or error querying\n }\n\n return {\n triggered: false,\n type: 'task_complete',\n reason: 'No implementation completion signals detected',\n confidence: 'high',\n };\n}\n\n/**\n * Check all triggers for an agent\n *\n * @param agentId - Agent ID\n * @param workspace - Workspace path\n * @param issueId - Issue ID\n * @param currentModel - Current model\n * @param health - Agent health state\n * @param config - Cloister configuration\n * @returns Array of triggered detections\n */\nexport function checkAllTriggers(\n agentId: string,\n workspace: string,\n issueId: string,\n currentModel: string,\n health: AgentHealth,\n config?: CloisterConfig\n): TriggerDetection[] {\n const triggers: TriggerDetection[] = [];\n\n // Check each trigger type\n const stuckCheck = checkStuckEscalation(health, currentModel, config);\n if (stuckCheck.triggered) triggers.push(stuckCheck);\n\n const planningCheck = checkPlanningComplete(agentId, workspace, issueId, config);\n if (planningCheck.triggered) triggers.push(planningCheck);\n\n const testCheck = checkTestFailure(workspace, currentModel, config);\n if (testCheck.triggered) triggers.push(testCheck);\n\n const completionCheck = checkTaskCompletion(issueId, config);\n if (completionCheck.triggered) triggers.push(completionCheck);\n\n return triggers;\n}\n","/**\n * Handoff Manager\n *\n * Orchestrates model handoffs for running agents using two methods:\n * 1. Kill & Spawn: For general agents (clean handoff with context preservation)\n * 2. Specialist Wake: For permanent specialists (resume with preserved context)\n */\n\nimport { existsSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport type { AgentState } from '../agents.js';\nimport { getAgentState, saveAgentState, stopAgent, spawnAgent, getAgentDir } from '../agents.js';\nimport type { HandoffContext } from './handoff-context.js';\nimport { captureHandoffContext, buildHandoffPrompt } from './handoff-context.js';\nimport { sessionExists } from '../tmux.js';\n\n/**\n * Handoff method type\n */\nexport type HandoffMethod = 'kill-spawn' | 'specialist-wake';\n\n/**\n * Handoff result\n */\nexport interface HandoffResult {\n success: boolean;\n method: HandoffMethod;\n newAgentId?: string;\n newSessionId?: string;\n context?: HandoffContext;\n error?: string;\n}\n\n/**\n * Handoff options\n */\nexport interface HandoffOptions {\n targetModel: string;\n reason: string;\n method?: HandoffMethod; // Auto-detect if not specified\n waitForIdle?: boolean; // Wait for agent to be idle before killing (default: true)\n idleTimeoutMs?: number; // How long to wait for idle (default: 30000)\n additionalInstructions?: string; // Extra instructions for new agent\n}\n\n/**\n * Perform a model handoff for an agent\n *\n * Auto-selects handoff method based on agent type:\n * - Specialists (merge-agent, test-agent, etc.): Use specialist-wake\n * - General agents: Use kill-spawn\n *\n * @param agentId - Agent to hand off\n * @param options - Handoff options\n * @returns Handoff result\n */\nexport async function performHandoff(\n agentId: string,\n options: HandoffOptions\n): Promise<HandoffResult> {\n // Get current agent state\n const state = getAgentState(agentId);\n if (!state) {\n return {\n success: false,\n method: 'kill-spawn',\n error: `Agent ${agentId} not found`,\n };\n }\n\n // Auto-detect method if not specified\n const method = options.method || detectHandoffMethod(agentId);\n\n // Execute appropriate handoff method\n if (method === 'specialist-wake') {\n return await performSpecialistWake(state, options);\n } else {\n return await performKillAndSpawn(state, options);\n }\n}\n\n/**\n * Detect appropriate handoff method for an agent\n *\n * @param agentId - Agent ID\n * @returns Handoff method\n */\nfunction detectHandoffMethod(agentId: string): HandoffMethod {\n // Specialists use specialist-wake (context-preserving resume)\n const specialists = ['merge-agent', 'review-agent', 'test-agent', 'planning-agent'];\n if (specialists.some(s => agentId.includes(s))) {\n return 'specialist-wake';\n }\n\n // General agents use kill-spawn\n return 'kill-spawn';\n}\n\n/**\n * Kill & Spawn handoff method\n *\n * Process:\n * 1. Signal agent to save state (update STATE.md)\n * 2. Wait for idle (check for activity)\n * 3. Capture handoff context\n * 4. Kill current agent\n * 5. Build handoff prompt\n * 6. Spawn new agent with target model\n *\n * @param state - Current agent state\n * @param options - Handoff options\n * @returns Handoff result\n */\nasync function performKillAndSpawn(\n state: AgentState,\n options: HandoffOptions\n): Promise<HandoffResult> {\n try {\n // Step 1: Signal agent to save state\n // TODO: Send message to agent asking to update STATE.md\n // For now, we'll capture what's there\n\n // Step 2: Wait for idle if requested\n if (options.waitForIdle !== false) {\n const timeout = options.idleTimeoutMs || 30000;\n const idle = await waitForIdle(state.id, timeout);\n if (!idle) {\n console.warn(`Agent ${state.id} did not become idle within ${timeout}ms`);\n }\n }\n\n // Step 3: Capture handoff context\n const context = await captureHandoffContext(state, options.targetModel, options.reason);\n\n // Step 4: Kill current agent\n stopAgent(state.id);\n\n // Step 5: Build handoff prompt\n const prompt = buildHandoffPrompt(context, options.additionalInstructions);\n\n // Save handoff prompt for debugging\n const handoffDir = join(getAgentDir(state.id), 'handoffs');\n mkdirSync(handoffDir, { recursive: true });\n const handoffFile = join(handoffDir, `handoff-${Date.now()}.md`);\n writeFileSync(handoffFile, prompt);\n\n // Step 6: Spawn new agent with target model\n // Use same agent ID to preserve identity\n const newState = spawnAgent({\n issueId: state.issueId,\n workspace: state.workspace,\n runtime: state.runtime,\n model: options.targetModel,\n prompt,\n });\n\n // Update handoff metrics\n newState.handoffCount = (state.handoffCount || 0) + 1;\n newState.costSoFar = state.costSoFar || 0;\n newState.complexity = state.complexity;\n saveAgentState(newState);\n\n return {\n success: true,\n method: 'kill-spawn',\n newAgentId: newState.id,\n context,\n };\n } catch (error) {\n return {\n success: false,\n method: 'kill-spawn',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Specialist Wake handoff method\n *\n * Process:\n * 1. Capture handoff context\n * 2. Use `claude --resume {sessionId}` to wake specialist\n * 3. Pass task-specific prompt\n * 4. Faster context loading, specialist expertise retained\n *\n * NOTE: This requires the specialist to have been initialized first.\n * Specialists are persistent sessions that can be resumed.\n *\n * @param state - Current agent state\n * @param options - Handoff options\n * @returns Handoff result\n */\nasync function performSpecialistWake(\n state: AgentState,\n options: HandoffOptions\n): Promise<HandoffResult> {\n try {\n // Step 1: Capture handoff context\n const context = await captureHandoffContext(state, options.targetModel, options.reason);\n\n // Step 2: Build task prompt for specialist\n const prompt = buildHandoffPrompt(context, options.additionalInstructions);\n\n // Step 3: Wake specialist using --resume\n // Determine specialist session ID from agent ID\n const specialistName = extractSpecialistName(state.id);\n if (!specialistName) {\n return {\n success: false,\n method: 'specialist-wake',\n error: 'Could not determine specialist name from agent ID',\n };\n }\n\n // Check if specialist session exists\n // TODO: Implement specialist session tracking\n // For now, fall back to kill-spawn\n console.warn(`Specialist wake not yet fully implemented, falling back to kill-spawn`);\n return await performKillAndSpawn(state, options);\n\n // Future implementation:\n // const specialistSessionId = await getSpecialistSessionId(specialistName);\n // if (!specialistSessionId) {\n // return { success: false, method: 'specialist-wake', error: 'Specialist session not found' };\n // }\n //\n // // Resume specialist with new task\n // execSync(`claude --resume ${specialistSessionId} --model ${options.targetModel}`, {\n // cwd: state.workspace,\n // });\n //\n // // Send prompt\n // messageAgent(state.id, prompt);\n //\n // return {\n // success: true,\n // method: 'specialist-wake',\n // newSessionId: specialistSessionId,\n // context,\n // };\n } catch (error) {\n return {\n success: false,\n method: 'specialist-wake',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Wait for agent to become idle\n *\n * @param agentId - Agent ID\n * @param timeoutMs - Timeout in milliseconds\n * @returns True if agent became idle, false if timeout\n */\nasync function waitForIdle(agentId: string, timeoutMs: number): Promise<boolean> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n // Check if agent session still exists\n if (!sessionExists(agentId)) {\n return true; // Agent is gone, consider it idle\n }\n\n // Check for recent activity\n // TODO: Implement proper activity detection\n // For now, just wait a bit\n await sleep(1000);\n }\n\n return false; // Timeout\n}\n\n/**\n * Extract specialist name from agent ID\n *\n * @param agentId - Agent ID (e.g., \"agent-merge-pan-18\")\n * @returns Specialist name or null\n */\nfunction extractSpecialistName(agentId: string): string | null {\n const specialists = ['merge-agent', 'review-agent', 'test-agent', 'planning-agent'];\n for (const specialist of specialists) {\n if (agentId.includes(specialist.replace('-agent', ''))) {\n return specialist;\n }\n }\n return null;\n}\n\n/**\n * Sleep helper\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Check if handoff is recommended for an agent\n *\n * This is a placeholder for future trigger logic.\n * Triggers will be implemented in Phase C.\n *\n * @param agentId - Agent ID\n * @returns True if handoff is recommended\n */\nexport function shouldHandoff(agentId: string): boolean {\n // TODO: Implement trigger logic in Phase C\n return false;\n}\n","/**\n * Handoff Context Module\n *\n * Captures and serializes agent context for handoffs between models.\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport type { TokenUsage } from '../runtimes/types.js';\nimport type { ComplexityLevel } from './complexity.js';\nimport type { AgentState } from '../agents.js';\nimport { getAgentDir } from '../agents.js';\n\n/**\n * Beads task snapshot for handoff\n */\nexport interface BeadsTask {\n id: string;\n title: string;\n description?: string;\n status: 'open' | 'in_progress' | 'closed';\n priority: number;\n labels?: string[];\n complexity?: ComplexityLevel;\n}\n\n/**\n * Handoff context - captures full state for agent transition\n */\nexport interface HandoffContext {\n // Agent identity\n issueId: string;\n agentId: string;\n workspace: string;\n\n // Source info\n previousModel: string;\n previousRuntime: 'claude-code';\n previousSessionId?: string;\n\n // Files\n stateFile?: string; // .planning/STATE.md content\n claudeMd?: string; // CLAUDE.md content\n\n // Git state\n gitBranch?: string;\n uncommittedFiles?: string[];\n lastCommit?: string;\n\n // Beads state\n activeBeadsTasks?: BeadsTask[];\n remainingTasks?: BeadsTask[];\n completedTasks?: BeadsTask[];\n\n // AI summaries\n whatWasDone?: string;\n whatRemains?: string;\n blockers?: string[];\n decisions?: string[];\n\n // Metrics\n tokenUsage?: TokenUsage;\n costSoFar?: number;\n handoffCount?: number;\n\n // New agent target\n targetModel: string;\n reason: string;\n}\n\n/**\n * Capture full handoff context from an agent\n *\n * @param agentState - Current agent state\n * @param targetModel - Model to hand off to\n * @param reason - Reason for handoff\n * @returns Handoff context\n */\nexport async function captureHandoffContext(\n agentState: AgentState,\n targetModel: string,\n reason: string\n): Promise<HandoffContext> {\n const context: HandoffContext = {\n issueId: agentState.issueId,\n agentId: agentState.id,\n workspace: agentState.workspace,\n previousModel: agentState.model,\n previousRuntime: 'claude-code',\n previousSessionId: agentState.sessionId,\n targetModel,\n reason,\n handoffCount: agentState.handoffCount || 0,\n costSoFar: agentState.costSoFar || 0,\n };\n\n // Capture files (STATE.md, CLAUDE.md)\n await captureFiles(context, agentState.workspace);\n\n // Capture git state\n await captureGitState(context, agentState.workspace);\n\n // Capture beads tasks\n await captureBeadsTasks(context, agentState.issueId);\n\n return context;\n}\n\n/**\n * Capture workspace files (STATE.md, CLAUDE.md)\n */\nasync function captureFiles(context: HandoffContext, workspace: string): Promise<void> {\n try {\n // Read STATE.md if it exists\n const stateFile = join(workspace, '.planning/STATE.md');\n if (existsSync(stateFile)) {\n context.stateFile = readFileSync(stateFile, 'utf-8');\n }\n\n // Read CLAUDE.md if it exists\n const claudeMd = join(workspace, 'CLAUDE.md');\n if (existsSync(claudeMd)) {\n context.claudeMd = readFileSync(claudeMd, 'utf-8');\n }\n } catch (error) {\n console.error('Error capturing files:', error);\n }\n}\n\n/**\n * Capture git state\n */\nasync function captureGitState(context: HandoffContext, workspace: string): Promise<void> {\n try {\n // Get current branch\n const branch = execSync('git branch --show-current', {\n cwd: workspace,\n encoding: 'utf-8',\n }).trim();\n context.gitBranch = branch;\n\n // Get uncommitted files\n const status = execSync('git status --porcelain', {\n cwd: workspace,\n encoding: 'utf-8',\n });\n context.uncommittedFiles = status\n .split('\\n')\n .filter(line => line.trim())\n .map(line => line.substring(3)); // Remove status prefix\n\n // Get last commit\n const lastCommit = execSync('git log -1 --oneline', {\n cwd: workspace,\n encoding: 'utf-8',\n }).trim();\n context.lastCommit = lastCommit;\n } catch (error) {\n console.error('Error capturing git state:', error);\n }\n}\n\n/**\n * Capture beads tasks state\n */\nasync function captureBeadsTasks(context: HandoffContext, issueId: string): Promise<void> {\n try {\n // List all tasks with this issue's label\n const label = issueId.toLowerCase();\n const output = execSync(`bd list --json -l ${label}`, {\n encoding: 'utf-8',\n });\n\n const tasks: BeadsTask[] = JSON.parse(output);\n\n // Categorize tasks\n context.activeBeadsTasks = tasks.filter(t => t.status === 'in_progress');\n context.remainingTasks = tasks.filter(t => t.status === 'open');\n context.completedTasks = tasks.filter(t => t.status === 'closed');\n } catch (error) {\n console.error('Error capturing beads tasks:', error);\n context.activeBeadsTasks = [];\n context.remainingTasks = [];\n context.completedTasks = [];\n }\n}\n\n/**\n * Serialize handoff context to markdown for agent prompt\n *\n * @param context - Handoff context\n * @returns Markdown representation\n */\nexport function serializeHandoffContext(context: HandoffContext): string {\n const lines: string[] = [];\n\n lines.push('# Handoff Context');\n lines.push('');\n lines.push(`**Reason:** ${context.reason}`);\n lines.push(`**From:** ${context.previousModel}`);\n lines.push(`**To:** ${context.targetModel}`);\n lines.push(`**Handoff Count:** ${context.handoffCount}`);\n if (context.costSoFar) {\n lines.push(`**Cost So Far:** $${context.costSoFar.toFixed(4)}`);\n }\n lines.push('');\n\n // Git state\n if (context.gitBranch) {\n lines.push('## Git State');\n lines.push('');\n lines.push(`**Branch:** ${context.gitBranch}`);\n if (context.lastCommit) {\n lines.push(`**Last Commit:** ${context.lastCommit}`);\n }\n if (context.uncommittedFiles && context.uncommittedFiles.length > 0) {\n lines.push(`**Uncommitted Files:** ${context.uncommittedFiles.length}`);\n lines.push('```');\n context.uncommittedFiles.forEach(file => lines.push(file));\n lines.push('```');\n }\n lines.push('');\n }\n\n // Beads tasks\n if (context.completedTasks && context.completedTasks.length > 0) {\n lines.push('## Completed Tasks');\n lines.push('');\n context.completedTasks.forEach(task => {\n lines.push(`- [x] ${task.title} (${task.id})`);\n });\n lines.push('');\n }\n\n if (context.activeBeadsTasks && context.activeBeadsTasks.length > 0) {\n lines.push('## Active Tasks');\n lines.push('');\n context.activeBeadsTasks.forEach(task => {\n lines.push(`- [ ] ${task.title} (${task.id}) - IN PROGRESS`);\n });\n lines.push('');\n }\n\n if (context.remainingTasks && context.remainingTasks.length > 0) {\n lines.push('## Remaining Tasks');\n lines.push('');\n context.remainingTasks.forEach(task => {\n lines.push(`- [ ] ${task.title} (${task.id})`);\n });\n lines.push('');\n }\n\n // STATE.md content\n if (context.stateFile) {\n lines.push('## Current State (STATE.md)');\n lines.push('');\n lines.push('```markdown');\n lines.push(context.stateFile);\n lines.push('```');\n lines.push('');\n }\n\n // AI summaries (if available)\n if (context.whatWasDone) {\n lines.push('## What Was Done');\n lines.push('');\n lines.push(context.whatWasDone);\n lines.push('');\n }\n\n if (context.whatRemains) {\n lines.push('## What Remains');\n lines.push('');\n lines.push(context.whatRemains);\n lines.push('');\n }\n\n if (context.blockers && context.blockers.length > 0) {\n lines.push('## Blockers');\n lines.push('');\n context.blockers.forEach(blocker => lines.push(`- ${blocker}`));\n lines.push('');\n }\n\n if (context.decisions && context.decisions.length > 0) {\n lines.push('## Decisions Made');\n lines.push('');\n context.decisions.forEach(decision => lines.push(`- ${decision}`));\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Build handoff prompt for new agent\n *\n * @param context - Handoff context\n * @param additionalInstructions - Optional additional instructions\n * @returns Prompt for new agent\n */\nexport function buildHandoffPrompt(\n context: HandoffContext,\n additionalInstructions?: string\n): string {\n const lines: string[] = [];\n\n lines.push('# Agent Handoff');\n lines.push('');\n lines.push(`You are taking over work on issue ${context.issueId} from a ${context.previousModel} agent.`);\n lines.push('');\n lines.push(`**Handoff Reason:** ${context.reason}`);\n lines.push('');\n lines.push('Please review the context below and continue the work.');\n lines.push('');\n lines.push('---');\n lines.push('');\n lines.push(serializeHandoffContext(context));\n\n if (additionalInstructions) {\n lines.push('---');\n lines.push('');\n lines.push('## Additional Instructions');\n lines.push('');\n lines.push(additionalInstructions);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","/**\n * Handoff Event Logger\n *\n * Logs handoff events to JSONL file for tracking and analysis.\n */\n\nimport { existsSync, mkdirSync, appendFileSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { PANOPTICON_HOME } from '../paths.js';\nimport type { HandoffContext } from './handoff-context.js';\nimport type { TriggerType } from './triggers.js';\n\n/**\n * Handoff event structure\n */\nexport interface HandoffEvent {\n timestamp: string;\n agentId: string;\n issueId: string;\n\n // Model transition\n from: {\n model: string;\n runtime: string;\n sessionId?: string;\n };\n to: {\n model: string;\n runtime: string;\n sessionId?: string;\n };\n\n // Trigger information\n trigger: TriggerType | 'manual';\n reason: string;\n\n // Context\n context: {\n beadsTaskCompleted?: string;\n stuckMinutes?: number;\n costAtHandoff?: number;\n handoffCount?: number;\n };\n\n // Result\n success: boolean;\n errorMessage?: string;\n}\n\n/**\n * Handoff log file path\n */\nconst HANDOFF_LOG_FILE = join(PANOPTICON_HOME, 'logs', 'handoffs.jsonl');\n\n/**\n * Ensure log directory exists\n */\nfunction ensureLogDir(): void {\n const logDir = join(PANOPTICON_HOME, 'logs');\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n}\n\n/**\n * Log a handoff event\n *\n * @param event - Handoff event to log\n */\nexport function logHandoffEvent(event: HandoffEvent): void {\n ensureLogDir();\n\n const line = JSON.stringify(event) + '\\n';\n appendFileSync(HANDOFF_LOG_FILE, line, 'utf-8');\n}\n\n/**\n * Create a handoff event from handoff result\n *\n * @param agentId - Agent ID\n * @param issueId - Issue ID\n * @param context - Handoff context\n * @param trigger - Trigger type\n * @param success - Whether handoff succeeded\n * @param errorMessage - Error message if failed\n * @returns Handoff event\n */\nexport function createHandoffEvent(\n agentId: string,\n issueId: string,\n context: HandoffContext,\n trigger: TriggerType | 'manual',\n success: boolean,\n errorMessage?: string\n): HandoffEvent {\n // Calculate stuck minutes if applicable\n let stuckMinutes: number | undefined;\n if (trigger === 'stuck_escalation') {\n // This would be calculated from health state\n // For now, we'll omit it unless available in context\n }\n\n return {\n timestamp: new Date().toISOString(),\n agentId,\n issueId,\n from: {\n model: context.previousModel,\n runtime: context.previousRuntime,\n sessionId: context.previousSessionId,\n },\n to: {\n model: context.targetModel,\n runtime: 'claude-code', // New agent runtime\n sessionId: undefined, // Will be set after spawn\n },\n trigger,\n reason: context.reason,\n context: {\n costAtHandoff: context.costSoFar,\n handoffCount: context.handoffCount,\n stuckMinutes,\n },\n success,\n errorMessage,\n };\n}\n\n/**\n * Read all handoff events from log\n *\n * @param limit - Maximum number of events to return (most recent first)\n * @returns Array of handoff events\n */\nexport function readHandoffEvents(limit?: number): HandoffEvent[] {\n ensureLogDir();\n\n if (!existsSync(HANDOFF_LOG_FILE)) {\n return [];\n }\n\n const content = readFileSync(HANDOFF_LOG_FILE, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.trim());\n\n const events = lines.map(line => JSON.parse(line) as HandoffEvent);\n\n // Return most recent first\n events.reverse();\n\n if (limit) {\n return events.slice(0, limit);\n }\n\n return events;\n}\n\n/**\n * Read handoff events for a specific issue\n *\n * @param issueId - Issue ID\n * @returns Array of handoff events for the issue\n */\nexport function readIssueHandoffEvents(issueId: string): HandoffEvent[] {\n const allEvents = readHandoffEvents();\n return allEvents.filter(e => e.issueId === issueId);\n}\n\n/**\n * Read handoff events for a specific agent\n *\n * @param agentId - Agent ID\n * @returns Array of handoff events for the agent\n */\nexport function readAgentHandoffEvents(agentId: string): HandoffEvent[] {\n const allEvents = readHandoffEvents();\n return allEvents.filter(e => e.agentId === agentId);\n}\n\n/**\n * Get handoff statistics\n *\n * @returns Handoff statistics\n */\nexport function getHandoffStats(): {\n totalHandoffs: number;\n byTrigger: Record<string, number>;\n byModel: {\n from: Record<string, number>;\n to: Record<string, number>;\n };\n successRate: number;\n} {\n const events = readHandoffEvents();\n\n const stats = {\n totalHandoffs: events.length,\n byTrigger: {} as Record<string, number>,\n byModel: {\n from: {} as Record<string, number>,\n to: {} as Record<string, number>,\n },\n successRate: 0,\n };\n\n let successCount = 0;\n\n for (const event of events) {\n // Count by trigger\n stats.byTrigger[event.trigger] = (stats.byTrigger[event.trigger] || 0) + 1;\n\n // Count by model\n stats.byModel.from[event.from.model] = (stats.byModel.from[event.from.model] || 0) + 1;\n stats.byModel.to[event.to.model] = (stats.byModel.to[event.to.model] || 0) + 1;\n\n // Count successes\n if (event.success) {\n successCount++;\n }\n }\n\n stats.successRate = events.length > 0 ? successCount / events.length : 0;\n\n return stats;\n}\n","/**\n * Cloister Service\n *\n * Core monitoring service that watches over all running agents.\n * Named after the TARDIS's Cloister Bell - an alarm for catastrophic events.\n */\n\nimport type { AgentRuntime, HealthState } from '../runtimes/types.js';\nimport type { CloisterConfig } from './config.js';\nimport type { AgentHealth, HealthSummary } from './health.js';\nimport { loadCloisterConfig } from './config.js';\nimport {\n getAgentHealth,\n getMultipleAgentHealth,\n generateHealthSummary,\n getAgentsToPoke,\n getAgentsToKill,\n getAgentsNeedingAttention,\n} from './health.js';\nimport {\n initHealthDatabase,\n writeHealthEvent,\n getLatestHealthEvent,\n closeHealthDatabase,\n} from './database.js';\nimport { initializeEnabledSpecialists } from './specialists.js';\nimport { getGlobalRegistry, getRuntimeForAgent } from '../runtimes/index.js';\nimport { listRunningAgents, getAgentState } from '../agents.js';\nimport { checkAllTriggers, type TriggerDetection } from './triggers.js';\nimport { performHandoff, type HandoffResult } from './handoff.js';\nimport { logHandoffEvent, createHandoffEvent } from './handoff-logger.js';\n\n/**\n * Cloister service status\n */\nexport interface CloisterStatus {\n running: boolean;\n lastCheck: Date | null;\n config: CloisterConfig;\n summary: HealthSummary;\n agentsNeedingAttention: string[];\n}\n\n/**\n * Cloister service event\n */\nexport type CloisterEvent =\n | { type: 'started' }\n | { type: 'stopped' }\n | { type: 'health_check'; agentHealths: AgentHealth[] }\n | { type: 'agent_warning'; agentId: string; health: AgentHealth }\n | { type: 'agent_stuck'; agentId: string; health: AgentHealth }\n | { type: 'poked_agent'; agentId: string }\n | { type: 'killed_agent'; agentId: string }\n | { type: 'handoff_triggered'; agentId: string; trigger: TriggerDetection }\n | { type: 'handoff_completed'; agentId: string; result: HandoffResult }\n | { type: 'emergency_stop'; killedAgents: string[] }\n | { type: 'error'; error: Error };\n\n/**\n * Cloister service event listener\n */\nexport type CloisterEventListener = (event: CloisterEvent) => void;\n\n/**\n * Cloister Service\n *\n * Monitors agent health and performs auto-actions.\n */\nexport class CloisterService {\n private running: boolean = false;\n private checkInterval: NodeJS.Timeout | null = null;\n private lastCheck: Date | null = null;\n private config: CloisterConfig;\n private listeners: CloisterEventListener[] = [];\n private previousStates: Map<string, HealthState> = new Map();\n\n constructor(config?: CloisterConfig) {\n this.config = config || loadCloisterConfig();\n }\n\n /**\n * Start the Cloister service\n */\n async start(): Promise<void> {\n if (this.running) {\n console.warn('Cloister is already running');\n return;\n }\n\n console.log('🔔 Starting Cloister agent watchdog...');\n\n // Initialize health history database\n try {\n initHealthDatabase();\n console.log(' ✓ Health history database initialized');\n } catch (error) {\n console.error(' ✗ Failed to initialize health database:', error);\n }\n\n // Auto-initialize enabled specialists\n try {\n console.log(' → Checking specialists...');\n const results = await initializeEnabledSpecialists();\n for (const result of results) {\n if (result.success) {\n console.log(` ✓ ${result.name}: ${result.message}`);\n } else {\n console.log(` ✗ ${result.name}: ${result.message}`);\n }\n }\n } catch (error) {\n console.error(' ✗ Failed to initialize specialists:', error);\n }\n\n this.running = true;\n this.emit({ type: 'started' });\n\n // Start monitoring loop\n this.startMonitoringLoop();\n }\n\n /**\n * Stop the Cloister service\n *\n * Note: This stops monitoring but does NOT kill agents.\n * Use emergencyStop() to kill all agents.\n */\n stop(): void {\n if (!this.running) {\n console.warn('Cloister is not running');\n return;\n }\n\n console.log('🔔 Stopping Cloister agent watchdog...');\n this.running = false;\n\n if (this.checkInterval) {\n clearInterval(this.checkInterval);\n this.checkInterval = null;\n }\n\n // Close database connection\n try {\n closeHealthDatabase();\n } catch (error) {\n console.error('Failed to close health database:', error);\n }\n\n this.emit({ type: 'stopped' });\n }\n\n /**\n * Emergency stop - kill ALL agents immediately\n *\n * This is the nuclear option. Use with caution.\n */\n emergencyStop(): string[] {\n console.log('🚨 EMERGENCY STOP - Killing all agents');\n\n const runningAgents = listRunningAgents();\n const killedAgents: string[] = [];\n\n for (const agent of runningAgents) {\n if (agent.tmuxActive) {\n try {\n const runtime = getRuntimeForAgent(agent.id);\n if (runtime) {\n runtime.killAgent(agent.id);\n killedAgents.push(agent.id);\n console.log(` ✓ Killed ${agent.id}`);\n }\n } catch (error) {\n console.error(` ✗ Failed to kill ${agent.id}:`, error);\n }\n }\n }\n\n this.emit({ type: 'emergency_stop', killedAgents });\n\n // Stop monitoring after emergency stop\n this.stop();\n\n return killedAgents;\n }\n\n /**\n * Start the monitoring loop\n */\n private startMonitoringLoop(): void {\n // Run initial check immediately\n this.performHealthCheck();\n\n // Schedule periodic checks\n const intervalMs = this.config.monitoring.check_interval * 1000;\n this.checkInterval = setInterval(() => {\n this.performHealthCheck();\n }, intervalMs);\n }\n\n /**\n * Perform a health check on all running agents\n */\n private async performHealthCheck(): Promise<void> {\n try {\n const runningAgents = listRunningAgents().filter((a) => a.tmuxActive);\n const agentIds = runningAgents.map((a) => a.id);\n\n if (agentIds.length === 0) {\n this.lastCheck = new Date();\n return;\n }\n\n // Get health for all agents\n const agentHealths: AgentHealth[] = [];\n\n for (const agentId of agentIds) {\n const runtime = getRuntimeForAgent(agentId);\n if (runtime) {\n const health = getAgentHealth(agentId, runtime);\n agentHealths.push(health);\n\n // Write health event to database\n this.recordHealthEvent(health);\n }\n }\n\n this.lastCheck = new Date();\n this.emit({ type: 'health_check', agentHealths });\n\n // Check for agents needing attention\n const needsAttention = getAgentsNeedingAttention(agentHealths);\n\n for (const health of needsAttention) {\n if (health.state === 'warning') {\n this.emit({ type: 'agent_warning', agentId: health.agentId, health });\n\n // Auto-poke if configured\n if (this.config.auto_actions.poke_on_warning) {\n this.pokeAgent(health.agentId);\n }\n } else if (health.state === 'stuck') {\n this.emit({ type: 'agent_stuck', agentId: health.agentId, health });\n\n // Auto-kill if configured (dangerous!)\n if (this.config.auto_actions.kill_on_stuck) {\n this.killAgent(health.agentId);\n }\n }\n }\n\n // Check for handoff triggers (Phase 4)\n await this.checkHandoffTriggers(agentHealths);\n } catch (error) {\n console.error('Cloister health check failed:', error);\n this.emit({ type: 'error', error: error as Error });\n }\n }\n\n /**\n * Poke an agent (send \"are you stuck?\" message)\n */\n private pokeAgent(agentId: string): void {\n try {\n const runtime = getRuntimeForAgent(agentId);\n if (!runtime) {\n throw new Error(`No runtime found for agent ${agentId}`);\n }\n\n const pokeMessage =\n 'Hey, I noticed you haven\\'t made progress in a while. Are you stuck? ' +\n 'If you need help or clarification, please ask. Otherwise, please continue with your work.';\n\n runtime.sendMessage(agentId, pokeMessage);\n this.emit({ type: 'poked_agent', agentId });\n\n console.log(`🔔 Poked ${agentId}`);\n } catch (error) {\n console.error(`Failed to poke ${agentId}:`, error);\n }\n }\n\n /**\n * Kill an agent\n */\n private killAgent(agentId: string): void {\n try {\n const runtime = getRuntimeForAgent(agentId);\n if (!runtime) {\n throw new Error(`No runtime found for agent ${agentId}`);\n }\n\n runtime.killAgent(agentId);\n this.emit({ type: 'killed_agent', agentId });\n\n console.log(`🔔 Killed ${agentId}`);\n } catch (error) {\n console.error(`Failed to kill ${agentId}:`, error);\n }\n }\n\n /**\n * Record health event to database\n *\n * Only writes events when state changes or on first check.\n */\n private recordHealthEvent(health: AgentHealth): void {\n try {\n const currentState = health.state;\n const previousState = this.previousStates.get(health.agentId);\n\n // Only write event if state changed or this is first check\n if (previousState === undefined || previousState !== currentState) {\n // Determine source from heartbeat\n const source = health.heartbeat?.source\n ? this.mapActivitySource(health.heartbeat.source)\n : 'unknown';\n\n writeHealthEvent({\n agentId: health.agentId,\n timestamp: new Date().toISOString(),\n state: currentState,\n previousState: previousState,\n source,\n metadata: health.heartbeat\n ? JSON.stringify({\n confidence: health.heartbeat.confidence,\n lastAction: health.heartbeat.lastAction,\n toolName: health.heartbeat.toolName,\n timeSinceActivity: health.timeSinceActivity,\n })\n : undefined,\n });\n\n // Update tracked state\n this.previousStates.set(health.agentId, currentState);\n }\n } catch (error) {\n console.error(`Failed to record health event for ${health.agentId}:`, error);\n }\n }\n\n /**\n * Check for handoff triggers and execute handoffs (Phase 4)\n *\n * Checks all triggers for each agent and performs handoffs when triggered.\n */\n private async checkHandoffTriggers(agentHealths: AgentHealth[]): Promise<void> {\n for (const health of agentHealths) {\n try {\n // Get agent state\n const agentState = getAgentState(health.agentId);\n if (!agentState) continue;\n\n // Skip if no workspace (can't determine context)\n if (!agentState.workspace) continue;\n\n // Check all triggers\n const triggers = checkAllTriggers(\n health.agentId,\n agentState.workspace,\n agentState.issueId,\n agentState.model,\n health,\n this.config\n );\n\n // Execute handoff for first triggered condition\n // (Priority: stuck > planning > test > completion)\n if (triggers.length > 0) {\n const trigger = triggers[0];\n this.emit({ type: 'handoff_triggered', agentId: health.agentId, trigger });\n\n console.log(`🔔 Handoff triggered for ${health.agentId}: ${trigger.reason}`);\n\n // Perform handoff\n const result = await performHandoff(health.agentId, {\n targetModel: trigger.suggestedModel || 'sonnet',\n reason: trigger.reason,\n });\n\n this.emit({ type: 'handoff_completed', agentId: health.agentId, result });\n\n // Log handoff event\n if (result.context) {\n const event = createHandoffEvent(\n health.agentId,\n agentState.issueId,\n result.context,\n trigger.type,\n result.success,\n result.error\n );\n logHandoffEvent(event);\n }\n\n if (result.success) {\n console.log(`✓ Handoff completed: ${health.agentId} → ${result.newAgentId} (${trigger.suggestedModel})`);\n } else {\n console.error(`✗ Handoff failed: ${result.error}`);\n }\n }\n } catch (error) {\n console.error(`Failed to check handoff triggers for ${health.agentId}:`, error);\n }\n }\n }\n\n /**\n * Map ActivitySource to database source string\n */\n private mapActivitySource(source: string): string {\n switch (source) {\n case 'jsonl':\n return 'jsonl_mtime';\n case 'tmux':\n return 'tmux_activity';\n case 'git':\n return 'git_activity';\n case 'active-heartbeat':\n return 'active_heartbeat';\n default:\n return source;\n }\n }\n\n /**\n * Get current status\n */\n getStatus(): CloisterStatus {\n const runningAgents = listRunningAgents().filter((a) => a.tmuxActive);\n const agentIds = runningAgents.map((a) => a.id);\n\n const agentHealths: AgentHealth[] = [];\n\n for (const agentId of agentIds) {\n const runtime = getRuntimeForAgent(agentId);\n if (runtime) {\n const health = getAgentHealth(agentId, runtime);\n agentHealths.push(health);\n }\n }\n\n const summary = generateHealthSummary(agentHealths);\n const needsAttention = getAgentsNeedingAttention(agentHealths).map((h) => h.agentId);\n\n return {\n running: this.running,\n lastCheck: this.lastCheck,\n config: this.config,\n summary,\n agentsNeedingAttention: needsAttention,\n };\n }\n\n /**\n * Get health for a specific agent\n */\n getAgentHealth(agentId: string): AgentHealth | null {\n const runtime = getRuntimeForAgent(agentId);\n if (!runtime) {\n return null;\n }\n\n return getAgentHealth(agentId, runtime);\n }\n\n /**\n * Get health for all running agents\n */\n getAllAgentHealth(): AgentHealth[] {\n const runningAgents = listRunningAgents().filter((a) => a.tmuxActive);\n const agentHealths: AgentHealth[] = [];\n\n for (const agent of runningAgents) {\n const runtime = getRuntimeForAgent(agent.id);\n if (runtime) {\n const health = getAgentHealth(agent.id, runtime);\n agentHealths.push(health);\n }\n }\n\n return agentHealths;\n }\n\n /**\n * Reload configuration\n */\n reloadConfig(): void {\n this.config = loadCloisterConfig();\n\n // Restart monitoring loop with new interval if running\n if (this.running && this.checkInterval) {\n clearInterval(this.checkInterval);\n this.startMonitoringLoop();\n }\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: CloisterConfig): void {\n this.config = config;\n\n // Restart monitoring loop with new interval if running\n if (this.running && this.checkInterval) {\n clearInterval(this.checkInterval);\n this.startMonitoringLoop();\n }\n }\n\n /**\n * Register an event listener\n */\n on(listener: CloisterEventListener): void {\n this.listeners.push(listener);\n }\n\n /**\n * Unregister an event listener\n */\n off(listener: CloisterEventListener): void {\n this.listeners = this.listeners.filter((l) => l !== listener);\n }\n\n /**\n * Emit an event to all listeners\n */\n private emit(event: CloisterEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('Cloister event listener error:', error);\n }\n }\n }\n\n /**\n * Check if service is running\n */\n isRunning(): boolean {\n return this.running;\n }\n}\n\n/**\n * Global Cloister service instance\n */\nlet globalService: CloisterService | null = null;\n\n/**\n * Get the global Cloister service instance\n *\n * Creates a new instance if one doesn't exist.\n */\nexport function getCloisterService(): CloisterService {\n if (!globalService) {\n globalService = new CloisterService();\n }\n return globalService;\n}\n\n/**\n * Set the global Cloister service instance\n *\n * Useful for testing or custom configurations.\n */\nexport function setCloisterService(service: CloisterService): void {\n globalService = service;\n}\n","/**\n * pan cloister start command\n *\n * Start Cloister monitoring service.\n */\n\nimport chalk from 'chalk';\nimport { getCloisterService } from '../../../lib/cloister/service.js';\n\nexport async function startCommand(): Promise<void> {\n const service = getCloisterService();\n\n if (service.isRunning()) {\n console.log(chalk.yellow('⚠️ Cloister is already running'));\n return;\n }\n\n await service.start();\n console.log(chalk.green('✓ Cloister started'));\n console.log(chalk.dim(' Monitoring all running agents...'));\n}\n","/**\n * pan cloister stop command\n *\n * Stop Cloister monitoring service (agents continue running).\n */\n\nimport chalk from 'chalk';\nimport { getCloisterService } from '../../../lib/cloister/service.js';\n\ninterface StopOptions {\n emergency?: boolean;\n}\n\nexport async function stopCommand(options: StopOptions): Promise<void> {\n const service = getCloisterService();\n\n if (!service.isRunning() && !options.emergency) {\n console.log(chalk.yellow('⚠️ Cloister is not running'));\n return;\n }\n\n if (options.emergency) {\n // Emergency stop - kill all agents\n console.log(chalk.red.bold('🚨 EMERGENCY STOP - Killing all agents'));\n console.log(chalk.dim(' This will terminate all running agent sessions'));\n\n const killedAgents = service.emergencyStop();\n\n console.log('');\n console.log(chalk.green(`✓ Killed ${killedAgents.length} agent(s):`));\n for (const agentId of killedAgents) {\n console.log(chalk.dim(` - ${agentId}`));\n }\n } else {\n // Normal stop - just stop monitoring\n service.stop();\n console.log(chalk.green('✓ Cloister stopped'));\n console.log(chalk.dim(' Agents are still running'));\n }\n}\n","/**\n * Cloister CLI Commands\n *\n * pan cloister <command>\n */\n\nimport { Command } from 'commander';\nimport { statusCommand } from './status.js';\nimport { startCommand } from './start.js';\nimport { stopCommand } from './stop.js';\n\nexport function registerCloisterCommands(program: Command): void {\n const cloister = program\n .command('cloister')\n .description('Cloister agent watchdog commands');\n\n // pan cloister status\n cloister\n .command('status')\n .description('Show Cloister service status and agent health')\n .option('--json', 'Output in JSON format')\n .action(statusCommand);\n\n // pan cloister start\n cloister\n .command('start')\n .description('Start Cloister monitoring service')\n .action(startCommand);\n\n // pan cloister stop\n cloister\n .command('stop')\n .description('Stop Cloister monitoring (agents continue running)')\n .action(stopCommand);\n\n // pan cloister emergency-stop\n cloister\n .command('emergency-stop')\n .description('Emergency stop - kill ALL agents immediately')\n .action(() => stopCommand({ emergency: true }));\n}\n","import chalk from 'chalk';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, chmodSync } from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { homedir } from 'os';\n\ninterface ClaudeSettings {\n hooks?: {\n PostToolUse?: Array<{\n matcher: string; // Regex pattern, e.g. \".*\" for all tools or \"Bash\" for specific\n hooks: Array<{\n type: string;\n command: string;\n }>;\n }>;\n };\n [key: string]: any;\n}\n\n/**\n * Check if jq is installed\n */\nfunction checkJqInstalled(): boolean {\n try {\n execSync('which jq', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Attempt to install jq using package manager\n */\nfunction installJq(): boolean {\n console.log(chalk.yellow('Installing jq dependency...'));\n\n try {\n // Detect platform and package manager\n const platform = process.platform;\n\n if (platform === 'darwin') {\n // macOS - try homebrew\n try {\n execSync('brew --version', { stdio: 'pipe' });\n execSync('brew install jq', { stdio: 'inherit' });\n console.log(chalk.green('✓ jq installed via Homebrew'));\n return true;\n } catch {\n console.log(chalk.yellow('⚠ Homebrew not found'));\n }\n } else if (platform === 'linux') {\n // Linux - try apt, then yum\n try {\n execSync('apt-get --version', { stdio: 'pipe' });\n execSync('sudo apt-get update && sudo apt-get install -y jq', { stdio: 'inherit' });\n console.log(chalk.green('✓ jq installed via apt'));\n return true;\n } catch {\n try {\n execSync('yum --version', { stdio: 'pipe' });\n execSync('sudo yum install -y jq', { stdio: 'inherit' });\n console.log(chalk.green('✓ jq installed via yum'));\n return true;\n } catch {\n console.log(chalk.yellow('⚠ No supported package manager found (apt/yum)'));\n }\n }\n }\n\n return false;\n } catch (error) {\n console.log(chalk.red('✗ Failed to install jq automatically'));\n return false;\n }\n}\n\n/**\n * Check if Panopticon heartbeat hook is already configured\n */\nfunction hookAlreadyConfigured(settings: ClaudeSettings, hookPath: string): boolean {\n const postToolUse = settings?.hooks?.PostToolUse || [];\n return postToolUse.some((hookConfig) =>\n hookConfig.hooks?.some((hook) =>\n hook.command === hookPath ||\n hook.command?.includes('panopticon') ||\n hook.command?.includes('heartbeat-hook')\n )\n );\n}\n\n/**\n * Setup Claude Code hooks for Panopticon heartbeat\n */\nexport async function setupHooksCommand(): Promise<void> {\n console.log(chalk.bold('Setting up Panopticon heartbeat hooks\\n'));\n\n // 1. Check for jq dependency\n if (!checkJqInstalled()) {\n console.log(chalk.yellow('⚠ jq is required for heartbeat hooks'));\n const installed = installJq();\n\n if (!installed) {\n console.log(chalk.red('\\n✗ Setup failed: jq dependency missing'));\n console.log(chalk.dim('\\nPlease install jq manually:'));\n console.log(chalk.dim(' macOS: brew install jq'));\n console.log(chalk.dim(' Ubuntu: sudo apt-get install jq'));\n console.log(chalk.dim(' CentOS: sudo yum install jq\\n'));\n process.exit(1);\n }\n } else {\n console.log(chalk.green('✓ jq is installed'));\n }\n\n // 2. Ensure ~/.panopticon/bin directory exists\n const panopticonHome = join(homedir(), '.panopticon');\n const binDir = join(panopticonHome, 'bin');\n const heartbeatsDir = join(panopticonHome, 'heartbeats');\n\n if (!existsSync(binDir)) {\n mkdirSync(binDir, { recursive: true });\n console.log(chalk.green('✓ Created ~/.panopticon/bin/'));\n }\n\n if (!existsSync(heartbeatsDir)) {\n mkdirSync(heartbeatsDir, { recursive: true });\n console.log(chalk.green('✓ Created ~/.panopticon/heartbeats/'));\n }\n\n // 3. Copy heartbeat-hook script to ~/.panopticon/bin/\n // Find the script in the Panopticon installation\n const scriptSource = join(process.cwd(), 'scripts', 'heartbeat-hook');\n const scriptDest = join(binDir, 'heartbeat-hook');\n\n // Check if script exists in cwd/scripts (development mode)\n let sourcePath = scriptSource;\n if (!existsSync(sourcePath)) {\n // Try finding it relative to CLI location (installed mode)\n const { fileURLToPath } = await import('url');\n const { dirname } = await import('path');\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const installedSource = join(__dirname, '..', '..', '..', 'scripts', 'heartbeat-hook');\n\n if (existsSync(installedSource)) {\n sourcePath = installedSource;\n } else {\n console.log(chalk.red('✗ Could not find heartbeat-hook script'));\n console.log(chalk.dim(` Checked: ${scriptSource}`));\n console.log(chalk.dim(` Checked: ${installedSource}`));\n process.exit(1);\n }\n }\n\n copyFileSync(sourcePath, scriptDest);\n chmodSync(scriptDest, 0o755); // Make executable\n console.log(chalk.green('✓ Installed heartbeat-hook script'));\n\n // 4. Read or create Claude Code settings.json\n const claudeDir = join(homedir(), '.claude');\n const settingsPath = join(claudeDir, 'settings.json');\n\n let settings: ClaudeSettings = {};\n\n if (existsSync(settingsPath)) {\n try {\n const settingsContent = readFileSync(settingsPath, 'utf-8');\n settings = JSON.parse(settingsContent);\n console.log(chalk.green('✓ Read existing Claude Code settings'));\n } catch (error) {\n console.log(chalk.yellow('⚠ Could not parse settings.json, creating new file'));\n settings = {};\n }\n } else {\n console.log(chalk.dim('No existing settings.json found, creating new file'));\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n }\n\n // 5. Check if hook is already configured\n if (hookAlreadyConfigured(settings, scriptDest)) {\n console.log(chalk.cyan('\\n✓ Panopticon heartbeat hook already configured'));\n console.log(chalk.dim(' No changes needed\\n'));\n return;\n }\n\n // 6. Add Panopticon hook to settings\n if (!settings.hooks) {\n settings.hooks = {};\n }\n\n if (!settings.hooks.PostToolUse) {\n settings.hooks.PostToolUse = [];\n }\n\n // Append Panopticon hook (matcher: \".*\" matches all tools)\n settings.hooks.PostToolUse.push({\n matcher: '.*',\n hooks: [\n {\n type: 'command',\n command: scriptDest\n }\n ]\n });\n\n // 7. Write updated settings\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2));\n console.log(chalk.green('✓ Updated Claude Code settings.json'));\n\n // 8. Success message\n console.log(chalk.green.bold('\\n✓ Setup complete!\\n'));\n console.log(chalk.dim('Heartbeat hooks are now active. When you run agents via'));\n console.log(chalk.dim('`pan work issue`, they will send real-time activity updates'));\n console.log(chalk.dim('to the Panopticon dashboard.\\n'));\n}\n","import { Command } from 'commander';\nimport { setupHooksCommand } from './hooks.js';\n\n/**\n * Register all setup subcommands\n */\nexport function registerSetupCommands(program: Command): void {\n const setup = program\n .command('setup')\n .description('Setup and configure Panopticon components');\n\n setup\n .command('hooks')\n .description('Configure Claude Code hooks for heartbeat tracking')\n .action(setupHooksCommand);\n}\n","import chalk from 'chalk';\nimport { existsSync, readFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport {\n listProjects,\n registerProject,\n unregisterProject,\n getProject,\n initializeProjectsConfig,\n PROJECTS_CONFIG_FILE,\n ProjectConfig,\n IssueRoutingRule,\n} from '../../lib/projects.js';\n\ninterface AddOptions {\n name?: string;\n type?: 'standalone' | 'monorepo';\n linearTeam?: string;\n}\n\nexport async function projectAddCommand(\n projectPath: string,\n options: AddOptions = {}\n): Promise<void> {\n const fullPath = resolve(projectPath);\n\n if (!existsSync(fullPath)) {\n console.log(chalk.red(`Path does not exist: ${fullPath}`));\n return;\n }\n\n // Determine name/key from directory if not provided\n const name = options.name || fullPath.split('/').pop() || 'unknown';\n const key = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n\n // Check if already registered\n const existing = getProject(key);\n if (existing) {\n console.log(chalk.yellow(`Project already registered with key: ${key}`));\n console.log(chalk.dim(`Existing path: ${existing.path}`));\n console.log(chalk.dim(`To update, first run: pan project remove ${key}`));\n return;\n }\n\n // Try to detect Linear team from .panopticon/project.toml or package.json\n let linearTeam = options.linearTeam;\n if (!linearTeam) {\n const projectToml = join(fullPath, '.panopticon', 'project.toml');\n if (existsSync(projectToml)) {\n const content = readFileSync(projectToml, 'utf-8');\n const match = content.match(/team\\s*=\\s*\"([^\"]+)\"/);\n if (match) linearTeam = match[1];\n }\n }\n\n const projectConfig: ProjectConfig = {\n name,\n path: fullPath,\n };\n\n if (linearTeam) {\n projectConfig.linear_team = linearTeam.toUpperCase();\n }\n\n registerProject(key, projectConfig);\n\n console.log(chalk.green(`✓ Added project: ${name}`));\n console.log(chalk.dim(` Key: ${key}`));\n console.log(chalk.dim(` Path: ${fullPath}`));\n if (linearTeam) {\n console.log(chalk.dim(` Linear team: ${linearTeam}`));\n }\n console.log('');\n console.log(chalk.dim(`Edit ${PROJECTS_CONFIG_FILE} to add issue routing rules.`));\n}\n\ninterface ListOptions {\n json?: boolean;\n}\n\nexport async function projectListCommand(options: ListOptions = {}): Promise<void> {\n const projects = listProjects();\n\n if (projects.length === 0) {\n console.log(chalk.dim('No projects registered.'));\n console.log(chalk.dim('Add one with: pan project add <path> --linear-team <TEAM>'));\n console.log(chalk.dim(`Or edit: ${PROJECTS_CONFIG_FILE}`));\n return;\n }\n\n if (options.json) {\n const output: Record<string, ProjectConfig> = {};\n for (const { key, config } of projects) {\n output[key] = config;\n }\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n console.log(chalk.bold('\\nRegistered Projects:\\n'));\n\n for (const { key, config } of projects) {\n const exists = existsSync(config.path);\n const statusIcon = exists ? chalk.green('✓') : chalk.red('✗');\n\n console.log(`${statusIcon} ${chalk.bold(config.name)} ${chalk.dim(`(${key})`)}`);\n console.log(` ${chalk.dim(config.path)}`);\n if (config.linear_team) {\n console.log(` ${chalk.cyan(`Linear: ${config.linear_team}`)}`);\n }\n if (config.issue_routing && config.issue_routing.length > 0) {\n console.log(` ${chalk.dim(`Routes: ${config.issue_routing.length} rules`)}`);\n }\n console.log('');\n }\n\n console.log(chalk.dim(`Config: ${PROJECTS_CONFIG_FILE}`));\n}\n\nexport async function projectRemoveCommand(nameOrPath: string): Promise<void> {\n // Try to find by key first, then by name, then by path\n const projects = listProjects();\n\n // Try direct key match\n if (unregisterProject(nameOrPath)) {\n console.log(chalk.green(`✓ Removed project: ${nameOrPath}`));\n return;\n }\n\n // Try to find by name or path\n for (const { key, config } of projects) {\n if (config.name === nameOrPath || config.path === resolve(nameOrPath)) {\n unregisterProject(key);\n console.log(chalk.green(`✓ Removed project: ${config.name}`));\n return;\n }\n }\n\n console.log(chalk.red(`Project not found: ${nameOrPath}`));\n console.log(chalk.dim(`Use 'pan project list' to see registered projects.`));\n}\n\nexport async function projectInitCommand(): Promise<void> {\n if (existsSync(PROJECTS_CONFIG_FILE)) {\n console.log(chalk.yellow(`Config already exists: ${PROJECTS_CONFIG_FILE}`));\n return;\n }\n\n initializeProjectsConfig();\n\n console.log(chalk.green('✓ Projects config initialized'));\n console.log('');\n console.log(chalk.dim(`Edit ${PROJECTS_CONFIG_FILE} to add your projects.`));\n console.log('');\n console.log(chalk.bold('Quick start:'));\n console.log(\n chalk.dim(\n ' pan project add /path/to/project --name \"My Project\" --linear-team MIN'\n )\n );\n}\n\nexport async function projectShowCommand(keyOrName: string): Promise<void> {\n const projects = listProjects();\n\n // Find by key or name\n let found = getProject(keyOrName);\n let foundKey = keyOrName;\n\n if (!found) {\n for (const { key, config } of projects) {\n if (config.name.toLowerCase() === keyOrName.toLowerCase()) {\n found = config;\n foundKey = key;\n break;\n }\n }\n }\n\n if (!found) {\n console.error(chalk.red(`Project not found: ${keyOrName}`));\n console.log(chalk.dim(`Use 'pan project list' to see registered projects.`));\n process.exit(1);\n }\n\n const pathExists = existsSync(found.path);\n const pathStatus = pathExists ? chalk.green('✓') : chalk.red('✗');\n\n console.log(chalk.bold(`\\nProject: ${foundKey}\\n`));\n console.log(` Name: ${found.name}`);\n console.log(` Path: ${pathStatus} ${found.path}`);\n if (found.linear_team) {\n console.log(` Team: ${found.linear_team}`);\n }\n\n if (found.issue_routing && found.issue_routing.length > 0) {\n console.log('\\n ' + chalk.bold('Routing Rules:'));\n for (const rule of found.issue_routing) {\n if (rule.labels) {\n console.log(` Labels: ${rule.labels.join(', ')}`);\n console.log(` → ${rule.path}`);\n } else if (rule.default) {\n console.log(` Default:`);\n console.log(` → ${rule.path}`);\n }\n }\n }\n\n console.log('');\n}\n","import chalk from 'chalk';\nimport { existsSync, readdirSync, readFileSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport {\n PANOPTICON_HOME,\n SKILLS_DIR,\n COMMANDS_DIR,\n AGENTS_DIR,\n CLAUDE_DIR,\n} from '../../lib/paths.js';\n\ninterface CheckResult {\n name: string;\n status: 'ok' | 'warn' | 'error';\n message: string;\n fix?: string;\n}\n\nfunction checkCommand(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { encoding: 'utf-8', stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction checkDirectory(path: string): boolean {\n return existsSync(path);\n}\n\nfunction countItems(path: string): number {\n if (!existsSync(path)) return 0;\n try {\n return readdirSync(path).length;\n } catch {\n return 0;\n }\n}\n\nexport async function doctorCommand(): Promise<void> {\n console.log(chalk.bold('\\nPanopticon Doctor\\n'));\n console.log(chalk.dim('Checking system health...\\n'));\n\n const checks: CheckResult[] = [];\n\n // Check required commands\n const requiredCommands = [\n { cmd: 'git', name: 'Git', fix: 'Install git' },\n { cmd: 'tmux', name: 'tmux', fix: 'Install tmux: apt install tmux / brew install tmux' },\n { cmd: 'node', name: 'Node.js', fix: 'Install Node.js 18+' },\n { cmd: 'claude', name: 'Claude CLI', fix: 'Install: npm install -g @anthropic-ai/claude-code' },\n ];\n\n for (const { cmd, name, fix } of requiredCommands) {\n if (checkCommand(cmd)) {\n checks.push({ name, status: 'ok', message: 'Installed' });\n } else {\n checks.push({ name, status: 'error', message: 'Not found', fix });\n }\n }\n\n // Check optional commands\n const optionalCommands = [\n { cmd: 'gh', name: 'GitHub CLI', fix: 'Install: gh auth login' },\n { cmd: 'bd', name: 'Beads CLI', fix: 'Install beads for task tracking' },\n { cmd: 'docker', name: 'Docker', fix: 'Install Docker for workspace containers' },\n ];\n\n for (const { cmd, name, fix } of optionalCommands) {\n if (checkCommand(cmd)) {\n checks.push({ name, status: 'ok', message: 'Installed' });\n } else {\n checks.push({ name, status: 'warn', message: 'Not installed (optional)', fix });\n }\n }\n\n // Check Panopticon directories\n const directories = [\n { path: PANOPTICON_HOME, name: 'Panopticon Home', fix: 'Run: pan init' },\n { path: SKILLS_DIR, name: 'Skills Directory', fix: 'Run: pan init' },\n { path: COMMANDS_DIR, name: 'Commands Directory', fix: 'Run: pan init' },\n { path: AGENTS_DIR, name: 'Agents Directory', fix: 'Run: pan init' },\n ];\n\n for (const { path, name, fix } of directories) {\n if (checkDirectory(path)) {\n const count = countItems(path);\n checks.push({ name, status: 'ok', message: `Exists (${count} items)` });\n } else {\n checks.push({ name, status: 'error', message: 'Missing', fix });\n }\n }\n\n // Check Claude Code integration\n if (checkDirectory(CLAUDE_DIR)) {\n const skillsCount = countItems(join(CLAUDE_DIR, 'skills'));\n const commandsCount = countItems(join(CLAUDE_DIR, 'commands'));\n checks.push({\n name: 'Claude Code Skills',\n status: skillsCount > 0 ? 'ok' : 'warn',\n message: `${skillsCount} skills`,\n fix: skillsCount === 0 ? 'Run: pan sync' : undefined,\n });\n checks.push({\n name: 'Claude Code Commands',\n status: commandsCount > 0 ? 'ok' : 'warn',\n message: `${commandsCount} commands`,\n fix: commandsCount === 0 ? 'Run: pan sync' : undefined,\n });\n } else {\n checks.push({\n name: 'Claude Code Directory',\n status: 'warn',\n message: 'Not found',\n fix: 'Install Claude Code first',\n });\n }\n\n // Check environment variables\n const envFile = join(homedir(), '.panopticon.env');\n if (existsSync(envFile)) {\n checks.push({ name: 'Config File', status: 'ok', message: '~/.panopticon.env exists' });\n } else {\n checks.push({\n name: 'Config File',\n status: 'warn',\n message: '~/.panopticon.env not found',\n fix: 'Create ~/.panopticon.env with LINEAR_API_KEY=...',\n });\n }\n\n // Check for LINEAR_API_KEY\n if (process.env.LINEAR_API_KEY) {\n checks.push({ name: 'LINEAR_API_KEY', status: 'ok', message: 'Set in environment' });\n } else if (existsSync(envFile)) {\n const content = readFileSync(envFile, 'utf-8');\n if (content.includes('LINEAR_API_KEY')) {\n checks.push({ name: 'LINEAR_API_KEY', status: 'ok', message: 'Set in config file' });\n } else {\n checks.push({\n name: 'LINEAR_API_KEY',\n status: 'warn',\n message: 'Not configured',\n fix: 'Add LINEAR_API_KEY to ~/.panopticon.env',\n });\n }\n } else {\n checks.push({\n name: 'LINEAR_API_KEY',\n status: 'warn',\n message: 'Not configured',\n fix: 'Set LINEAR_API_KEY environment variable or add to ~/.panopticon.env',\n });\n }\n\n // Check tmux sessions\n try {\n const sessions = execSync('tmux list-sessions 2>/dev/null || true', { encoding: 'utf-8' });\n const agentSessions = sessions.split('\\n').filter((s) => s.includes('agent-')).length;\n checks.push({\n name: 'Running Agents',\n status: 'ok',\n message: `${agentSessions} agent sessions`,\n });\n } catch {\n checks.push({\n name: 'Running Agents',\n status: 'ok',\n message: '0 agent sessions',\n });\n }\n\n // Print results\n const icons = {\n ok: chalk.green('\\u2713'),\n warn: chalk.yellow('\\u26a0'),\n error: chalk.red('\\u2717'),\n };\n\n let hasErrors = false;\n let hasWarnings = false;\n\n for (const check of checks) {\n const icon = icons[check.status];\n const message = check.status === 'error' ? chalk.red(check.message) :\n check.status === 'warn' ? chalk.yellow(check.message) :\n chalk.dim(check.message);\n\n console.log(`${icon} ${check.name}: ${message}`);\n\n if (check.fix && check.status !== 'ok') {\n console.log(chalk.dim(` Fix: ${check.fix}`));\n }\n\n if (check.status === 'error') hasErrors = true;\n if (check.status === 'warn') hasWarnings = true;\n }\n\n console.log('');\n\n if (hasErrors) {\n console.log(chalk.red('Some required components are missing.'));\n console.log(chalk.dim('Fix the errors above before using Panopticon.'));\n } else if (hasWarnings) {\n console.log(chalk.yellow('System is functional with some optional features missing.'));\n } else {\n console.log(chalk.green('All systems operational!'));\n }\n console.log('');\n}\n","/**\n * pan update - Update Panopticon to latest version\n */\n\nimport { execSync } from 'child_process';\nimport chalk from 'chalk';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { loadConfig } from '../../lib/config.js';\nimport { syncCommand } from './sync.js';\n\n// Get current installed version\nfunction getCurrentVersion(): string {\n try {\n // Navigate from this file to package.json\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const pkgPath = join(__dirname, '..', '..', '..', 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version;\n } catch {\n return 'unknown';\n }\n}\n\n// Get latest version from npm\nasync function getLatestVersion(): Promise<string> {\n try {\n const result = execSync('npm view panopticon-cli version', {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return result.trim();\n } catch {\n throw new Error('Failed to check npm for latest version');\n }\n}\n\n// Compare semver versions\nfunction isNewer(latest: string, current: string): boolean {\n const parseVersion = (v: string) => {\n const parts = v.replace(/^v/, '').split('.');\n return {\n major: parseInt(parts[0] || '0', 10),\n minor: parseInt(parts[1] || '0', 10),\n patch: parseInt(parts[2] || '0', 10),\n };\n };\n\n const l = parseVersion(latest);\n const c = parseVersion(current);\n\n if (l.major !== c.major) return l.major > c.major;\n if (l.minor !== c.minor) return l.minor > c.minor;\n return l.patch > c.patch;\n}\n\nexport async function updateCommand(options: {\n check?: boolean;\n force?: boolean;\n}) {\n console.log(chalk.bold('Panopticon Update\\n'));\n\n const currentVersion = getCurrentVersion();\n console.log(`Current version: ${chalk.cyan(currentVersion)}`);\n\n let latestVersion: string;\n try {\n console.log(chalk.dim('Checking npm for latest version...'));\n latestVersion = await getLatestVersion();\n console.log(`Latest version: ${chalk.cyan(latestVersion)}`);\n } catch (error) {\n console.error(chalk.red('Failed to check for updates'));\n console.error(chalk.dim('Make sure you have internet connectivity'));\n process.exit(1);\n }\n\n const needsUpdate = isNewer(latestVersion, currentVersion);\n\n if (!needsUpdate) {\n console.log(chalk.green('\\n✓ You are on the latest version'));\n return;\n }\n\n console.log(\n chalk.yellow(`\\n↑ Update available: ${currentVersion} → ${latestVersion}`)\n );\n\n if (options.check) {\n console.log(chalk.dim('\\nRun `pan update` to install'));\n return;\n }\n\n // Perform the update\n console.log(chalk.dim('\\nUpdating Panopticon...'));\n\n try {\n execSync('npm install -g panopticon-cli@latest', {\n stdio: 'inherit',\n });\n\n console.log(chalk.green(`\\n✓ Updated to ${latestVersion}`));\n\n // Auto-sync if enabled\n const config = loadConfig();\n if (config.sync.auto_sync) {\n console.log(chalk.dim('\\nRunning auto-sync...'));\n await syncCommand({});\n }\n\n console.log(chalk.dim('\\nRestart any running agents to use the new version.'));\n } catch (error) {\n console.error(chalk.red('\\nUpdate failed'));\n console.error(\n chalk.dim('Try running with sudo: sudo npm install -g panopticon-cli@latest')\n );\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["chalk","chalk","ora","chalk","spinner","ora","backup","chalk","ora","chalk","backup","ora","chalk","chalk","backup","readdirSync","existsSync","join","chalk","existsSync","readdirSync","join","chalk","chalk","ora","existsSync","readFileSync","join","dirname","existsSync","mkdirSync","writeFileSync","readFileSync","readdirSync","join","execSync","existsSync","mkdirSync","readFileSync","writeFileSync","readdirSync","join","join","mkdirSync","existsSync","writeFileSync","readFileSync","readdirSync","existsSync","mkdirSync","readFileSync","writeFileSync","readdirSync","join","join","existsSync","readFileSync","mkdirSync","writeFileSync","existsSync","readdirSync","join","existsSync","readFileSync","mkdirSync","writeFileSync","execSync","readdirSync","join","existsSync","dirname","readFileSync","ora","chalk","planningContext","beadsTasks","chalk","chalk","chalk","chalk","chalk","isRunning","chalk","chalk","existsSync","readFileSync","join","chalk","join","existsSync","readFileSync","chalk","ora","existsSync","writeFileSync","readFileSync","join","homedir","execSync","join","homedir","existsSync","readFileSync","execSync","chalk","ora","writeFileSync","chalk","ora","inquirer","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","homedir","execSync","getLinearApiKey","project","chalk","ora","chalk","ora","chalk","ora","readFileSync","writeFileSync","existsSync","mkdirSync","join","homedir","getTrackerConfig","join","homedir","existsSync","readFileSync","mkdirSync","writeFileSync","ora","chalk","secondaryTracker","chalk","chalk","chalk","ora","ora","chalk","agentId","chalk","chalk","chalk","existsSync","mkdirSync","readFileSync","writeFileSync","readdirSync","join","join","existsSync","readFileSync","mkdirSync","writeFileSync","join","mkdirSync","existsSync","writeFileSync","readdirSync","readFileSync","join","existsSync","readdirSync","join","readFileSync","readFileSync","existsSync","chalk","chalk","existsSync","mkdirSync","readFileSync","writeFileSync","join","execSync","join","existsSync","readFileSync","mkdirSync","writeFileSync","execSync","execSync","existsSync","readdirSync","resolve","chalk","program","chalk","ora","existsSync","mkdirSync","writeFileSync","join","basename","execSync","mkdirSync","dirname","readFileSync","existsSync","readdirSync","join","existsSync","readFileSync","join","readdirSync","existsSync","readdirSync","mkdirSync","appendFileSync","join","execSync","execSync","join","mkdirSync","existsSync","readdirSync","appendFileSync","program","listCommand","ora","join","chalk","existsSync","writeFileSync","mkdirSync","listProjects","worktrees","workspaces","basename","chalk","ora","execSync","existsSync","mkdirSync","readFileSync","readdirSync","join","homedir","program","readFileSync","existsSync","mkdirSync","readdirSync","join","execSync","homedir","chalk","ora","plat","chalk","readFileSync","writeFileSync","existsSync","mkdirSync","join","join","existsSync","mkdirSync","readFileSync","writeFileSync","getAgentHealth","isRunning","join","existsSync","mkdirSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","existsSync","mkdirSync","readdirSync","unlinkSync","join","basename","execSync","existsSync","readFileSync","readdirSync","statSync","join","basename","homedir","join","join","join","homedir","existsSync","readdirSync","statSync","existsSync","readFileSync","model","basename","join","existsSync","mkdirSync","readFileSync","writeFileSync","execSync","execSync","resolve","existsSync","readFileSync","statSync","mkdirSync","writeFileSync","join","homedir","CLAUDE_PROJECTS_DIR","join","homedir","existsSync","readFileSync","statSync","mkdirSync","writeFileSync","existsSync","join","execSync","execSync","join","existsSync","writeFileSync","mkdirSync","join","existsSync","readFileSync","join","execSync","join","mkdirSync","writeFileSync","resolve","existsSync","mkdirSync","appendFileSync","readFileSync","join","join","existsSync","mkdirSync","appendFileSync","getAgentHealth","needsAttention","statusCommand","chalk","chalk","chalk","chalk","chalk","program","statusCommand","chalk","readFileSync","writeFileSync","existsSync","mkdirSync","copyFileSync","chmodSync","join","execSync","homedir","platform","fileURLToPath","dirname","__dirname","program","chalk","existsSync","readFileSync","join","existsSync","chalk","join","readFileSync","chalk","existsSync","readdirSync","readFileSync","execSync","homedir","join","checkCommand","execSync","existsSync","readdirSync","chalk","join","homedir","readFileSync","execSync","chalk","readFileSync","fileURLToPath","dirname","join","__filename","fileURLToPath","__dirname","dirname","join","readFileSync","execSync","chalk","execSync","join","dirname","fileURLToPath","readFileSync","existsSync","parse","__dirname","chalk"]}