titan-agent 5.4.0 → 5.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agent.js +1 -1
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/agentLoop.js +77 -12
- package/dist/agent/agentLoop.js.map +1 -1
- package/dist/agent/agentWakeup.js +8 -3
- package/dist/agent/agentWakeup.js.map +1 -1
- package/dist/agent/commandPost.js +6 -1
- package/dist/agent/commandPost.js.map +1 -1
- package/dist/agent/heartbeatScheduler.js +36 -4
- package/dist/agent/heartbeatScheduler.js.map +1 -1
- package/dist/agent/toolRunner.js +30 -0
- package/dist/agent/toolRunner.js.map +1 -1
- package/dist/config/config.js +30 -8
- package/dist/config/config.js.map +1 -1
- package/dist/config/schema.js +10 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/eval/record.js +1 -1
- package/dist/eval/record.js.map +1 -1
- package/dist/gateway/server.js +26 -0
- package/dist/gateway/server.js.map +1 -1
- package/dist/mesh/transport.js +60 -8
- package/dist/mesh/transport.js.map +1 -1
- package/dist/providers/anthropic.js +3 -2
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/base.js.map +1 -1
- package/dist/providers/google.js +94 -20
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/modelCapabilities.js +59 -0
- package/dist/providers/modelCapabilities.js.map +1 -0
- package/dist/providers/ollama.js +3 -2
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.js +4 -3
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openai_compat.js +3 -2
- package/dist/providers/openai_compat.js.map +1 -1
- package/dist/providers/router.js +63 -21
- package/dist/providers/router.js.map +1 -1
- package/dist/skills/registry.js +176 -163
- package/dist/skills/registry.js.map +1 -1
- package/dist/telemetry/activityLog.js +1 -1
- package/dist/telemetry/activityLog.js.map +1 -1
- package/dist/utils/constants.js +2 -2
- package/dist/utils/constants.js.map +1 -1
- package/docs/AGENT-HIERARCHY.md +154 -0
- package/docs/superpowers/plans/2026-04-29-titan-production-fix.md +241 -0
- package/package.json +2 -2
- package/scripts/start-workers.sh +39 -0
- package/scripts/task-feeder.ts +38 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/agent/commandPost.ts"],"sourcesContent":["/**\n * TITAN — Command Post\n * Agent governance layer inspired by Paperclip (paperclipai/paperclip).\n * Provides: atomic task checkout, budget enforcement, goal ancestry,\n * agent registry with heartbeats, and real-time activity feed.\n *\n * Additive layer — wraps existing goals, multi-agent, and cost systems.\n * Gated behind config.commandPost.enabled (defaults false).\n */\nimport { v4 as uuid } from 'uuid';\nimport { existsSync, readFileSync, writeFileSync, appendFileSync } from 'fs';\nimport { spawn } from 'child_process';\nimport { join } from 'path';\nimport { TITAN_HOME } from '../utils/constants.js';\nimport { ensureDir } from '../utils/helpers.js';\nimport { titanEvents } from './daemon.js';\nimport { spawnAgent, stopAgent, listAgents, type AgentInstance } from './multiAgent.js';\nimport { listGoals, type Goal } from './goals.js';\nimport logger from '../utils/logger.js';\nimport type { CommandPostConfig } from '../config/schema.js';\nimport { loadConfig } from '../config/config.js';\nimport { shouldAutoApprove, type ApprovalRule } from './approvalClassifier.js';\n\nconst COMPONENT = 'CommandPost';\nconst STATE_PATH = join(TITAN_HOME, 'command-post.json');\nconst ACTIVITY_PATH = join(TITAN_HOME, 'command-post-activity.jsonl');\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface TaskCheckout {\n subtaskId: string;\n goalId: string;\n agentId: string;\n runId: string;\n checkedOutAt: string;\n expiresAt: string;\n status: 'locked' | 'released' | 'expired';\n}\n\nexport interface BudgetPolicy {\n id: string;\n name: string;\n scope: { type: 'agent' | 'goal' | 'global'; targetId?: string };\n period: 'daily' | 'weekly' | 'monthly';\n limitUsd: number;\n warningThresholdPercent: number;\n action: 'warn' | 'pause' | 'stop';\n currentSpend: number;\n periodStart: string;\n enabled: boolean;\n}\n\nexport interface RegisteredAgent {\n id: string;\n name: string;\n model: string;\n status: 'active' | 'idle' | 'paused' | 'error' | 'stopped';\n lastHeartbeat: string;\n currentTaskId?: string;\n totalTasksCompleted: number;\n totalCostUsd: number;\n createdAt: string;\n // Paperclip org chart fields\n reportsTo?: string;\n role: 'ceo' | 'manager' | 'engineer' | 'researcher' | 'general';\n title?: string;\n /** TITAN identity fields (F2). Optional — absent = fall back to global config.\n * When set, they give the agent a continuous personality across restarts. */\n /** F5-TTS voice clone name (e.g. 'andrew', 'leah', 'jess'). Falls back to config.voice.ttsVoice. */\n voiceId?: string;\n /** Persona file stem from assets/personas/. Falls back to config.agent.persona. */\n personaId?: string;\n /** Extra text prepended to the system prompt when this agent runs. */\n systemPromptOverride?: string;\n /** Hindsight memory network key. Defaults to `agent:${id}`. */\n memoryNamespace?: string;\n /** 1-3 sentence self-description. Seed for future relationship memory. */\n characterSummary?: string;\n /** Sub-agent template this agent was hired with (e.g. 'explorer', 'coder') */\n template?: string;\n}\n\nexport interface ActivityEntry {\n id: string;\n timestamp: string;\n type: 'task_checkout' | 'task_checkin' | 'task_expired' | 'budget_warning' |\n 'budget_exceeded' | 'agent_heartbeat' | 'agent_status_change' |\n 'goal_created' | 'goal_completed' | 'goal_proposal_requested' | 'goal_proposal_rejected' |\n 'autopilot_run' | 'tool_execution' | 'error' | 'issue_deleted' | 'system';\n agentId?: string;\n goalId?: string;\n message: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GoalTreeNode {\n goal: Goal;\n children: GoalTreeNode[];\n depth: number;\n}\n\n// ─── Paperclip: Issue/Ticket System ──────────────────────────────────────\n\nexport interface CPIssue {\n id: string;\n title: string;\n description: string;\n status: 'backlog' | 'todo' | 'in_progress' | 'in_review' | 'done' | 'blocked' | 'cancelled';\n priority: 'critical' | 'high' | 'medium' | 'low';\n assigneeAgentId?: string;\n createdByAgentId?: string;\n createdByUser?: string;\n goalId?: string;\n parentId?: string;\n checkoutRunId?: string;\n issueNumber: number;\n identifier: string; // e.g. \"TIT-42\"\n createdAt: string;\n updatedAt: string;\n startedAt?: string;\n completedAt?: string;\n}\n\nexport interface CPComment {\n id: string;\n issueId: string;\n authorAgentId?: string;\n authorUser?: string;\n body: string;\n createdAt: string;\n}\n\n// ─── Paperclip: Approval System ──────────────────────────────────────────\n\nexport interface CPApproval {\n id: string;\n type: 'hire_agent' | 'budget_override' | 'goal_proposal' | 'soma_proposal' | 'custom';\n status: 'pending' | 'approved' | 'rejected';\n requestedBy: string;\n payload: Record<string, unknown>;\n decidedBy?: string;\n decidedAt?: string;\n decisionNote?: string;\n linkedIssueIds: string[];\n createdAt: string;\n /** Threaded conversation between agent and user */\n thread?: CPComment[];\n /** If set, approval is snoozed until this ISO timestamp */\n snoozedUntil?: string;\n}\n\n// ─── Paperclip: Run Tracking ─────────────────────────────────────────────\n\nexport interface CPRun {\n id: string;\n agentId: string;\n source: 'heartbeat' | 'assignment' | 'manual' | 'autopilot';\n status: 'running' | 'succeeded' | 'failed' | 'error';\n issueId?: string;\n startedAt: string;\n finishedAt?: string;\n durationMs?: number;\n toolsUsed: string[];\n tokenUsage?: { prompt: number; completion: number };\n error?: string;\n}\n\n// ─── Paperclip: Org Tree Node ────────────────────────────────────────────\n\nexport interface OrgNode {\n id: string;\n name: string;\n role: string;\n title?: string;\n status: string;\n model: string;\n reports: OrgNode[];\n}\n\ninterface CommandPostState {\n checkouts: TaskCheckout[];\n budgetPolicies: BudgetPolicy[];\n agents: RegisteredAgent[];\n issues: CPIssue[];\n approvals: CPApproval[];\n runs: CPRun[];\n comments: CPComment[];\n issueCounter: number;\n lastSaved: string;\n}\n\n// ─── State ────────────────────────────────────────────────────────────────\n\nconst checkouts = new Map<string, TaskCheckout>();\nlet budgetPolicies: BudgetPolicy[] = [];\nconst registeredAgents = new Map<string, RegisteredAgent>();\nconst activityBuffer: ActivityEntry[] = [];\nconst issues = new Map<string, CPIssue>();\nconst comments: CPComment[] = [];\nconst approvals = new Map<string, CPApproval>();\nconst runs: CPRun[] = [];\nlet issueCounter = 0;\nlet config: CommandPostConfig | null = null;\nlet sweepInterval: ReturnType<typeof setInterval> | null = null;\nlet heartbeatInterval: ReturnType<typeof setInterval> | null = null;\nlet initialized = false;\nconst eventListeners: Array<{ event: string; handler: (...args: unknown[]) => void }> = [];\n\n// ─── Persistence ──────────────────────────────────────────────────────────\n\nfunction loadState(): void {\n if (!existsSync(STATE_PATH)) return;\n try {\n const raw = readFileSync(STATE_PATH, 'utf-8');\n const state = JSON.parse(raw) as CommandPostState;\n for (const c of state.checkouts || []) {\n if (c.status === 'locked') checkouts.set(c.subtaskId, c);\n }\n budgetPolicies = state.budgetPolicies || [];\n for (const a of state.agents || []) {\n if (!a.role) a.role = 'general'; // backcompat\n registeredAgents.set(a.id, a);\n }\n for (const i of state.issues || []) issues.set(i.id, i);\n for (const a of state.approvals || []) approvals.set(a.id, a);\n runs.push(...(state.runs || []).slice(-200)); // keep last 200 runs\n comments.push(...(state.comments || []));\n issueCounter = state.issueCounter || (state.issues?.length || 0);\n } catch (err) {\n logger.warn(COMPONENT, `Failed to load state: ${(err as Error).message}`);\n }\n}\n\nfunction saveState(): void {\n try {\n ensureDir(TITAN_HOME);\n const state: CommandPostState = {\n checkouts: Array.from(checkouts.values()),\n budgetPolicies,\n agents: Array.from(registeredAgents.values()),\n issues: Array.from(issues.values()),\n approvals: Array.from(approvals.values()),\n runs: runs.slice(-200),\n comments,\n issueCounter,\n lastSaved: new Date().toISOString(),\n };\n writeFileSync(STATE_PATH, JSON.stringify(state, null, 2), 'utf-8');\n } catch (err) {\n logger.error(COMPONENT, `Failed to save state: ${(err as Error).message}`);\n }\n}\n\n// ─── Activity Feed ────────────────────────────────────────────────────────\n\nfunction addActivity(entry: Omit<ActivityEntry, 'id' | 'timestamp'>): void {\n const full: ActivityEntry = {\n id: uuid().slice(0, 12),\n timestamp: new Date().toISOString(),\n ...entry,\n };\n const bufferSize = config?.activityBufferSize ?? 500;\n activityBuffer.push(full);\n if (activityBuffer.length > bufferSize) activityBuffer.shift();\n\n // Append to JSONL file\n try {\n appendFileSync(ACTIVITY_PATH, JSON.stringify(full) + '\\n', 'utf-8');\n } catch { /* non-critical */ }\n\n titanEvents.emit('commandpost:activity', full);\n}\n\nexport function getActivity(opts?: { limit?: number; type?: string }): ActivityEntry[] {\n let entries = [...activityBuffer];\n if (opts?.type) entries = entries.filter(e => e.type === opts.type);\n if (opts?.limit) entries = entries.slice(-opts.limit);\n return entries;\n}\n\n// ─── Task Checkout (Atomic Locking) ──────────────────────────────────────\n\n/**\n * Gap 3 (plan-this-logical-ocean): stale-lock adoption threshold.\n * If the lock-holding agent hasn't heartbeat in this long, a different agent\n * is allowed to adopt the lock instead of being blocked by it. Default 5 min\n * picks up abandoned runs quickly without stealing from agents that are just\n * doing long work (checkoutTimeoutMs default is 30 min — sweep handles those).\n */\nconst STALE_LOCK_ADOPTION_MS = 5 * 60 * 1000;\n\nexport function checkoutTask(goalId: string, subtaskId: string, agentId: string): TaskCheckout | null {\n // Atomic: single-threaded Node.js event loop = synchronous check-and-lock\n const existing = checkouts.get(subtaskId);\n if (existing && existing.status === 'locked') {\n // Same agent re-checking out — adopt (Paperclip dual-run pattern)\n if (existing.agentId === agentId) {\n existing.checkedOutAt = new Date().toISOString();\n existing.expiresAt = new Date(Date.now() + (config?.checkoutTimeoutMs ?? 1800000)).toISOString();\n saveState();\n return existing;\n }\n // Gap 3: different agent — check if the lock-holder is stale.\n // Previously we returned null here, which meant a crashed agent\n // would zombie the subtask for up to checkoutTimeoutMs (30 min)\n // before the sweep cleared it. Now, if the lock-holder's heartbeat\n // is older than STALE_LOCK_ADOPTION_MS, let the new agent take\n // over with a fresh runId. If the holder is not in the agent\n // registry at all (never heartbeat, possibly a test caller or an\n // old persisted checkout), we conservatively treat them as STILL\n // HOLDING — the sweep will clean the lock up after checkoutTimeoutMs.\n // This preserves the existing safety invariant that two different\n // agents can't hold the same subtask simultaneously.\n const holder = registeredAgents.get(existing.agentId);\n if (!holder) return null;\n const holderLastBeat = new Date(holder.lastHeartbeat).getTime();\n const holderStale = Date.now() - holderLastBeat > STALE_LOCK_ADOPTION_MS;\n if (!holderStale) return null;\n\n const adopted: TaskCheckout = {\n ...existing,\n agentId,\n runId: uuid().slice(0, 8),\n checkedOutAt: new Date().toISOString(),\n expiresAt: new Date(Date.now() + (config?.checkoutTimeoutMs ?? 1800000)).toISOString(),\n status: 'locked',\n };\n checkouts.set(subtaskId, adopted);\n saveState();\n addActivity({\n type: 'task_checkout',\n agentId,\n goalId,\n message: `Agent \"${agentId}\" adopted stale lock on ${subtaskId} (prev holder \"${existing.agentId}\" heartbeat ${holder ? Math.round((Date.now() - holderLastBeat) / 1000) + 's ago' : 'missing'})`,\n metadata: { runId: adopted.runId, adoptedFrom: existing.agentId, previousRunId: existing.runId },\n });\n titanEvents.emit('commandpost:task:checkout', adopted);\n return adopted;\n }\n\n const checkout: TaskCheckout = {\n subtaskId,\n goalId,\n agentId,\n runId: uuid().slice(0, 8),\n checkedOutAt: new Date().toISOString(),\n expiresAt: new Date(Date.now() + (config?.checkoutTimeoutMs ?? 1800000)).toISOString(),\n status: 'locked',\n };\n\n checkouts.set(subtaskId, checkout);\n saveState();\n\n addActivity({\n type: 'task_checkout',\n agentId,\n goalId,\n message: `Agent \"${agentId}\" checked out subtask ${subtaskId}`,\n metadata: { runId: checkout.runId },\n });\n\n titanEvents.emit('commandpost:task:checkout', checkout);\n return checkout;\n}\n\nexport function checkinTask(subtaskId: string, runId: string): boolean {\n const checkout = checkouts.get(subtaskId);\n if (!checkout || checkout.runId !== runId) return false;\n\n checkout.status = 'released';\n checkouts.delete(subtaskId);\n saveState();\n\n addActivity({\n type: 'task_checkin',\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n message: `Agent \"${checkout.agentId}\" released subtask ${subtaskId}`,\n });\n\n titanEvents.emit('commandpost:task:checkin', { subtaskId, runId });\n return true;\n}\n\nexport function getActiveCheckouts(): TaskCheckout[] {\n return Array.from(checkouts.values()).filter(c => c.status === 'locked');\n}\n\n/** Get a specific task checkout by subtask ID (for taskQueue lock status). */\nexport function getCheckout(subtaskId: string): TaskCheckout | undefined {\n return checkouts.get(subtaskId);\n}\n\nfunction sweepExpiredCheckouts(): void {\n const now = Date.now();\n for (const [id, checkout] of checkouts) {\n if (checkout.status === 'locked' && new Date(checkout.expiresAt).getTime() < now) {\n checkout.status = 'expired';\n checkouts.delete(id);\n\n addActivity({\n type: 'task_expired',\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n message: `Checkout expired for subtask ${id} (agent: ${checkout.agentId})`,\n });\n\n titanEvents.emit('commandpost:task:expired', { subtaskId: id, agentId: checkout.agentId });\n }\n }\n saveState();\n}\n\n/** Auto-purge stale approvals older than configured retention days */\nfunction sweepStaleApprovals(): void {\n const cfg = loadConfig();\n const retentionDays = Number((cfg as Record<string, unknown>).approvalRetentionDays ?? 7);\n if (retentionDays <= 0) return;\n const cutoff = Date.now() - retentionDays * 86400000;\n let purged = 0;\n for (const [id, approval] of approvals) {\n const age = new Date(approval.createdAt).getTime();\n if (age < cutoff) {\n approvals.delete(id);\n purged++;\n }\n }\n if (purged > 0) {\n saveState();\n logger.info(COMPONENT, `Auto-purged ${purged} stale approval(s) older than ${retentionDays} days`);\n addActivity({\n type: 'issue_deleted',\n message: `Auto-purged ${purged} stale approval(s) older than ${retentionDays} days`,\n metadata: { purged, retentionDays },\n });\n }\n}\n\n/** v5.0.0: Auto-reject ancient pending approvals (> 3 days) so the queue\n * doesn't stall forever on items the user will never see. */\nfunction sweepAncientPendingApprovals(): void {\n const PENDING_MAX_AGE_MS = 3 * 24 * 60 * 60 * 1000; // 3 days\n const cutoff = Date.now() - PENDING_MAX_AGE_MS;\n let rejected = 0;\n for (const [id, approval] of approvals) {\n if (approval.status !== 'pending') continue;\n const age = new Date(approval.createdAt).getTime();\n if (age < cutoff) {\n approval.status = 'rejected';\n approval.decidedBy = 'auto:sweep';\n approval.decidedAt = new Date().toISOString();\n approval.decisionNote = 'Auto-rejected after 3 days in pending queue';\n rejected++;\n }\n }\n if (rejected > 0) {\n saveState();\n logger.info(COMPONENT, `Auto-rejected ${rejected} ancient pending approval(s)`);\n addActivity({\n type: 'goal_proposal_rejected',\n message: `Auto-rejected ${rejected} pending approval(s) older than 3 days`,\n metadata: { rejected },\n });\n }\n}\n\n/** Manual sweep entrypoint for API/admin use */\nexport function sweepStaleApprovalsManual(): { purged: number; retentionDays: number } {\n const before = approvals.size;\n sweepStaleApprovals();\n const purged = before - approvals.size;\n const cfg = loadConfig();\n const retentionDays = Number((cfg as Record<string, unknown>).approvalRetentionDays ?? 7);\n return { purged, retentionDays };\n}\n\n// ─── Budget Policies ─────────────────────────────────────────────────────\n\nexport function createBudgetPolicy(opts: Omit<BudgetPolicy, 'id' | 'currentSpend' | 'periodStart'>): BudgetPolicy {\n const policy: BudgetPolicy = {\n id: uuid().slice(0, 8),\n ...opts,\n currentSpend: 0,\n periodStart: new Date().toISOString(),\n };\n budgetPolicies.push(policy);\n saveState();\n logger.info(COMPONENT, `Budget policy created: \"${policy.name}\" (${policy.scope.type}/${policy.scope.targetId || 'all'}) limit=$${policy.limitUsd}`);\n return policy;\n}\n\nexport function updateBudgetPolicy(id: string, updates: Partial<BudgetPolicy>): BudgetPolicy | null {\n const policy = budgetPolicies.find(p => p.id === id);\n if (!policy) return null;\n Object.assign(policy, updates, { id }); // id is immutable\n saveState();\n return policy;\n}\n\nexport function deleteBudgetPolicy(id: string): boolean {\n const idx = budgetPolicies.findIndex(p => p.id === id);\n if (idx === -1) return false;\n budgetPolicies.splice(idx, 1);\n saveState();\n return true;\n}\n\nexport function getBudgetPolicies(): BudgetPolicy[] {\n return [...budgetPolicies];\n}\n\nexport function recordSpend(agentId: string, goalId: string | undefined, amountUsd: number): void {\n for (const policy of budgetPolicies) {\n if (!policy.enabled) continue;\n\n // Check if policy applies\n const applies =\n policy.scope.type === 'global' ||\n (policy.scope.type === 'agent' && policy.scope.targetId === agentId) ||\n (policy.scope.type === 'goal' && policy.scope.targetId === goalId);\n\n if (!applies) continue;\n\n // Reset period if expired\n if (isPeriodExpired(policy)) {\n policy.currentSpend = 0;\n policy.periodStart = new Date().toISOString();\n }\n\n policy.currentSpend += amountUsd;\n const pct = (policy.currentSpend / policy.limitUsd) * 100;\n\n if (pct >= 100 && (policy.action === 'pause' || policy.action === 'stop')) {\n addActivity({\n type: 'budget_exceeded',\n agentId,\n goalId,\n message: `Budget \"${policy.name}\" exceeded: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct, action: policy.action },\n });\n\n // Enforce budget — actually stop or pause the agent\n if (policy.action === 'stop') {\n stopAgent(agentId);\n updateAgentStatus(agentId, 'paused'); // Budget pause (not manual pause)\n } else if (policy.action === 'pause') {\n updateAgentStatus(agentId, 'paused');\n }\n\n titanEvents.emit('commandpost:budget:exceeded', { policyId: policy.id, agentId, goalId, pct, action: policy.action });\n } else if (pct >= policy.warningThresholdPercent) {\n addActivity({\n type: 'budget_warning',\n agentId,\n goalId,\n message: `Budget \"${policy.name}\" at ${pct.toFixed(0)}%: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct },\n });\n titanEvents.emit('commandpost:budget:warning', { policyId: policy.id, agentId, goalId, pct });\n }\n }\n saveState();\n}\n\nfunction isPeriodExpired(policy: BudgetPolicy): boolean {\n const start = new Date(policy.periodStart).getTime();\n const now = Date.now();\n const msPerDay = 86400000;\n switch (policy.period) {\n case 'daily': return now - start > msPerDay;\n case 'weekly': return now - start > msPerDay * 7;\n case 'monthly': return now - start > msPerDay * 30;\n default: return false;\n }\n}\n\n// ─── Goal Ancestry ───────────────────────────────────────────────────────\n\nexport function getAncestryChain(goalId: string): Goal[] {\n const goals = listGoals();\n const chain: Goal[] = [];\n let current = goals.find(g => g.id === goalId);\n const visited = new Set<string>();\n\n while (current) {\n if (visited.has(current.id)) break; // cycle protection\n visited.add(current.id);\n chain.unshift(current); // root first\n if (!current.parentGoalId) break;\n current = goals.find(g => g.id === current!.parentGoalId);\n }\n return chain;\n}\n\n/**\n * Build ancestry context for a goal — returns the full chain plus depth info.\n * Used by UI to render goal hierarchy breadcrumbs.\n */\nexport function buildAncestryContext(goalId: string): {\n chain: Goal[];\n depth: number;\n rootGoal: Goal | null;\n} {\n const chain = getAncestryChain(goalId);\n return {\n chain,\n depth: chain.length,\n rootGoal: chain.length > 0 ? chain[0] : null,\n };\n}\n\n/**\n * Check if setting parentId on a goal would create a cycle in the ancestry tree.\n */\nexport function wouldCreateCycle(goalId: string, parentId: string): boolean {\n if (goalId === parentId) return true;\n const chain = getAncestryChain(parentId);\n return chain.some(g => g.id === goalId);\n}\n\nexport function getGoalTree(): GoalTreeNode[] {\n const goals = listGoals();\n const goalsById = new Map(goals.map(g => [g.id, g]));\n const childrenMap = new Map<string | undefined, Goal[]>();\n\n for (const g of goals) {\n const parentId = g.parentGoalId || undefined;\n if (!childrenMap.has(parentId)) childrenMap.set(parentId, []);\n childrenMap.get(parentId)!.push(g);\n }\n\n function buildTree(parentId: string | undefined, depth: number): GoalTreeNode[] {\n const children = childrenMap.get(parentId) || [];\n return children.map(goal => ({\n goal,\n children: buildTree(goal.id, depth + 1),\n depth,\n }));\n }\n\n return buildTree(undefined, 0);\n}\n\n// ─── Agent Registry ──────────────────────────────────────────────────────\n\n/**\n * Register a new agent in the Command Post registry.\n * Used by the hire approval flow and syncAgentRegistry.\n */\nexport function registerAgent(opts: {\n id?: string;\n name: string;\n role?: string;\n title?: string;\n model?: string;\n template?: string;\n status?: RegisteredAgent['status'];\n}): RegisteredAgent {\n const id = opts.id || `agent-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;\n const agent: RegisteredAgent = {\n id,\n name: opts.name,\n model: opts.model || '',\n status: opts.status || 'active',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: new Date().toISOString(),\n role: (opts.role || 'general') as RegisteredAgent['role'],\n title: opts.title,\n template: opts.template,\n };\n registeredAgents.set(id, agent);\n saveState();\n return agent;\n}\n\nexport function syncAgentRegistry(): void {\n const liveAgents = listAgents();\n for (const agent of liveAgents) {\n if (!registeredAgents.has(agent.id)) {\n // v4.8.4: the default primary agent is CEO-level (orchestrates\n // the whole org). Everyone else defaults to general. Specialists\n // register with their own explicit role via forceRegisterSpecialist.\n const defaultRole: RegisteredAgent['role'] =\n agent.id === 'default' ? 'ceo' : 'general';\n registeredAgents.set(agent.id, {\n id: agent.id,\n name: agent.name,\n model: agent.model,\n status: agent.status === 'running' ? 'active' : agent.status === 'stopped' ? 'stopped' : 'idle',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: agent.createdAt,\n role: defaultRole,\n title: agent.id === 'default' ? 'Primary orchestrator' : undefined,\n });\n } else {\n // Update live status + heal prior mis-tagged CEO role.\n const reg = registeredAgents.get(agent.id)!;\n reg.model = agent.model;\n if (agent.status === 'running') reg.status = 'active';\n else if (agent.status === 'stopped') reg.status = 'stopped';\n // v4.8.4: if `default` is still tagged 'general' from a prior\n // install, upgrade it to 'ceo' (the intended role).\n if (agent.id === 'default' && reg.role === 'general') {\n reg.role = 'ceo';\n if (!reg.title) reg.title = 'Primary orchestrator';\n }\n }\n }\n saveState();\n}\n\n/**\n * v4.7.0: register a specialist with a PINNED stable ID (not the usual\n * auto-generated `agent-xxx`). Used by the specialist bootstrap so Scout,\n * Builder, Writer, Analyst have reliable IDs across restarts.\n * Idempotent — returns existing agent if already registered.\n */\nexport function forceRegisterSpecialist(opts: {\n id: string;\n name: string;\n role: RegisteredAgent['role'];\n title: string;\n model: string;\n reportsTo?: string;\n}): RegisteredAgent {\n const existing = registeredAgents.get(opts.id);\n if (existing) {\n // v4.8.1: heal specialists stuck in 'error' from the v4.7.0 /\n // pre-v4.8.1 stale-heartbeat bug. A specialist that never did work\n // got flagged as errored after 120s, but it should have stayed\n // 'idle'. On boot we reset it to idle so the registry UI is clean.\n // v4.14.0: also heal 'paused' specialists with no task history —\n // they were likely paused by a now-deleted budget policy or manual\n // action and should be available for work.\n const shouldHeal = (existing.status === 'error' || existing.status === 'paused') && (existing.totalTasksCompleted ?? 0) === 0;\n if (shouldHeal) {\n existing.status = 'idle';\n existing.lastHeartbeat = new Date().toISOString();\n saveState();\n }\n return existing;\n }\n const agent: RegisteredAgent = {\n id: opts.id,\n name: opts.name,\n model: opts.model,\n status: 'idle',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: new Date().toISOString(),\n role: opts.role,\n title: opts.title,\n reportsTo: opts.reportsTo,\n };\n registeredAgents.set(opts.id, agent);\n saveState();\n return agent;\n}\n\nexport function reportHeartbeat(agentId: string): boolean {\n const agent = registeredAgents.get(agentId);\n if (!agent) return false;\n agent.lastHeartbeat = new Date().toISOString();\n if (agent.status === 'error') agent.status = 'active';\n saveState();\n titanEvents.emit('commandpost:agent:heartbeat', { agentId, timestamp: agent.lastHeartbeat });\n return true;\n}\n\nexport function updateAgentStatus(agentId: string, status: RegisteredAgent['status']): boolean {\n const agent = registeredAgents.get(agentId);\n if (!agent) return false;\n const prev = agent.status;\n agent.status = status;\n saveState();\n\n addActivity({\n type: 'agent_status_change',\n agentId,\n message: `Agent \"${agent.name}\" status: ${prev} → ${status}`,\n });\n titanEvents.emit('commandpost:agent:status', { agentId, prev, status });\n return true;\n}\n\nexport function removeAgent(agentId: string): boolean {\n if (agentId === 'default') return false; // Never remove the primary agent\n const agent = registeredAgents.get(agentId);\n if (!agent) return false;\n registeredAgents.delete(agentId);\n saveState();\n addActivity({\n type: 'agent_status_change',\n agentId,\n message: `Agent \"${agent.name}\" removed`,\n });\n titanEvents.emit('commandpost:agent:removed', { agentId, name: agent.name });\n return true;\n}\n\nexport function getRegisteredAgents(): RegisteredAgent[] {\n return Array.from(registeredAgents.values());\n}\n\nfunction checkStaleHeartbeats(): void {\n const interval = config?.heartbeatIntervalMs ?? 60000;\n const threshold = interval * 2;\n const now = Date.now();\n\n for (const [id, agent] of registeredAgents) {\n if (agent.status === 'stopped' || agent.status === 'paused') continue;\n // v4.8.1: idle agents that have never been assigned work shouldn't\n // be flagged as error for not heartbeating.\n // v4.10.0-local: BROADENED — specialists (Scout/Builder/Writer/Analyst)\n // don't self-heartbeat; they only beat when running a task. So ANY\n // specialist with `totalTasksCompleted === 0` should be skipped,\n // regardless of status. Previously status='active' + 0 tasks →\n // immediately marked as error, even though that's the normal\n // resting state for a fresh specialist after unpause.\n if ((agent.totalTasksCompleted ?? 0) === 0) continue;\n const lastBeat = new Date(agent.lastHeartbeat).getTime();\n if (now - lastBeat > threshold && agent.status !== 'error') {\n agent.status = 'error';\n addActivity({\n type: 'agent_status_change',\n agentId: id,\n message: `Agent \"${agent.name}\" heartbeat stale — marked as error`,\n });\n titanEvents.emit('commandpost:agent:status', { agentId: id, prev: 'active', status: 'error' });\n }\n }\n // v4.10.0-local: also self-heal specialists currently stuck in 'error'\n // state with zero completed tasks (means they never actually ran — the\n // stale-heartbeat check put them there). Reset to 'idle' so they're\n // ready to pick up new work.\n for (const [, agent] of registeredAgents) {\n if (agent.status === 'error' && (agent.totalTasksCompleted ?? 0) === 0) {\n agent.status = 'idle';\n }\n }\n saveState();\n}\n\n// ─── Dashboard Aggregation ───────────────────────────────────────────────\n\nexport function getDashboard(): {\n activeAgents: number;\n totalAgents: number;\n activeCheckouts: number;\n budgetUtilization: number;\n recentActivity: ActivityEntry[];\n agents: RegisteredAgent[];\n checkouts: TaskCheckout[];\n budgets: BudgetPolicy[];\n goalTree: GoalTreeNode[];\n} {\n // Re-sync with live agents on every dashboard fetch\n syncAgentRegistry();\n const agents = getRegisteredAgents();\n const activeCheckouts = getActiveCheckouts();\n const budgets = getBudgetPolicies();\n\n // Overall budget utilization (average across enabled policies)\n const enabledBudgets = budgets.filter(b => b.enabled);\n const budgetUtilization = enabledBudgets.length > 0\n ? enabledBudgets.reduce((sum, b) => sum + (b.currentSpend / b.limitUsd) * 100, 0) / enabledBudgets.length\n : 0;\n\n return {\n activeAgents: agents.filter(a => a.status === 'active').length,\n totalAgents: agents.length,\n activeCheckouts: activeCheckouts.length,\n budgetUtilization: Math.round(budgetUtilization),\n recentActivity: activityBuffer.slice(-20),\n agents,\n checkouts: activeCheckouts,\n budgets,\n goalTree: getGoalTree(),\n };\n}\n\n// ─── Lifecycle ───────────────────────────────────────────────────────────\n\nexport function initCommandPost(cfg: CommandPostConfig): void {\n if (initialized) return;\n config = cfg;\n ensureDir(TITAN_HOME);\n loadState();\n syncAgentRegistry();\n\n // Start sweepers\n sweepInterval = setInterval(sweepExpiredCheckouts, 60000);\n sweepInterval.unref();\n const approvalSweepInterval = setInterval(() => {\n sweepStaleApprovals();\n sweepAncientPendingApprovals();\n }, 300000); // every 5 min\n approvalSweepInterval.unref();\n heartbeatInterval = setInterval(checkStaleHeartbeats, cfg.heartbeatIntervalMs);\n heartbeatInterval.unref();\n\n // Subscribe to titanEvents for activity feed (track refs for cleanup)\n const onGoalCreated = (data: { goalId: string; title: string; subtasks?: number }) => {\n addActivity({ type: 'goal_created', goalId: data.goalId, message: `Goal created: \"${data.title}\"` });\n };\n const onGoalCompleted = (data: { goalId: string; title: string }) => {\n addActivity({ type: 'goal_completed', goalId: data.goalId, message: `Goal completed: \"${data.title}\"` });\n };\n const onAgentSpawned = (data: { id: string; name: string; model: string }) => {\n registeredAgents.set(data.id, {\n id: data.id,\n name: data.name,\n model: data.model,\n status: 'active',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: new Date().toISOString(),\n role: 'general',\n });\n addActivity({ type: 'agent_status_change', agentId: data.id, message: `Agent \"${data.name}\" spawned` });\n saveState();\n };\n const onAgentStopped = (data: { id: string; name?: string }) => {\n const agent = registeredAgents.get(data.id);\n if (agent) {\n agent.status = 'stopped';\n addActivity({ type: 'agent_status_change', agentId: data.id, message: `Agent \"${agent.name}\" stopped` });\n saveState();\n }\n };\n const onDaemonHeartbeat = () => {\n reportHeartbeat('default');\n };\n\n titanEvents.on('goal:created', onGoalCreated);\n titanEvents.on('goal:completed', onGoalCompleted);\n titanEvents.on('agent:spawned', onAgentSpawned);\n titanEvents.on('agent:stopped', onAgentStopped);\n titanEvents.on('daemon:heartbeat', onDaemonHeartbeat);\n eventListeners.push(\n { event: 'goal:created', handler: onGoalCreated as unknown as (...args: unknown[]) => void },\n { event: 'goal:completed', handler: onGoalCompleted as unknown as (...args: unknown[]) => void },\n { event: 'agent:spawned', handler: onAgentSpawned as unknown as (...args: unknown[]) => void },\n { event: 'agent:stopped', handler: onAgentStopped as unknown as (...args: unknown[]) => void },\n { event: 'daemon:heartbeat', handler: onDaemonHeartbeat as unknown as (...args: unknown[]) => void },\n );\n\n initialized = true;\n logger.info(COMPONENT, `Command Post initialized — ${registeredAgents.size} agents, ${budgetPolicies.length} budget policies, ${checkouts.size} active checkouts`);\n}\n\n// ─── Paperclip: Issue/Ticket System ──────────────────────────────────────\n\nexport function createIssue(opts: {\n title: string; description?: string; priority?: CPIssue['priority'];\n assigneeAgentId?: string; createdByAgentId?: string; createdByUser?: string;\n goalId?: string; parentId?: string;\n}): CPIssue {\n issueCounter++;\n const issue: CPIssue = {\n id: uuid().slice(0, 8),\n title: opts.title,\n description: opts.description || '',\n status: 'backlog',\n priority: opts.priority || 'medium',\n assigneeAgentId: opts.assigneeAgentId,\n createdByAgentId: opts.createdByAgentId,\n createdByUser: opts.createdByUser || 'board',\n goalId: opts.goalId,\n parentId: opts.parentId,\n issueNumber: issueCounter,\n identifier: `TIT-${issueCounter}`,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n issues.set(issue.id, issue);\n // Cap issues map to prevent unbounded memory growth\n if (issues.size > 1000) {\n const sorted = [...issues.entries()].sort((a, b) =>\n new Date(a[1].createdAt).getTime() - new Date(b[1].createdAt).getTime()\n );\n const toRemove = sorted.slice(0, issues.size - 800); // Keep newest 800\n for (const [id] of toRemove) issues.delete(id);\n }\n saveState();\n addActivity({ type: 'goal_created', message: `Issue ${issue.identifier} created: \"${issue.title}\"`, metadata: { issueId: issue.id } });\n return issue;\n}\n\nexport function updateIssue(id: string, updates: Partial<Pick<CPIssue, 'title' | 'description' | 'status' | 'priority' | 'assigneeAgentId' | 'goalId'>>): CPIssue | null {\n const issue = issues.get(id);\n if (!issue) return null;\n const prev = issue.status;\n Object.assign(issue, updates);\n issue.updatedAt = new Date().toISOString();\n if (updates.status === 'in_progress' && !issue.startedAt) issue.startedAt = issue.updatedAt;\n if (updates.status === 'done' && !issue.completedAt) issue.completedAt = issue.updatedAt;\n saveState();\n if (updates.status && updates.status !== prev) {\n addActivity({ type: 'task_checkin', message: `Issue ${issue.identifier} status: ${prev} → ${updates.status}`, metadata: { issueId: id } });\n }\n return issue;\n}\n\nexport function getIssue(id: string): CPIssue | null {\n return issues.get(id) || null;\n}\n\nexport function listIssues(filters?: { status?: string; assigneeAgentId?: string; goalId?: string }): CPIssue[] {\n let result = Array.from(issues.values());\n if (filters?.status) result = result.filter(i => i.status === filters.status);\n if (filters?.assigneeAgentId) result = result.filter(i => i.assigneeAgentId === filters.assigneeAgentId);\n if (filters?.goalId) result = result.filter(i => i.goalId === filters.goalId);\n return result.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n}\n\nexport function deleteIssue(id: string): boolean {\n if (!issues.has(id)) return false;\n issues.delete(id);\n saveState();\n addActivity({ type: 'issue_deleted', agentId: 'user', message: `Issue ${id} deleted` });\n return true;\n}\n\nexport function checkoutIssue(issueId: string, agentId: string): CPIssue | null {\n const issue = issues.get(issueId);\n if (!issue) return null;\n if (issue.status === 'in_progress' && issue.checkoutRunId && issue.assigneeAgentId !== agentId) return null; // 409: locked\n issue.status = 'in_progress';\n issue.assigneeAgentId = agentId;\n issue.checkoutRunId = uuid().slice(0, 8);\n issue.startedAt = issue.startedAt || new Date().toISOString();\n issue.updatedAt = new Date().toISOString();\n saveState();\n addActivity({ type: 'task_checkout', agentId, message: `Agent \"${agentId}\" checked out issue ${issue.identifier}`, metadata: { issueId } });\n return issue;\n}\n\nexport function addIssueComment(issueId: string, body: string, author: { agentId?: string; user?: string }): CPComment | null {\n if (!issues.has(issueId)) return null;\n const comment: CPComment = {\n id: uuid().slice(0, 8),\n issueId,\n authorAgentId: author.agentId,\n authorUser: author.user || 'board',\n body,\n createdAt: new Date().toISOString(),\n };\n comments.push(comment);\n saveState();\n return comment;\n}\n\nexport function getIssueComments(issueId: string): CPComment[] {\n return comments.filter(c => c.issueId === issueId);\n}\n\n/**\n * Full-text search across CP issues, titles, descriptions, and comments.\n * Returns matching issues sorted by relevance (title match > description > comments).\n */\nexport function searchIssues(query: string): CPIssue[] {\n if (!query || query.trim().length < 2) return [];\n const q = query.toLowerCase().trim();\n const scored = Array.from(issues.values()).map(issue => {\n let score = 0;\n const title = (issue.title || '').toLowerCase();\n const desc = (issue.description || '').toLowerCase();\n const issueComments = getIssueComments(issue.id);\n const commentText = issueComments.map(c => (c.body || '').toLowerCase()).join(' ');\n\n if (title.includes(q)) score += 10;\n if (desc.includes(q)) score += 5;\n if (commentText.includes(q)) score += 2;\n if (issue.id.toLowerCase().includes(q)) score += 3;\n\n // Word-boundary bonus\n const words = q.split(/\\s+/);\n for (const word of words) {\n if (word.length < 2) continue;\n if (title.includes(word)) score += 2;\n if (desc.includes(word)) score += 1;\n }\n\n return { issue, score };\n });\n\n return scored\n .filter(s => s.score > 0)\n .sort((a, b) => b.score - a.score)\n .map(s => s.issue);\n}\n\n// ─── Paperclip: Approval System ──────────────────────────────────────────\n\n/**\n * v4.13 coalescing key — generates a stable signature for an approval so\n * autonomous producers that fire on a cron can reuse a pending approval\n * for the same concern instead of piling up duplicates. Keyed on\n * (type, requestedBy, payload.kind, and either goalId or model — the\n * fields that are identity-like for the concern being raised).\n */\nfunction coalesceKey(opts: {\n type: CPApproval['type']; requestedBy: string; payload: Record<string, unknown>;\n}): string {\n const kind = typeof opts.payload.kind === 'string' ? opts.payload.kind : '';\n const goalId = typeof opts.payload.goalId === 'string' ? opts.payload.goalId : '';\n const model = typeof opts.payload.model === 'string' ? opts.payload.model : '';\n const title = typeof opts.payload.title === 'string' ? opts.payload.title : '';\n // Prefer goalId/model when available, otherwise fall back to title. Title-less\n // concerns (e.g. repeating self_repair) get coalesced by (type, requestedBy, kind).\n const identity = goalId || model || title;\n return `${opts.type}|${opts.requestedBy}|${kind}|${identity}`;\n}\n\nexport function createApproval(opts: {\n type: CPApproval['type']; requestedBy: string; payload: Record<string, unknown>;\n linkedIssueIds?: string[];\n}): CPApproval {\n // Gap 4 (plan-this-logical-ocean): path-scoped auto-approval.\n // Before filing, classify the intent. If the configured autoApprove\n // rules say 'auto', short-circuit to an already-approved CPApproval\n // so the thing never reaches the human queue. Off by default — the\n // (config as any).autoApprove check keeps legacy callers happy\n // before the config schema is loaded.\n try {\n const auto = (config as unknown as { autoApprove?: { enabled?: boolean; rules?: unknown[] } })?.autoApprove;\n if (auto?.enabled) {\n const rules = (auto.rules as ApprovalRule[]) || [];\n if (shouldAutoApprove({ type: opts.type, payload: opts.payload }, { enabled: true, rules })) {\n const approved: CPApproval = {\n id: uuid().slice(0, 8),\n type: opts.type,\n status: 'approved',\n requestedBy: opts.requestedBy,\n payload: opts.payload,\n decidedBy: 'auto:path-classifier',\n decidedAt: new Date().toISOString(),\n decisionNote: 'Auto-approved by path-scoped classifier',\n linkedIssueIds: opts.linkedIssueIds || [],\n createdAt: new Date().toISOString(),\n };\n approvals.set(approved.id, approved);\n saveState();\n addActivity({\n type: 'goal_created',\n message: `Approval auto-approved: ${approved.type} (${opts.payload.kind ?? '-'}) from ${opts.requestedBy}`,\n metadata: { approvalId: approved.id, auto: true, path: opts.payload.path ?? null },\n });\n return approved;\n }\n }\n } catch (err) {\n logger.warn(COMPONENT, `Auto-approval classifier error, falling through to human queue: ${(err as Error).message}`);\n }\n\n // Coalesce: if a pending approval already exists for the same concern,\n // update its payload + timestamp and return it instead of filing a new\n // one. Stops autonomous producers (canary-eval, self-repair daemon,\n // auto-heal runner) from flooding the queue with dupes while a human\n // hasn't decided the first one yet.\n const key = coalesceKey(opts);\n for (const existing of approvals.values()) {\n if (existing.status !== 'pending') continue;\n if (coalesceKey({ type: existing.type, requestedBy: existing.requestedBy, payload: existing.payload as Record<string, unknown> }) === key) {\n existing.payload = opts.payload;\n existing.createdAt = new Date().toISOString();\n saveState();\n logger.debug(COMPONENT, `Approval coalesced into ${existing.id} (key=${key})`);\n return existing;\n }\n }\n\n const approval: CPApproval = {\n id: uuid().slice(0, 8),\n type: opts.type,\n status: 'pending',\n requestedBy: opts.requestedBy,\n payload: opts.payload,\n linkedIssueIds: opts.linkedIssueIds || [],\n createdAt: new Date().toISOString(),\n };\n approvals.set(approval.id, approval);\n // Cap approvals map to prevent unbounded memory growth\n if (approvals.size > 500) {\n const sorted = [...approvals.entries()].sort((a, b) =>\n new Date(a[1].createdAt).getTime() - new Date(b[1].createdAt).getTime()\n );\n const toRemove = sorted.slice(0, approvals.size - 400);\n for (const [id] of toRemove) approvals.delete(id);\n }\n saveState();\n addActivity({ type: 'goal_created', message: `Approval requested: ${approval.type} by ${approval.requestedBy}`, metadata: { approvalId: approval.id } });\n return approval;\n}\n\nexport async function approveApproval(id: string, decidedBy: string, note?: string): Promise<CPApproval | null> {\n const approval = approvals.get(id);\n if (!approval || approval.status !== 'pending') return null;\n approval.status = 'approved';\n approval.decidedBy = decidedBy;\n approval.decidedAt = new Date().toISOString();\n approval.decisionNote = note;\n saveState();\n\n // Paperclip competitive gap fix: wire up approval actions\n // Previously hire_agent was dead code — approving a hire didn't create an agent.\n if (approval.type === 'hire_agent') {\n const { name, role, template, model, task } = approval.payload as {\n name?: string; role?: string; template?: string; model?: string; task?: string;\n };\n if (name) {\n // Resolve model: explicit → template tier → config default\n const config = loadConfig();\n const aliases = config.agent.modelAliases || {};\n let resolvedModel = model || '';\n if (!resolvedModel && template) {\n const { SUB_AGENT_TEMPLATES } = await import('./subAgent.js');\n const tmpl = SUB_AGENT_TEMPLATES[template];\n const tier = (tmpl as Record<string, unknown> | undefined)?.tier as string | undefined;\n resolvedModel = tier ? (aliases[tier] || aliases.cloud || '') : (aliases.cloud || '');\n }\n if (!resolvedModel) {\n resolvedModel = config.agent.model || aliases.cloud || 'ollama/kimi-k2.6:cloud';\n }\n\n // Spawn live agent in multi-agent router\n const spawnResult = spawnAgent({\n name,\n model: resolvedModel,\n systemPrompt: template\n ? `You are the ${name} specialist. You were hired with the \"${template}\" template. Execute tasks efficiently and report back when done.`\n : `You are the ${name} agent. Execute tasks efficiently and report back when done.`,\n channelBindings: [{ channel: 'direct', pattern: name }],\n });\n\n if (!spawnResult.success || !spawnResult.agent) {\n logger.error('CommandPost', `[HireApproval] Failed to spawn agent \"${name}\": ${spawnResult.error}`);\n addActivity({ type: 'error', message: `Failed to hire agent \"${name}\": ${spawnResult.error}`, metadata: { approvalId: id } });\n return approval;\n }\n\n // Register in Command Post registry\n const agent = registerAgent({\n id: spawnResult.agent.id, // sync CP id with multiAgent id\n name,\n role: role || 'general',\n title: role || name,\n model: resolvedModel,\n template,\n status: 'active',\n });\n logger.info('CommandPost', `[HireApproval] Agent \"${name}\" hired and activated (model: ${resolvedModel}, approved by ${decidedBy})`);\n addActivity({ type: 'agent_status_change', message: `Agent \"${name}\" hired and activated (model: ${resolvedModel}, approved by ${decidedBy})`, metadata: { approvalId: id, agentId: agent.id } });\n\n // Optionally create a first task issue for the new agent\n if (task) {\n createIssue({\n title: task,\n description: `Initial task assigned on hire (approval ${id})`,\n priority: 'medium',\n assigneeAgentId: agent.id,\n });\n }\n }\n } else if (approval.type === 'budget_override' && approval.payload.agentId) {\n // Resume paused agent\n updateAgentStatus(approval.payload.agentId as string, 'active');\n addActivity({ type: 'goal_completed', message: `Budget override approved for ${approval.payload.agentId} by ${decidedBy}`, metadata: { approvalId: id } });\n } else if (approval.type === 'custom' && (approval.payload as { kind?: string }).kind === 'restart_titan') {\n // v4.13: approval-gated restart. When approved, audit-log the\n // decision THEN async-exec systemctl restart. The current process\n // will die; next boot writes a 'restart_completed' audit entry.\n const reason = (approval.payload as { reason?: string }).reason || 'no reason given';\n try {\n const { logAudit } = await import('../security/auditLog.js');\n logAudit('security_alert', decidedBy, {\n action: 'restart_titan_approved',\n approvalId: id,\n reason,\n requestedBy: approval.requestedBy,\n });\n } catch { /* audit unavailable — still proceed, restart is more important */ }\n logger.info('CommandPost', `[RestartApproval] TITAN restart approved by ${decidedBy}: ${reason}`);\n addActivity({ type: 'goal_completed', message: `Restart approved by ${decidedBy}: ${reason}`, metadata: { approvalId: id } });\n // Fire-and-forget so the approval response returns before systemctl\n // kills this process. The 1500ms delay gives Express time to flush\n // the /api/command-post/approvals/:id/approve response.\n setTimeout(() => {\n try {\n const proc = spawn('sudo', ['-n', 'systemctl', 'restart', 'titan-gateway.service'], {\n detached: true,\n stdio: 'ignore',\n });\n proc.unref();\n } catch (err) {\n logger.error('CommandPost', `[RestartApproval] systemctl restart failed: ${(err as Error).message}`);\n }\n }, 1500).unref();\n } else if (approval.type === 'goal_proposal' || approval.type === 'soma_proposal') {\n const payload = approval.payload as {\n title?: string; description?: string; priority?: number;\n tags?: string[]; parentGoalId?: string;\n subtasks?: Array<{ title: string; description: string; dependsOn?: string[] }>;\n };\n if (!payload.title || !payload.description) {\n logger.warn('CommandPost', `[GoalProposal] Approval ${id} has malformed payload — missing title/description`);\n addActivity({ type: 'error', message: `Goal proposal ${id} approved but payload was malformed`, metadata: { approvalId: id } });\n } else {\n // Dynamic import to avoid circular dependency (goals.ts imports commandPost types)\n try {\n const { createGoal } = await import('./goals.js');\n // v4.8.0: preserve proposer provenance on the goal so the\n // self-mod pipeline can trace goal → drive → proposal.\n // Uses `soma:<drive>` tag convention already established\n // by pressure.ts.\n const enrichedTags = [...(payload.tags || [])];\n if (approval.requestedBy && approval.requestedBy.startsWith('soma:')\n && !enrichedTags.includes(approval.requestedBy)) {\n enrichedTags.push(approval.requestedBy);\n }\n const goal = createGoal({\n title: payload.title!,\n description: payload.description!,\n priority: payload.priority,\n tags: enrichedTags,\n parentGoalId: payload.parentGoalId,\n subtasks: payload.subtasks,\n force: true, // human explicitly approved this proposal\n });\n // Link the goal back to the approval so UI can track progress\n approval.payload = { ...approval.payload, goalId: goal.id };\n saveState();\n addActivity({\n type: 'goal_created',\n goalId: goal.id,\n message: `Goal proposal approved: \"${goal.title}\" (proposed by ${approval.requestedBy}, approved by ${decidedBy})`,\n metadata: { approvalId: id, proposedBy: approval.requestedBy },\n });\n logger.info('CommandPost', `[GoalProposal] Goal ${goal.id} created from approval ${id}`);\n } catch (err) {\n logger.error('CommandPost', `[GoalProposal] Failed to create goal from approval ${id}: ${(err as Error).message}`);\n addActivity({ type: 'error', message: `Goal proposal ${id} creation failed: ${(err as Error).message}`, metadata: { approvalId: id } });\n }\n }\n } else if (\n approval.type === 'custom'\n && (approval.payload as Record<string, unknown>)?.kind === 'self_mod_pr'\n ) {\n // v4.9.0-local.8: apply the staged self-modification PR. Fire-and-forget\n // so the approval call returns immediately; errors land in logs + a\n // follow-up activity entry.\n const payload = approval.payload as Record<string, unknown>;\n const goalId = payload.goalId as string | undefined;\n if (goalId) {\n (async () => {\n try {\n const { applyStagedPR } = await import('./selfModStaging.js');\n const result = await applyStagedPR(goalId);\n const { recordEpisode } = await import('../memory/episodic.js');\n // v4.10.0-local polish: surface Opus verdict in activity + episode\n const opusNote = result.opusReview\n ? ` · Opus ${result.opusReview.verdict} (conf ${result.opusReview.confidence.toFixed(2)})`\n : '';\n if (result.blockedByReview && result.opusReview) {\n recordEpisode({\n kind: 'self_mod_pr_rejected',\n summary: `Self-mod PR BLOCKED by Opus review (goal ${goalId}): ${result.opusReview.reasoning}`,\n detail: `Verdict: ${result.opusReview.verdict}\\nConcerns:\\n${result.opusReview.concerns.join('\\n- ')}\\nSuggestions:\\n${result.opusReview.suggestions.join('\\n- ')}`,\n tags: ['self-mod', 'pr-blocked-by-review', goalId],\n });\n addActivity({\n type: 'error',\n message: `Self-mod PR blocked by Opus review for goal ${goalId}: ${result.opusReview.reasoning.slice(0, 120)}`,\n metadata: { approvalId: id, goalId, opusReview: result.opusReview },\n });\n return;\n }\n recordEpisode({\n kind: 'self_mod_pr_merged',\n summary: `Self-mod PR applied: ${result.applied.length} file(s) landed, ${result.failed.length} failed (goal ${goalId})${opusNote}`,\n detail: `Applied: ${result.applied.join(', ')}\\nFailed: ${result.failed.map(f => `${f.path} (${f.error})`).join(', ') || 'none'}\\n${result.opusReview ? `Opus reasoning: ${result.opusReview.reasoning}` : ''}`,\n tags: ['self-mod', 'pr-merged', goalId],\n });\n addActivity({\n type: 'goal_completed',\n message: `Self-mod PR applied for goal ${goalId}: ${result.applied.length} file(s) → ${resolveSelfModTargetSafe()}, ${result.failed.length} failures${opusNote}`,\n metadata: { approvalId: id, goalId, applied: result.applied, failed: result.failed, opusReview: result.opusReview },\n });\n } catch (err) {\n logger.warn('CommandPost', `[SelfModApply] Failed: ${(err as Error).message}`);\n addActivity({ type: 'error', message: `Self-mod PR apply failed for goal ${goalId}: ${(err as Error).message}`, metadata: { approvalId: id, goalId } });\n }\n })();\n }\n addActivity({ type: 'goal_completed', message: `Self-mod PR approved by ${decidedBy} — applying…`, metadata: { approvalId: id, goalId } });\n } else if (approval.type === 'custom' && (approval.payload as { kind?: string }).kind === 'driver_blocked') {\n const payload = approval.payload as { goalId?: string; goalTitle?: string };\n if (payload.goalId) {\n // Instant-unblock: tick the driver immediately so the user sees\n // TITAN start working right away instead of waiting up to 10s\n // for the next scheduler loop.\n import('./goalDriver.js').then(({ tickDriver }) => {\n tickDriver(payload.goalId!).catch(() => { /* driver may not exist */ });\n }).catch(() => { /* module load failed */ });\n addActivity({\n type: 'goal_completed',\n message: `Driver unblocked for \"${payload.goalTitle || payload.goalId}\" (approved by ${decidedBy})`,\n metadata: { approvalId: id, goalId: payload.goalId },\n });\n logger.info('CommandPost', `[DriverUnblock] Approval ${id} approved — ticking driver for goal ${payload.goalId}`);\n }\n } else {\n addActivity({ type: 'goal_completed', message: `Approval ${approval.type} approved by ${decidedBy}`, metadata: { approvalId: id } });\n }\n\n return approval;\n}\n\n// Small helper so the async apply block can log the resolved target without\n// threading loadConfig through — silently falls back to the default if the\n// config isn't loaded yet for any reason.\nfunction resolveSelfModTargetSafe(): string {\n try {\n const c = loadConfig();\n const sm = (c.autonomy as unknown as { selfMod?: { target?: string } }).selfMod;\n return sm?.target ?? '/opt/TITAN';\n } catch { return '/opt/TITAN'; }\n}\n\n/**\n * Request a hire approval. Creates a pending approval that, when approved,\n * will register the agent and optionally create their first task.\n */\nexport function requestHireApproval(\n requestedBy: string,\n name: string,\n role: string,\n template?: string,\n model?: string,\n task?: string,\n): CPApproval {\n // Use the full approval pipeline (auto-approval classifier + coalescing)\n // instead of manually constructing and inserting a raw approval.\n const approval = createApproval({\n type: 'hire_agent',\n requestedBy,\n payload: { name, role, template, model, task },\n });\n addActivity({ type: 'agent_status_change', message: `Hire approval requested for \"${name}\" (${role}) by ${requestedBy}`, metadata: { approvalId: approval.id } });\n logger.info('CommandPost', `[HireRequest] Pending approval for \"${name}\" (${role}) (id=${approval.id})`);\n return approval;\n}\n\nexport function rejectApproval(id: string, decidedBy: string, note?: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval || approval.status !== 'pending') return null;\n approval.status = 'rejected';\n approval.decidedBy = decidedBy;\n approval.decidedAt = new Date().toISOString();\n approval.decisionNote = note;\n saveState();\n const activityType: ActivityEntry['type'] =\n approval.type === 'goal_proposal' ? 'goal_proposal_rejected' : 'error';\n addActivity({ type: activityType, message: `Approval ${approval.type} rejected by ${decidedBy}${note ? `: ${note}` : ''}`, metadata: { approvalId: id, proposedBy: approval.requestedBy } });\n\n // v4.9.0-local.8: when a self_mod_pr is rejected, archive the staging\n // bundle so the files don't silently linger. Fire-and-forget.\n if (\n approval.type === 'custom'\n && (approval.payload as Record<string, unknown>)?.kind === 'self_mod_pr'\n ) {\n const payload = approval.payload as Record<string, unknown>;\n const goalId = payload.goalId as string | undefined;\n if (goalId) {\n (async () => {\n try {\n const { rejectStagedPR } = await import('./selfModStaging.js');\n const r = rejectStagedPR(goalId, note ?? 'rejected without note');\n const { recordEpisode } = await import('../memory/episodic.js');\n recordEpisode({\n kind: 'self_mod_pr_rejected',\n summary: `Self-mod PR rejected for goal ${goalId}${note ? `: ${note}` : ''}`,\n detail: `Bundle archived: ${r.archived}`,\n tags: ['self-mod', 'pr-rejected', goalId],\n });\n } catch (err) {\n logger.warn('CommandPost', `[SelfModReject] Failed: ${(err as Error).message}`);\n }\n })();\n }\n }\n return approval;\n}\n\n/**\n * Attach a Soma shadow-rehearsal verdict to an existing pending approval.\n * The verdict is merged into the approval payload under `shadowVerdict` so\n * downstream UI (Approvals tab, Soma view) can render it alongside accept/reject.\n * Returns the updated approval or null if the approval doesn't exist / was decided.\n */\nexport function attachShadowVerdictToApproval(\n approvalId: string,\n verdict: Record<string, unknown>,\n): CPApproval | null {\n const approval = approvals.get(approvalId);\n if (!approval || approval.status !== 'pending') return null;\n approval.payload = { ...approval.payload, shadowVerdict: verdict };\n saveState();\n return approval;\n}\n\n// ─── Threaded Inbox: Reply / Snooze / Batch ─────────────────────────────\n\nexport function replyToApproval(id: string, author: string, body: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval) return null;\n const comment: CPComment = {\n id: uuid().slice(0, 8),\n issueId: id,\n authorUser: author,\n body,\n createdAt: new Date().toISOString(),\n };\n if (!approval.thread) approval.thread = [];\n approval.thread.push(comment);\n saveState();\n addActivity({ type: 'system', message: `Reply on approval ${id} by ${author}`, metadata: { approvalId: id } });\n return approval;\n}\n\nexport function snoozeApproval(id: string, until: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval || approval.status !== 'pending') return null;\n approval.snoozedUntil = until;\n saveState();\n return approval;\n}\n\nexport function unsnoozeApproval(id: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval) return null;\n delete approval.snoozedUntil;\n saveState();\n return approval;\n}\n\nexport async function batchApprove(ids: string[], decidedBy: string, note?: string): Promise<{ approved: string[]; failed: string[] }> {\n const approved: string[] = [];\n const failed: string[] = [];\n for (const id of ids) {\n const result = await approveApproval(id, decidedBy, note);\n if (result) approved.push(id); else failed.push(id);\n }\n return { approved, failed };\n}\n\nexport function batchReject(ids: string[], decidedBy: string, note?: string): { rejected: string[]; failed: string[] } {\n const rejected: string[] = [];\n const failed: string[] = [];\n for (const id of ids) {\n const result = rejectApproval(id, decidedBy, note);\n if (result) rejected.push(id); else failed.push(id);\n }\n return { rejected, failed };\n}\n\n// ─── Agent-to-User Messaging ─────────────────────────────────────────────\n\nexport interface AgentMessage {\n id: string;\n agentId: string;\n agentName: string;\n userId: string;\n content: string;\n context?: Record<string, unknown>;\n read: boolean;\n createdAt: string;\n}\n\nconst agentMessages: AgentMessage[] = [];\n\nexport function sendAgentMessage(agentId: string, agentName: string, userId: string, content: string, context?: Record<string, unknown>): AgentMessage {\n const msg: AgentMessage = {\n id: uuid().slice(0, 8),\n agentId,\n agentName,\n userId,\n content,\n context,\n read: false,\n createdAt: new Date().toISOString(),\n };\n agentMessages.push(msg);\n if (agentMessages.length > 500) agentMessages.splice(0, agentMessages.length - 500);\n addActivity({ type: 'system', message: `Message from ${agentName}: ${content.slice(0, 100)}`, metadata: { agentId, messageId: msg.id } });\n return msg;\n}\n\nexport function getAgentMessages(agentId?: string, userId?: string, unreadOnly = false): AgentMessage[] {\n return agentMessages.filter(m => {\n if (agentId && m.agentId !== agentId) return false;\n if (userId && m.userId !== userId) return false;\n if (unreadOnly && m.read) return false;\n return true;\n }).slice().reverse();\n}\n\nexport function markAgentMessageRead(id: string): boolean {\n const msg = agentMessages.find(m => m.id === id);\n if (!msg) return false;\n msg.read = true;\n return true;\n}\n\n/**\n * File a goal proposal from an agent. Creates a pending approval that, when\n * approved, becomes a real goal via createGoal(). Used by the goalProposer\n * during the nightly dreaming cycle.\n */\nexport function requestGoalProposalApproval(\n requestedBy: string,\n proposal: {\n title: string;\n description: string;\n rationale?: string;\n priority?: number;\n tags?: string[];\n parentGoalId?: string;\n subtasks?: Array<{ title: string; description: string; dependsOn?: string[] }>;\n },\n type: 'goal_proposal' | 'soma_proposal' = 'goal_proposal'\n): CPApproval {\n // v5.0.0: Pending queue cap — if there are too many pending approvals,\n // auto-reject the oldest ones to prevent the queue from growing without bound.\n const MAX_PENDING_APPROVALS = 30;\n const pending = Array.from(approvals.values()).filter(a => a.status === 'pending');\n if (pending.length >= MAX_PENDING_APPROVALS) {\n // Sort oldest first, reject enough to get back under the cap\n pending.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());\n const toReject = pending.slice(0, pending.length - MAX_PENDING_APPROVALS + 1);\n for (const old of toReject) {\n old.status = 'rejected';\n old.decidedBy = 'auto:cap';\n old.decidedAt = new Date().toISOString();\n old.decisionNote = `Auto-rejected: pending approval cap (${MAX_PENDING_APPROVALS}) reached`;\n logger.info(COMPONENT, `Auto-rejected approval ${old.id} due to pending cap`);\n }\n if (toReject.length > 0) saveState();\n }\n\n // Dedupe: if a pending proposal with the same title already exists\n // (regardless of which agent proposed it), return the existing one\n // instead of filing a duplicate. Multiple specialists running the\n // proposer concurrently were producing 3× the same goals every tick.\n const normalizedTitle = proposal.title.trim().toLowerCase();\n for (const existing of approvals.values()) {\n if (existing.status !== 'pending') continue;\n if (existing.type !== type) continue;\n const existingTitle = ((existing.payload as { title?: string })?.title || '').trim().toLowerCase();\n if (existingTitle && existingTitle === normalizedTitle) {\n logger.debug(COMPONENT, `${type} dedupe: \"${proposal.title}\" already pending (approval ${existing.id}) — returning existing`);\n return existing;\n }\n }\n const approval = createApproval({\n type,\n requestedBy,\n payload: proposal,\n });\n addActivity({\n type: 'goal_proposal_requested',\n agentId: requestedBy,\n message: `Goal proposal filed by ${requestedBy}: \"${proposal.title}\"`,\n metadata: { approvalId: approval.id, rationale: proposal.rationale },\n });\n return approval;\n}\n\nexport function listApprovals(status?: string): CPApproval[] {\n let result = Array.from(approvals.values());\n if (status) result = result.filter(a => a.status === status);\n return result.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n}\n\nexport function getApproval(id: string): CPApproval | null {\n return approvals.get(id) || null;\n}\n\n// ─── v4.10.0-local (Phase B): approval categorization ─────────────\n\nexport type ApprovalUrgency = 'high' | 'medium' | 'low';\nexport type ApprovalCategory =\n | 'driver_blocked' // driver needs human input RIGHT NOW\n | 'self_mod_pr' // code change to TITAN awaiting review\n | 'self_repair' // self-repair daemon proposal\n | 'goal_proposal' // SOMA/proposer wants a new goal active\n | 'hire_agent' // create a new agent\n | 'budget_override' // spend more / continue past limit\n | 'canary_regression' // model quality drift detected\n | 'other';\n\nexport interface CategorizedApproval extends CPApproval {\n category: ApprovalCategory;\n urgency: ApprovalUrgency;\n ageMins: number;\n summary: string;\n}\n\nexport function categorizeApproval(a: CPApproval): CategorizedApproval {\n const payload = a.payload as Record<string, unknown>;\n const kind = payload?.kind as string | undefined;\n // Category\n let category: ApprovalCategory = 'other';\n if (kind === 'driver_blocked') category = 'driver_blocked';\n else if (kind === 'self_mod_pr') category = 'self_mod_pr';\n else if (kind === 'self_repair') category = 'self_repair';\n else if (a.type === 'goal_proposal' || a.type === 'soma_proposal') category = 'goal_proposal';\n else if (a.type === 'hire_agent') category = 'hire_agent';\n else if (a.type === 'budget_override') category = 'budget_override';\n else if (kind === 'canary_regression') category = 'canary_regression';\n\n // Urgency\n let urgency: ApprovalUrgency = 'low';\n if (category === 'driver_blocked' || category === 'canary_regression') urgency = 'high';\n else if (category === 'self_mod_pr' || category === 'self_repair' || category === 'hire_agent') urgency = 'medium';\n // Explicit payload override wins\n if (payload?.urgency === 'high') urgency = 'high';\n if (payload?.urgency === 'medium' && urgency === 'low') urgency = 'medium';\n\n // Summary line for the UI/digest\n const summary =\n (payload?.question as string) ||\n (payload?.title as string) ||\n (payload?.goalTitle as string) ||\n (payload?.reason as string) ||\n a.type;\n\n return {\n ...a,\n category,\n urgency,\n ageMins: Math.round((Date.now() - new Date(a.createdAt).getTime()) / 60_000),\n summary: String(summary).slice(0, 200),\n };\n}\n\nexport function listCategorizedApprovals(status: string = 'pending'): {\n approvals: CategorizedApproval[];\n byCategory: Record<ApprovalCategory, number>;\n byUrgency: Record<ApprovalUrgency, number>;\n} {\n const cats = listApprovals(status).map(categorizeApproval);\n // Sort: urgency desc, age desc\n const urgOrder: Record<ApprovalUrgency, number> = { high: 3, medium: 2, low: 1 };\n cats.sort((a, b) => (urgOrder[b.urgency] - urgOrder[a.urgency]) || (b.ageMins - a.ageMins));\n\n const byCategory: Record<ApprovalCategory, number> = {\n driver_blocked: 0, self_mod_pr: 0, self_repair: 0, goal_proposal: 0,\n hire_agent: 0, budget_override: 0, canary_regression: 0, other: 0,\n };\n const byUrgency: Record<ApprovalUrgency, number> = { high: 0, medium: 0, low: 0 };\n for (const a of cats) {\n byCategory[a.category]++;\n byUrgency[a.urgency]++;\n }\n return { approvals: cats, byCategory, byUrgency };\n}\n\n// ─── Paperclip: Run Tracking ─────────────────────────────────────────────\n\nexport function startRun(agentId: string, source: CPRun['source'], issueId?: string): CPRun {\n const run: CPRun = {\n id: uuid().slice(0, 8),\n agentId,\n source,\n status: 'running',\n issueId,\n startedAt: new Date().toISOString(),\n toolsUsed: [],\n };\n runs.push(run);\n if (runs.length > 500) runs.splice(0, runs.length - 500);\n saveState();\n return run;\n}\n\nexport function endRun(runId: string, result: { status: 'succeeded' | 'failed' | 'error'; toolsUsed?: string[]; tokenUsage?: CPRun['tokenUsage']; error?: string }): CPRun | null {\n const run = runs.find(r => r.id === runId);\n if (!run) return null;\n run.status = result.status;\n run.finishedAt = new Date().toISOString();\n run.durationMs = new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime();\n if (result.toolsUsed) run.toolsUsed = result.toolsUsed;\n if (result.tokenUsage) run.tokenUsage = result.tokenUsage;\n if (result.error) run.error = result.error;\n saveState();\n return run;\n}\n\nexport function listRuns(agentId?: string, limit = 50): CPRun[] {\n let result = [...runs];\n if (agentId) result = result.filter(r => r.agentId === agentId);\n return result.slice(-limit).reverse();\n}\n\n// ─── Paperclip: Org Chart ────────────────────────────────────────────────\n\nexport function getOrgTree(): OrgNode[] {\n const agents = getRegisteredAgents();\n const agentsById = new Map(agents.map(a => [a.id, a]));\n const childrenMap = new Map<string | undefined, RegisteredAgent[]>();\n\n for (const a of agents) {\n const parent = a.reportsTo || undefined;\n if (!childrenMap.has(parent)) childrenMap.set(parent, []);\n childrenMap.get(parent)!.push(a);\n }\n\n function buildTree(parentId: string | undefined): OrgNode[] {\n const children = childrenMap.get(parentId) || [];\n return children.map(a => ({\n id: a.id,\n name: a.name,\n role: a.role,\n title: a.title,\n status: a.status,\n model: a.model,\n reports: buildTree(a.id),\n }));\n }\n\n return buildTree(undefined);\n}\n\n/**\n * Update an agent's persistent identity (F2). Any field omitted is left\n * untouched; pass `null` to explicitly clear a field. Triggers an activity\n * feed entry so the change is auditable.\n */\nexport function updateAgentIdentity(\n agentId: string,\n updates: {\n voiceId?: string | null;\n personaId?: string | null;\n systemPromptOverride?: string | null;\n memoryNamespace?: string | null;\n characterSummary?: string | null;\n model?: string | null;\n },\n): RegisteredAgent | null {\n const agent = registeredAgents.get(agentId);\n if (!agent) return null;\n\n const changed: string[] = [];\n const apply = <K extends 'voiceId' | 'personaId' | 'systemPromptOverride' | 'memoryNamespace' | 'characterSummary' | 'model'>(key: K) => {\n const v = updates[key];\n if (v === undefined) return;\n const before = agent[key];\n if (v === null) delete agent[key];\n else agent[key] = v;\n if (before !== agent[key]) changed.push(key);\n };\n apply('voiceId');\n apply('personaId');\n apply('systemPromptOverride');\n apply('memoryNamespace');\n apply('characterSummary');\n apply('model');\n\n if (changed.length === 0) return agent;\n\n saveState();\n addActivity({\n type: 'agent_status_change',\n agentId,\n message: `Agent \"${agent.name}\" identity updated: ${changed.join(', ')}`,\n metadata: { fields: changed },\n });\n return agent;\n}\n\n/**\n * Resolve the effective Hindsight memory namespace for an agent.\n * Defaults to `agent:${id}` when no explicit namespace is set.\n */\nexport function getAgentMemoryNamespace(agentId: string): string {\n const agent = registeredAgents.get(agentId);\n if (!agent) return `agent:${agentId}`;\n return agent.memoryNamespace || `agent:${agent.id}`;\n}\n\n/**\n * Resolve the effective TTS voice for an agent. Returns the agent's stored\n * voiceId if set, otherwise undefined — callers should fall back to the\n * global config.voice.ttsVoice. Voice-mode plumbing of this getter is\n * tracked separately; F2 ships identity storage + agent.ts + Hindsight\n * scoping only.\n */\nexport function getAgentVoice(agentId: string): string | undefined {\n const agent = registeredAgents.get(agentId);\n return agent?.voiceId;\n}\n\nexport function updateRegisteredAgent(agentId: string, updates: Partial<Pick<RegisteredAgent, 'reportsTo' | 'role' | 'title' | 'name' | 'model'>>): RegisteredAgent | null {\n const agent = registeredAgents.get(agentId);\n if (!agent) return null;\n if (updates.reportsTo !== undefined) agent.reportsTo = updates.reportsTo || undefined;\n if (updates.role) agent.role = updates.role;\n if (updates.title !== undefined) agent.title = updates.title || undefined;\n if (updates.name) agent.name = updates.name;\n if (updates.model !== undefined) agent.model = updates.model || '';\n saveState();\n return agent;\n}\n\nexport function shutdownCommandPost(): void {\n if (sweepInterval) { clearInterval(sweepInterval); sweepInterval = null; }\n if (heartbeatInterval) { clearInterval(heartbeatInterval); heartbeatInterval = null; }\n if (initialized) saveState();\n // Remove event listeners\n for (const { event, handler } of eventListeners) {\n titanEvents.removeListener(event, handler);\n }\n eventListeners.length = 0;\n // Clear all in-memory state for clean re-init\n checkouts.clear();\n budgetPolicies = [];\n registeredAgents.clear();\n activityBuffer.length = 0;\n issues.clear();\n comments.length = 0;\n approvals.clear();\n runs.length = 0;\n issueCounter = 0;\n config = null;\n initialized = false;\n logger.info(COMPONENT, 'Command Post shut down');\n}\n\nexport function isCommandPostEnabled(): boolean {\n return initialized;\n}\n\n// ─── Ancestry Validation ───────────────────────────────────────────────\n\n/**\n * Validate ancestry integrity for a goal — checks for cycles and orphaned\n * parent references. Returns { valid: true } or { valid: false, errors: [...] }.\n */\nexport function validateGoalAncestry(goalId: string): { valid: boolean; errors?: string[] } {\n const errors: string[] = [];\n const goals = listGoals();\n const goalsById = new Map(goals.map(g => [g.id, g]));\n\n // Check goal exists\n const goal = goalsById.get(goalId);\n if (!goal) {\n return { valid: false, errors: [`Goal ${goalId} not found`] };\n }\n\n // Walk ancestry chain and check for cycles\n const visited = new Set<string>();\n let current: Goal | undefined = goal;\n\n while (current) {\n if (visited.has(current.id)) {\n errors.push(`Cycle detected: goal \"${current.id}\" references itself in ancestry chain`);\n return { valid: false, errors };\n }\n visited.add(current.id);\n\n if (current.parentGoalId) {\n const parent = goalsById.get(current.parentGoalId);\n if (!parent) {\n errors.push(`Orphaned parent reference: goal \"${current.id}\" references parent \"${current.parentGoalId}\" which does not exist`);\n return { valid: false, errors };\n }\n current = parent;\n } else {\n break;\n }\n }\n\n // Additional check: goal cannot be its own parent\n if (goal.parentGoalId === goal.id) {\n errors.push(`Self-reference: goal \"${goal.id}\" cannot be its own parent`);\n return { valid: false, errors };\n }\n\n return { valid: true };\n}\n\n/**\n * Validate that setting parentId on a goal would create a valid tree\n * (no cycles, no orphaned parents).\n */\nexport function validateGoalParentAssignment(goalId: string, potentialParentId: string | null): { valid: boolean; errors?: string[] } {\n const errors: string[] = [];\n\n // Can't be own parent\n if (potentialParentId === goalId) {\n errors.push(`Self-reference: goal \"${goalId}\" cannot be its own parent`);\n return { valid: false, errors };\n }\n\n // If parentId is null, goal becomes root — always valid\n if (potentialParentId === null) {\n return { valid: true };\n }\n\n const goals = listGoals();\n const goalsById = new Map(goals.map(g => [g.id, g]));\n\n // Parent must exist\n if (!goalsById.has(potentialParentId)) {\n errors.push(`Orphaned parent: goal \"${potentialParentId}\" does not exist`);\n return { valid: false, errors };\n }\n\n // Check for cycles: walk from potential parent up to root\n const visited = new Set<string>();\n let current: Goal | undefined = goalsById.get(potentialParentId);\n\n while (current) {\n if (visited.has(current.id)) {\n errors.push(`Cycle in parent chain at goal \"${current.id}\"`);\n return { valid: false, errors };\n }\n visited.add(current.id);\n if (current.id === goalId) {\n errors.push(`Cycle detected: setting parent to \"${potentialParentId}\" would create a cycle`);\n return { valid: false, errors };\n }\n current = current.parentGoalId ? goalsById.get(current.parentGoalId) : undefined;\n }\n\n return { valid: true };\n}\n\n// ─── Checkout Sweep ─────────────────────────────────────────────────────\n\n/**\n * Manually trigger expired checkout sweep. Returns count of expired checkouts\n * found and details for audit.\n */\nexport function sweepExpiredCheckoutsManual(): { swept: number; details: { subtaskId: string; agentId: string; goalId: string; expiredAt: string }[] } {\n const details: { subtaskId: string; agentId: string; goalId: string; expiredAt: string }[] = [];\n const now = Date.now();\n\n for (const [id, checkout] of checkouts) {\n if (checkout.status === 'locked' && new Date(checkout.expiresAt).getTime() < now) {\n details.push({\n subtaskId: id,\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n expiredAt: checkout.expiresAt,\n });\n\n checkout.status = 'expired';\n checkouts.delete(id);\n\n addActivity({\n type: 'task_expired',\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n message: `Checkout expired for subtask ${id} (agent: ${checkout.agentId})`,\n });\n\n titanEvents.emit('commandpost:task:expired', { subtaskId: id, agentId: checkout.agentId });\n }\n }\n\n if (details.length > 0) saveState();\n return { swept: details.length, details };\n}\n\n// ─── Stale Agents ────────────────────────────────────────────────────────\n\n/**\n * Detect agents with stale heartbeats (no heartbeat in 2x the heartbeat interval).\n * Returns list of stale agents with their last heartbeat timestamp.\n */\nexport function getStaleAgents(): { id: string; name: string; lastHeartbeat: string; status: string; staleFor: number }[] {\n const interval = config?.heartbeatIntervalMs ?? 60000;\n const threshold = interval * 2;\n const now = Date.now();\n const staleAgents: { id: string; name: string; lastHeartbeat: string; status: string; staleFor: number }[] = [];\n\n for (const [id, agent] of registeredAgents) {\n if (agent.status === 'stopped' || agent.status === 'paused') continue;\n const lastBeat = new Date(agent.lastHeartbeat).getTime();\n const staleMs = now - lastBeat;\n if (staleMs > threshold) {\n staleAgents.push({\n id,\n name: agent.name,\n lastHeartbeat: agent.lastHeartbeat,\n status: agent.status,\n staleFor: Math.floor(staleMs / 1000),\n });\n }\n }\n\n return staleAgents;\n}\n\n// ─── Budget Enforcement API ─────────────────────────────────────────────\n\n/**\n * Enforce budget policy on a specific agent — check current spend vs limit\n * and take action (warn/pause/stop) based on policy config.\n */\nexport function enforceBudgetForAgent(agentId: string): { budgetOk: boolean; policies: { policyId: string; name: string; pct: number; currentSpend: number; limit: number; action: string }[] } {\n const policiesApplied: { policyId: string; name: string; pct: number; currentSpend: number; limit: number; action: string }[] = [];\n\n for (const policy of budgetPolicies) {\n if (!policy.enabled) continue;\n\n // Check if policy applies to this agent\n const applies =\n policy.scope.type === 'global' ||\n (policy.scope.type === 'agent' && policy.scope.targetId === agentId);\n\n if (!applies) continue;\n\n // Reset period if expired\n if (isPeriodExpired(policy)) {\n policy.currentSpend = 0;\n policy.periodStart = new Date().toISOString();\n }\n\n const pct = (policy.currentSpend / policy.limitUsd) * 100;\n policiesApplied.push({\n policyId: policy.id,\n name: policy.name,\n pct,\n currentSpend: policy.currentSpend,\n limit: policy.limitUsd,\n action: policy.action,\n });\n\n // Enforce budget\n if (pct >= 100 && (policy.action === 'pause' || policy.action === 'stop')) {\n addActivity({\n type: 'budget_exceeded',\n agentId,\n message: `Budget \"${policy.name}\" exceeded: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct, action: policy.action },\n });\n\n if (policy.action === 'stop') {\n stopAgent(agentId);\n updateAgentStatus(agentId, 'paused');\n } else if (policy.action === 'pause') {\n updateAgentStatus(agentId, 'paused');\n }\n\n titanEvents.emit('commandpost:budget:exceeded', { policyId: policy.id, agentId, pct, action: policy.action });\n } else if (pct >= policy.warningThresholdPercent) {\n addActivity({\n type: 'budget_warning',\n agentId,\n message: `Budget \"${policy.name}\" at ${pct.toFixed(0)}%: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct },\n });\n titanEvents.emit('commandpost:budget:warning', { policyId: policy.id, agentId, pct });\n }\n }\n\n saveState();\n return {\n budgetOk: policiesApplied.every(p => p.pct < 100),\n policies: policiesApplied,\n };\n}\n\n/**\n * Get budget policy for a specific agent (enriched with usage stats).\n */\nexport function getBudgetPolicyForAgent(agentId: string): { policies: BudgetPolicy[]; totalSpend: number; totalBudget: number; pctUsed: number } {\n const applicablePolicies = budgetPolicies.filter(p =>\n p.enabled && (p.scope.type === 'global' || (p.scope.type === 'agent' && p.scope.targetId === agentId))\n );\n\n const totalSpend = applicablePolicies.reduce((sum, p) => sum + p.currentSpend, 0);\n const totalBudget = applicablePolicies.reduce((sum, p) => sum + p.limitUsd, 0);\n const pctUsed = totalBudget > 0 ? (totalSpend / totalBudget) * 100 : 0;\n\n return {\n policies: applicablePolicies,\n totalSpend,\n totalBudget,\n pctUsed,\n };\n}\n"],"mappings":"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","names":["config"]}
|
|
1
|
+
{"version":3,"sources":["../../src/agent/commandPost.ts"],"sourcesContent":["/**\n * TITAN — Command Post\n * Agent governance layer inspired by Paperclip (paperclipai/paperclip).\n * Provides: atomic task checkout, budget enforcement, goal ancestry,\n * agent registry with heartbeats, and real-time activity feed.\n *\n * Additive layer — wraps existing goals, multi-agent, and cost systems.\n * Gated behind config.commandPost.enabled (defaults false).\n */\nimport { v4 as uuid } from 'uuid';\nimport { existsSync, readFileSync, writeFileSync, appendFileSync } from 'fs';\nimport { spawn } from 'child_process';\nimport { join } from 'path';\nimport { TITAN_HOME } from '../utils/constants.js';\nimport { ensureDir } from '../utils/helpers.js';\nimport { titanEvents } from './daemon.js';\nimport { spawnAgent, stopAgent, listAgents, type AgentInstance } from './multiAgent.js';\nimport { listGoals, type Goal } from './goals.js';\nimport logger from '../utils/logger.js';\nimport type { CommandPostConfig } from '../config/schema.js';\nimport { loadConfig } from '../config/config.js';\nimport { shouldAutoApprove, type ApprovalRule } from './approvalClassifier.js';\n\nconst COMPONENT = 'CommandPost';\nconst STATE_PATH = join(TITAN_HOME, 'command-post.json');\nconst ACTIVITY_PATH = join(TITAN_HOME, 'command-post-activity.jsonl');\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface TaskCheckout {\n subtaskId: string;\n goalId: string;\n agentId: string;\n runId: string;\n checkedOutAt: string;\n expiresAt: string;\n status: 'locked' | 'released' | 'expired';\n}\n\nexport interface BudgetPolicy {\n id: string;\n name: string;\n scope: { type: 'agent' | 'goal' | 'global'; targetId?: string };\n period: 'daily' | 'weekly' | 'monthly';\n limitUsd: number;\n warningThresholdPercent: number;\n action: 'warn' | 'pause' | 'stop';\n currentSpend: number;\n periodStart: string;\n enabled: boolean;\n}\n\nexport interface RegisteredAgent {\n id: string;\n name: string;\n model: string;\n status: 'active' | 'idle' | 'paused' | 'error' | 'stopped';\n lastHeartbeat: string;\n currentTaskId?: string;\n totalTasksCompleted: number;\n totalCostUsd: number;\n createdAt: string;\n // Paperclip org chart fields\n reportsTo?: string;\n role: 'ceo' | 'manager' | 'engineer' | 'researcher' | 'general';\n title?: string;\n /** TITAN identity fields (F2). Optional — absent = fall back to global config.\n * When set, they give the agent a continuous personality across restarts. */\n /** F5-TTS voice clone name (e.g. 'andrew', 'leah', 'jess'). Falls back to config.voice.ttsVoice. */\n voiceId?: string;\n /** Persona file stem from assets/personas/. Falls back to config.agent.persona. */\n personaId?: string;\n /** Extra text prepended to the system prompt when this agent runs. */\n systemPromptOverride?: string;\n /** Hindsight memory network key. Defaults to `agent:${id}`. */\n memoryNamespace?: string;\n /** 1-3 sentence self-description. Seed for future relationship memory. */\n characterSummary?: string;\n /** Sub-agent template this agent was hired with (e.g. 'explorer', 'coder') */\n template?: string;\n}\n\nexport interface ActivityEntry {\n id: string;\n timestamp: string;\n type: 'task_checkout' | 'task_checkin' | 'task_expired' | 'budget_warning' |\n 'budget_exceeded' | 'agent_heartbeat' | 'agent_status_change' |\n 'goal_created' | 'goal_completed' | 'goal_proposal_requested' | 'goal_proposal_rejected' |\n 'autopilot_run' | 'tool_execution' | 'error' | 'issue_deleted' | 'system';\n agentId?: string;\n goalId?: string;\n message: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GoalTreeNode {\n goal: Goal;\n children: GoalTreeNode[];\n depth: number;\n}\n\n// ─── Paperclip: Issue/Ticket System ──────────────────────────────────────\n\nexport interface CPIssue {\n id: string;\n title: string;\n description: string;\n status: 'backlog' | 'todo' | 'in_progress' | 'in_review' | 'done' | 'blocked' | 'cancelled';\n priority: 'critical' | 'high' | 'medium' | 'low';\n assigneeAgentId?: string;\n createdByAgentId?: string;\n createdByUser?: string;\n goalId?: string;\n parentId?: string;\n checkoutRunId?: string;\n issueNumber: number;\n identifier: string; // e.g. \"TIT-42\"\n createdAt: string;\n updatedAt: string;\n startedAt?: string;\n completedAt?: string;\n}\n\nexport interface CPComment {\n id: string;\n issueId: string;\n authorAgentId?: string;\n authorUser?: string;\n body: string;\n createdAt: string;\n}\n\n// ─── Paperclip: Approval System ──────────────────────────────────────────\n\nexport interface CPApproval {\n id: string;\n type: 'hire_agent' | 'budget_override' | 'goal_proposal' | 'soma_proposal' | 'custom';\n status: 'pending' | 'approved' | 'rejected';\n requestedBy: string;\n payload: Record<string, unknown>;\n decidedBy?: string;\n decidedAt?: string;\n decisionNote?: string;\n linkedIssueIds: string[];\n createdAt: string;\n /** Threaded conversation between agent and user */\n thread?: CPComment[];\n /** If set, approval is snoozed until this ISO timestamp */\n snoozedUntil?: string;\n}\n\n// ─── Paperclip: Run Tracking ─────────────────────────────────────────────\n\nexport interface CPRun {\n id: string;\n agentId: string;\n source: 'heartbeat' | 'assignment' | 'manual' | 'autopilot';\n status: 'running' | 'succeeded' | 'failed' | 'error';\n issueId?: string;\n startedAt: string;\n finishedAt?: string;\n durationMs?: number;\n toolsUsed: string[];\n tokenUsage?: { prompt: number; completion: number };\n error?: string;\n}\n\n// ─── Paperclip: Org Tree Node ────────────────────────────────────────────\n\nexport interface OrgNode {\n id: string;\n name: string;\n role: string;\n title?: string;\n status: string;\n model: string;\n reports: OrgNode[];\n}\n\ninterface CommandPostState {\n checkouts: TaskCheckout[];\n budgetPolicies: BudgetPolicy[];\n agents: RegisteredAgent[];\n issues: CPIssue[];\n approvals: CPApproval[];\n runs: CPRun[];\n comments: CPComment[];\n issueCounter: number;\n lastSaved: string;\n}\n\n// ─── State ────────────────────────────────────────────────────────────────\n\nconst checkouts = new Map<string, TaskCheckout>();\nlet budgetPolicies: BudgetPolicy[] = [];\nconst registeredAgents = new Map<string, RegisteredAgent>();\nconst activityBuffer: ActivityEntry[] = [];\nconst issues = new Map<string, CPIssue>();\nconst comments: CPComment[] = [];\nconst approvals = new Map<string, CPApproval>();\nconst runs: CPRun[] = [];\nlet issueCounter = 0;\nlet config: CommandPostConfig | null = null;\nlet sweepInterval: ReturnType<typeof setInterval> | null = null;\nlet heartbeatInterval: ReturnType<typeof setInterval> | null = null;\nlet approvalSweepInterval: ReturnType<typeof setInterval> | null = null;\nlet initialized = false;\nconst eventListeners: Array<{ event: string; handler: (...args: unknown[]) => void }> = [];\n\n// ─── Persistence ──────────────────────────────────────────────────────────\n\nfunction loadState(): void {\n if (!existsSync(STATE_PATH)) return;\n try {\n const raw = readFileSync(STATE_PATH, 'utf-8');\n const state = JSON.parse(raw) as CommandPostState;\n for (const c of state.checkouts || []) {\n if (c.status === 'locked') checkouts.set(c.subtaskId, c);\n }\n budgetPolicies = state.budgetPolicies || [];\n for (const a of state.agents || []) {\n if (!a.role) a.role = 'general'; // backcompat\n registeredAgents.set(a.id, a);\n }\n for (const i of state.issues || []) issues.set(i.id, i);\n for (const a of state.approvals || []) approvals.set(a.id, a);\n runs.push(...(state.runs || []).slice(-200)); // keep last 200 runs\n comments.push(...(state.comments || []));\n issueCounter = state.issueCounter || (state.issues?.length || 0);\n } catch (err) {\n logger.warn(COMPONENT, `Failed to load state: ${(err as Error).message}`);\n }\n}\n\nfunction saveState(): void {\n try {\n ensureDir(TITAN_HOME);\n const state: CommandPostState = {\n checkouts: Array.from(checkouts.values()),\n budgetPolicies,\n agents: Array.from(registeredAgents.values()),\n issues: Array.from(issues.values()),\n approvals: Array.from(approvals.values()),\n runs: runs.slice(-200),\n comments,\n issueCounter,\n lastSaved: new Date().toISOString(),\n };\n writeFileSync(STATE_PATH, JSON.stringify(state, null, 2), 'utf-8');\n } catch (err) {\n logger.error(COMPONENT, `Failed to save state: ${(err as Error).message}`);\n }\n}\n\n// ─── Activity Feed ────────────────────────────────────────────────────────\n\nfunction addActivity(entry: Omit<ActivityEntry, 'id' | 'timestamp'>): void {\n const full: ActivityEntry = {\n id: uuid().slice(0, 12),\n timestamp: new Date().toISOString(),\n ...entry,\n };\n const bufferSize = config?.activityBufferSize ?? 500;\n activityBuffer.push(full);\n if (activityBuffer.length > bufferSize) activityBuffer.shift();\n\n // Append to JSONL file\n try {\n appendFileSync(ACTIVITY_PATH, JSON.stringify(full) + '\\n', 'utf-8');\n } catch { /* non-critical */ }\n\n titanEvents.emit('commandpost:activity', full);\n}\n\nexport function getActivity(opts?: { limit?: number; type?: string }): ActivityEntry[] {\n let entries = [...activityBuffer];\n if (opts?.type) entries = entries.filter(e => e.type === opts.type);\n if (opts?.limit) entries = entries.slice(-opts.limit);\n return entries;\n}\n\n// ─── Task Checkout (Atomic Locking) ──────────────────────────────────────\n\n/**\n * Gap 3 (plan-this-logical-ocean): stale-lock adoption threshold.\n * If the lock-holding agent hasn't heartbeat in this long, a different agent\n * is allowed to adopt the lock instead of being blocked by it. Default 5 min\n * picks up abandoned runs quickly without stealing from agents that are just\n * doing long work (checkoutTimeoutMs default is 30 min — sweep handles those).\n */\nconst STALE_LOCK_ADOPTION_MS = 5 * 60 * 1000;\n\nexport function checkoutTask(goalId: string, subtaskId: string, agentId: string): TaskCheckout | null {\n // Atomic: single-threaded Node.js event loop = synchronous check-and-lock\n const existing = checkouts.get(subtaskId);\n if (existing && existing.status === 'locked') {\n // Same agent re-checking out — adopt (Paperclip dual-run pattern)\n if (existing.agentId === agentId) {\n existing.checkedOutAt = new Date().toISOString();\n existing.expiresAt = new Date(Date.now() + (config?.checkoutTimeoutMs ?? 1800000)).toISOString();\n saveState();\n return existing;\n }\n // Gap 3: different agent — check if the lock-holder is stale.\n // Previously we returned null here, which meant a crashed agent\n // would zombie the subtask for up to checkoutTimeoutMs (30 min)\n // before the sweep cleared it. Now, if the lock-holder's heartbeat\n // is older than STALE_LOCK_ADOPTION_MS, let the new agent take\n // over with a fresh runId. If the holder is not in the agent\n // registry at all (never heartbeat, possibly a test caller or an\n // old persisted checkout), we conservatively treat them as STILL\n // HOLDING — the sweep will clean the lock up after checkoutTimeoutMs.\n // This preserves the existing safety invariant that two different\n // agents can't hold the same subtask simultaneously.\n const holder = registeredAgents.get(existing.agentId);\n if (!holder) return null;\n const holderLastBeat = new Date(holder.lastHeartbeat).getTime();\n const holderStale = Date.now() - holderLastBeat > STALE_LOCK_ADOPTION_MS;\n if (!holderStale) return null;\n\n const adopted: TaskCheckout = {\n ...existing,\n agentId,\n runId: uuid().slice(0, 8),\n checkedOutAt: new Date().toISOString(),\n expiresAt: new Date(Date.now() + (config?.checkoutTimeoutMs ?? 1800000)).toISOString(),\n status: 'locked',\n };\n checkouts.set(subtaskId, adopted);\n saveState();\n addActivity({\n type: 'task_checkout',\n agentId,\n goalId,\n message: `Agent \"${agentId}\" adopted stale lock on ${subtaskId} (prev holder \"${existing.agentId}\" heartbeat ${holder ? Math.round((Date.now() - holderLastBeat) / 1000) + 's ago' : 'missing'})`,\n metadata: { runId: adopted.runId, adoptedFrom: existing.agentId, previousRunId: existing.runId },\n });\n titanEvents.emit('commandpost:task:checkout', adopted);\n return adopted;\n }\n\n const checkout: TaskCheckout = {\n subtaskId,\n goalId,\n agentId,\n runId: uuid().slice(0, 8),\n checkedOutAt: new Date().toISOString(),\n expiresAt: new Date(Date.now() + (config?.checkoutTimeoutMs ?? 1800000)).toISOString(),\n status: 'locked',\n };\n\n checkouts.set(subtaskId, checkout);\n saveState();\n\n addActivity({\n type: 'task_checkout',\n agentId,\n goalId,\n message: `Agent \"${agentId}\" checked out subtask ${subtaskId}`,\n metadata: { runId: checkout.runId },\n });\n\n titanEvents.emit('commandpost:task:checkout', checkout);\n return checkout;\n}\n\nexport function checkinTask(subtaskId: string, runId: string): boolean {\n const checkout = checkouts.get(subtaskId);\n if (!checkout || checkout.runId !== runId) return false;\n\n checkout.status = 'released';\n checkouts.delete(subtaskId);\n saveState();\n\n addActivity({\n type: 'task_checkin',\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n message: `Agent \"${checkout.agentId}\" released subtask ${subtaskId}`,\n });\n\n titanEvents.emit('commandpost:task:checkin', { subtaskId, runId });\n return true;\n}\n\nexport function getActiveCheckouts(): TaskCheckout[] {\n return Array.from(checkouts.values()).filter(c => c.status === 'locked');\n}\n\n/** Get a specific task checkout by subtask ID (for taskQueue lock status). */\nexport function getCheckout(subtaskId: string): TaskCheckout | undefined {\n return checkouts.get(subtaskId);\n}\n\nfunction sweepExpiredCheckouts(): void {\n const now = Date.now();\n for (const [id, checkout] of checkouts) {\n if (checkout.status === 'locked' && new Date(checkout.expiresAt).getTime() < now) {\n checkout.status = 'expired';\n checkouts.delete(id);\n\n addActivity({\n type: 'task_expired',\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n message: `Checkout expired for subtask ${id} (agent: ${checkout.agentId})`,\n });\n\n titanEvents.emit('commandpost:task:expired', { subtaskId: id, agentId: checkout.agentId });\n }\n }\n saveState();\n}\n\n/** Auto-purge stale approvals older than configured retention days */\nfunction sweepStaleApprovals(): void {\n const cfg = loadConfig();\n const retentionDays = Number((cfg as Record<string, unknown>).approvalRetentionDays ?? 7);\n if (retentionDays <= 0) return;\n const cutoff = Date.now() - retentionDays * 86400000;\n let purged = 0;\n for (const [id, approval] of approvals) {\n const age = new Date(approval.createdAt).getTime();\n if (age < cutoff) {\n approvals.delete(id);\n purged++;\n }\n }\n if (purged > 0) {\n saveState();\n logger.info(COMPONENT, `Auto-purged ${purged} stale approval(s) older than ${retentionDays} days`);\n addActivity({\n type: 'issue_deleted',\n message: `Auto-purged ${purged} stale approval(s) older than ${retentionDays} days`,\n metadata: { purged, retentionDays },\n });\n }\n}\n\n/** v5.0.0: Auto-reject ancient pending approvals (> 3 days) so the queue\n * doesn't stall forever on items the user will never see. */\nfunction sweepAncientPendingApprovals(): void {\n const PENDING_MAX_AGE_MS = 3 * 24 * 60 * 60 * 1000; // 3 days\n const cutoff = Date.now() - PENDING_MAX_AGE_MS;\n let rejected = 0;\n for (const [id, approval] of approvals) {\n if (approval.status !== 'pending') continue;\n const age = new Date(approval.createdAt).getTime();\n if (age < cutoff) {\n approval.status = 'rejected';\n approval.decidedBy = 'auto:sweep';\n approval.decidedAt = new Date().toISOString();\n approval.decisionNote = 'Auto-rejected after 3 days in pending queue';\n rejected++;\n }\n }\n if (rejected > 0) {\n saveState();\n logger.info(COMPONENT, `Auto-rejected ${rejected} ancient pending approval(s)`);\n addActivity({\n type: 'goal_proposal_rejected',\n message: `Auto-rejected ${rejected} pending approval(s) older than 3 days`,\n metadata: { rejected },\n });\n }\n}\n\n/** Manual sweep entrypoint for API/admin use */\nexport function sweepStaleApprovalsManual(): { purged: number; retentionDays: number } {\n const before = approvals.size;\n sweepStaleApprovals();\n const purged = before - approvals.size;\n const cfg = loadConfig();\n const retentionDays = Number((cfg as Record<string, unknown>).approvalRetentionDays ?? 7);\n return { purged, retentionDays };\n}\n\n// ─── Budget Policies ─────────────────────────────────────────────────────\n\nexport function createBudgetPolicy(opts: Omit<BudgetPolicy, 'id' | 'currentSpend' | 'periodStart'>): BudgetPolicy {\n const policy: BudgetPolicy = {\n id: uuid().slice(0, 8),\n ...opts,\n currentSpend: 0,\n periodStart: new Date().toISOString(),\n };\n budgetPolicies.push(policy);\n saveState();\n logger.info(COMPONENT, `Budget policy created: \"${policy.name}\" (${policy.scope.type}/${policy.scope.targetId || 'all'}) limit=$${policy.limitUsd}`);\n return policy;\n}\n\nexport function updateBudgetPolicy(id: string, updates: Partial<BudgetPolicy>): BudgetPolicy | null {\n const policy = budgetPolicies.find(p => p.id === id);\n if (!policy) return null;\n Object.assign(policy, updates, { id }); // id is immutable\n saveState();\n return policy;\n}\n\nexport function deleteBudgetPolicy(id: string): boolean {\n const idx = budgetPolicies.findIndex(p => p.id === id);\n if (idx === -1) return false;\n budgetPolicies.splice(idx, 1);\n saveState();\n return true;\n}\n\nexport function getBudgetPolicies(): BudgetPolicy[] {\n return [...budgetPolicies];\n}\n\nexport function recordSpend(agentId: string, goalId: string | undefined, amountUsd: number): void {\n for (const policy of budgetPolicies) {\n if (!policy.enabled) continue;\n\n // Check if policy applies\n const applies =\n policy.scope.type === 'global' ||\n (policy.scope.type === 'agent' && policy.scope.targetId === agentId) ||\n (policy.scope.type === 'goal' && policy.scope.targetId === goalId);\n\n if (!applies) continue;\n\n // Reset period if expired\n if (isPeriodExpired(policy)) {\n policy.currentSpend = 0;\n policy.periodStart = new Date().toISOString();\n }\n\n policy.currentSpend += amountUsd;\n const pct = (policy.currentSpend / policy.limitUsd) * 100;\n\n if (pct >= 100 && (policy.action === 'pause' || policy.action === 'stop')) {\n addActivity({\n type: 'budget_exceeded',\n agentId,\n goalId,\n message: `Budget \"${policy.name}\" exceeded: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct, action: policy.action },\n });\n\n // Enforce budget — actually stop or pause the agent\n if (policy.action === 'stop') {\n stopAgent(agentId);\n updateAgentStatus(agentId, 'paused'); // Budget pause (not manual pause)\n } else if (policy.action === 'pause') {\n updateAgentStatus(agentId, 'paused');\n }\n\n titanEvents.emit('commandpost:budget:exceeded', { policyId: policy.id, agentId, goalId, pct, action: policy.action });\n } else if (pct >= policy.warningThresholdPercent) {\n addActivity({\n type: 'budget_warning',\n agentId,\n goalId,\n message: `Budget \"${policy.name}\" at ${pct.toFixed(0)}%: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct },\n });\n titanEvents.emit('commandpost:budget:warning', { policyId: policy.id, agentId, goalId, pct });\n }\n }\n saveState();\n}\n\nfunction isPeriodExpired(policy: BudgetPolicy): boolean {\n const start = new Date(policy.periodStart).getTime();\n const now = Date.now();\n const msPerDay = 86400000;\n switch (policy.period) {\n case 'daily': return now - start > msPerDay;\n case 'weekly': return now - start > msPerDay * 7;\n case 'monthly': return now - start > msPerDay * 30;\n default: return false;\n }\n}\n\n// ─── Goal Ancestry ───────────────────────────────────────────────────────\n\nexport function getAncestryChain(goalId: string): Goal[] {\n const goals = listGoals();\n const chain: Goal[] = [];\n let current = goals.find(g => g.id === goalId);\n const visited = new Set<string>();\n\n while (current) {\n if (visited.has(current.id)) break; // cycle protection\n visited.add(current.id);\n chain.unshift(current); // root first\n if (!current.parentGoalId) break;\n current = goals.find(g => g.id === current!.parentGoalId);\n }\n return chain;\n}\n\n/**\n * Build ancestry context for a goal — returns the full chain plus depth info.\n * Used by UI to render goal hierarchy breadcrumbs.\n */\nexport function buildAncestryContext(goalId: string): {\n chain: Goal[];\n depth: number;\n rootGoal: Goal | null;\n} {\n const chain = getAncestryChain(goalId);\n return {\n chain,\n depth: chain.length,\n rootGoal: chain.length > 0 ? chain[0] : null,\n };\n}\n\n/**\n * Check if setting parentId on a goal would create a cycle in the ancestry tree.\n */\nexport function wouldCreateCycle(goalId: string, parentId: string): boolean {\n if (goalId === parentId) return true;\n const chain = getAncestryChain(parentId);\n return chain.some(g => g.id === goalId);\n}\n\nexport function getGoalTree(): GoalTreeNode[] {\n const goals = listGoals();\n const goalsById = new Map(goals.map(g => [g.id, g]));\n const childrenMap = new Map<string | undefined, Goal[]>();\n\n for (const g of goals) {\n const parentId = g.parentGoalId || undefined;\n if (!childrenMap.has(parentId)) childrenMap.set(parentId, []);\n childrenMap.get(parentId)!.push(g);\n }\n\n function buildTree(parentId: string | undefined, depth: number): GoalTreeNode[] {\n const children = childrenMap.get(parentId) || [];\n return children.map(goal => ({\n goal,\n children: buildTree(goal.id, depth + 1),\n depth,\n }));\n }\n\n return buildTree(undefined, 0);\n}\n\n// ─── Agent Registry ──────────────────────────────────────────────────────\n\n/**\n * Register a new agent in the Command Post registry.\n * Used by the hire approval flow and syncAgentRegistry.\n */\nexport function registerAgent(opts: {\n id?: string;\n name: string;\n role?: string;\n title?: string;\n model?: string;\n template?: string;\n status?: RegisteredAgent['status'];\n}): RegisteredAgent {\n const id = opts.id || `agent-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;\n const agent: RegisteredAgent = {\n id,\n name: opts.name,\n model: opts.model || '',\n status: opts.status || 'active',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: new Date().toISOString(),\n role: (opts.role || 'general') as RegisteredAgent['role'],\n title: opts.title,\n template: opts.template,\n };\n registeredAgents.set(id, agent);\n saveState();\n return agent;\n}\n\nexport function syncAgentRegistry(): void {\n const liveAgents = listAgents();\n for (const agent of liveAgents) {\n if (!registeredAgents.has(agent.id)) {\n // v4.8.4: the default primary agent is CEO-level (orchestrates\n // the whole org). Everyone else defaults to general. Specialists\n // register with their own explicit role via forceRegisterSpecialist.\n const defaultRole: RegisteredAgent['role'] =\n agent.id === 'default' ? 'ceo' : 'general';\n registeredAgents.set(agent.id, {\n id: agent.id,\n name: agent.name,\n model: agent.model,\n status: agent.status === 'running' ? 'active' : agent.status === 'stopped' ? 'stopped' : 'idle',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: agent.createdAt,\n role: defaultRole,\n title: agent.id === 'default' ? 'Primary orchestrator' : undefined,\n });\n } else {\n // Update live status + heal prior mis-tagged CEO role.\n const reg = registeredAgents.get(agent.id)!;\n reg.model = agent.model;\n if (agent.status === 'running') reg.status = 'active';\n else if (agent.status === 'stopped') reg.status = 'stopped';\n // v4.8.4: if `default` is still tagged 'general' from a prior\n // install, upgrade it to 'ceo' (the intended role).\n if (agent.id === 'default' && reg.role === 'general') {\n reg.role = 'ceo';\n if (!reg.title) reg.title = 'Primary orchestrator';\n }\n }\n }\n saveState();\n}\n\n/**\n * v4.7.0: register a specialist with a PINNED stable ID (not the usual\n * auto-generated `agent-xxx`). Used by the specialist bootstrap so Scout,\n * Builder, Writer, Analyst have reliable IDs across restarts.\n * Idempotent — returns existing agent if already registered.\n */\nexport function forceRegisterSpecialist(opts: {\n id: string;\n name: string;\n role: RegisteredAgent['role'];\n title: string;\n model: string;\n reportsTo?: string;\n}): RegisteredAgent {\n const existing = registeredAgents.get(opts.id);\n if (existing) {\n // v4.8.1: heal specialists stuck in 'error' from the v4.7.0 /\n // pre-v4.8.1 stale-heartbeat bug. A specialist that never did work\n // got flagged as errored after 120s, but it should have stayed\n // 'idle'. On boot we reset it to idle so the registry UI is clean.\n // v4.14.0: also heal 'paused' specialists with no task history —\n // they were likely paused by a now-deleted budget policy or manual\n // action and should be available for work.\n const shouldHeal = (existing.status === 'error' || existing.status === 'paused') && (existing.totalTasksCompleted ?? 0) === 0;\n if (shouldHeal) {\n existing.status = 'idle';\n existing.lastHeartbeat = new Date().toISOString();\n saveState();\n }\n return existing;\n }\n const agent: RegisteredAgent = {\n id: opts.id,\n name: opts.name,\n model: opts.model,\n status: 'idle',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: new Date().toISOString(),\n role: opts.role,\n title: opts.title,\n reportsTo: opts.reportsTo,\n };\n registeredAgents.set(opts.id, agent);\n saveState();\n return agent;\n}\n\nexport function reportHeartbeat(agentId: string): boolean {\n const agent = registeredAgents.get(agentId);\n if (!agent) return false;\n agent.lastHeartbeat = new Date().toISOString();\n if (agent.status === 'error') agent.status = 'active';\n saveState();\n titanEvents.emit('commandpost:agent:heartbeat', { agentId, timestamp: agent.lastHeartbeat });\n return true;\n}\n\nexport function updateAgentStatus(agentId: string, status: RegisteredAgent['status']): boolean {\n const agent = registeredAgents.get(agentId);\n if (!agent) return false;\n const prev = agent.status;\n agent.status = status;\n saveState();\n\n addActivity({\n type: 'agent_status_change',\n agentId,\n message: `Agent \"${agent.name}\" status: ${prev} → ${status}`,\n });\n titanEvents.emit('commandpost:agent:status', { agentId, prev, status });\n return true;\n}\n\nexport function removeAgent(agentId: string): boolean {\n if (agentId === 'default') return false; // Never remove the primary agent\n const agent = registeredAgents.get(agentId);\n if (!agent) return false;\n registeredAgents.delete(agentId);\n saveState();\n addActivity({\n type: 'agent_status_change',\n agentId,\n message: `Agent \"${agent.name}\" removed`,\n });\n titanEvents.emit('commandpost:agent:removed', { agentId, name: agent.name });\n return true;\n}\n\nexport function getRegisteredAgents(): RegisteredAgent[] {\n return Array.from(registeredAgents.values());\n}\n\nfunction checkStaleHeartbeats(): void {\n const interval = config?.heartbeatIntervalMs ?? 60000;\n const threshold = interval * 2;\n const now = Date.now();\n\n for (const [id, agent] of registeredAgents) {\n if (agent.status === 'stopped' || agent.status === 'paused') continue;\n // v4.8.1: idle agents that have never been assigned work shouldn't\n // be flagged as error for not heartbeating.\n // v4.10.0-local: BROADENED — specialists (Scout/Builder/Writer/Analyst)\n // don't self-heartbeat; they only beat when running a task. So ANY\n // specialist with `totalTasksCompleted === 0` should be skipped,\n // regardless of status. Previously status='active' + 0 tasks →\n // immediately marked as error, even though that's the normal\n // resting state for a fresh specialist after unpause.\n if ((agent.totalTasksCompleted ?? 0) === 0) continue;\n const lastBeat = new Date(agent.lastHeartbeat).getTime();\n if (now - lastBeat > threshold && agent.status !== 'error') {\n agent.status = 'error';\n addActivity({\n type: 'agent_status_change',\n agentId: id,\n message: `Agent \"${agent.name}\" heartbeat stale — marked as error`,\n });\n titanEvents.emit('commandpost:agent:status', { agentId: id, prev: 'active', status: 'error' });\n }\n }\n // v4.10.0-local: also self-heal specialists currently stuck in 'error'\n // state with zero completed tasks (means they never actually ran — the\n // stale-heartbeat check put them there). Reset to 'idle' so they're\n // ready to pick up new work.\n for (const [, agent] of registeredAgents) {\n if (agent.status === 'error' && (agent.totalTasksCompleted ?? 0) === 0) {\n agent.status = 'idle';\n }\n }\n saveState();\n}\n\n// ─── Dashboard Aggregation ───────────────────────────────────────────────\n\nexport function getDashboard(): {\n activeAgents: number;\n totalAgents: number;\n activeCheckouts: number;\n budgetUtilization: number;\n recentActivity: ActivityEntry[];\n agents: RegisteredAgent[];\n checkouts: TaskCheckout[];\n budgets: BudgetPolicy[];\n goalTree: GoalTreeNode[];\n} {\n // Re-sync with live agents on every dashboard fetch\n syncAgentRegistry();\n const agents = getRegisteredAgents();\n const activeCheckouts = getActiveCheckouts();\n const budgets = getBudgetPolicies();\n\n // Overall budget utilization (average across enabled policies)\n const enabledBudgets = budgets.filter(b => b.enabled);\n const budgetUtilization = enabledBudgets.length > 0\n ? enabledBudgets.reduce((sum, b) => sum + (b.currentSpend / b.limitUsd) * 100, 0) / enabledBudgets.length\n : 0;\n\n return {\n activeAgents: agents.filter(a => a.status === 'active').length,\n totalAgents: agents.length,\n activeCheckouts: activeCheckouts.length,\n budgetUtilization: Math.round(budgetUtilization),\n recentActivity: activityBuffer.slice(-20),\n agents,\n checkouts: activeCheckouts,\n budgets,\n goalTree: getGoalTree(),\n };\n}\n\n// ─── Lifecycle ───────────────────────────────────────────────────────────\n\nexport function initCommandPost(cfg: CommandPostConfig): void {\n if (initialized) return;\n config = cfg;\n ensureDir(TITAN_HOME);\n loadState();\n syncAgentRegistry();\n\n // Start sweepers\n sweepInterval = setInterval(sweepExpiredCheckouts, 60000);\n sweepInterval.unref();\n approvalSweepInterval = setInterval(() => {\n sweepStaleApprovals();\n sweepAncientPendingApprovals();\n }, 300000); // every 5 min\n approvalSweepInterval.unref();\n heartbeatInterval = setInterval(checkStaleHeartbeats, cfg.heartbeatIntervalMs);\n heartbeatInterval.unref();\n\n // Subscribe to titanEvents for activity feed (track refs for cleanup)\n const onGoalCreated = (data: { goalId: string; title: string; subtasks?: number }) => {\n addActivity({ type: 'goal_created', goalId: data.goalId, message: `Goal created: \"${data.title}\"` });\n };\n const onGoalCompleted = (data: { goalId: string; title: string }) => {\n addActivity({ type: 'goal_completed', goalId: data.goalId, message: `Goal completed: \"${data.title}\"` });\n };\n const onAgentSpawned = (data: { id: string; name: string; model: string }) => {\n registeredAgents.set(data.id, {\n id: data.id,\n name: data.name,\n model: data.model,\n status: 'active',\n lastHeartbeat: new Date().toISOString(),\n totalTasksCompleted: 0,\n totalCostUsd: 0,\n createdAt: new Date().toISOString(),\n role: 'general',\n });\n addActivity({ type: 'agent_status_change', agentId: data.id, message: `Agent \"${data.name}\" spawned` });\n saveState();\n };\n const onAgentStopped = (data: { id: string; name?: string }) => {\n const agent = registeredAgents.get(data.id);\n if (agent) {\n agent.status = 'stopped';\n addActivity({ type: 'agent_status_change', agentId: data.id, message: `Agent \"${agent.name}\" stopped` });\n saveState();\n }\n };\n const onDaemonHeartbeat = () => {\n reportHeartbeat('default');\n };\n\n titanEvents.on('goal:created', onGoalCreated);\n titanEvents.on('goal:completed', onGoalCompleted);\n titanEvents.on('agent:spawned', onAgentSpawned);\n titanEvents.on('agent:stopped', onAgentStopped);\n titanEvents.on('daemon:heartbeat', onDaemonHeartbeat);\n eventListeners.push(\n { event: 'goal:created', handler: onGoalCreated as unknown as (...args: unknown[]) => void },\n { event: 'goal:completed', handler: onGoalCompleted as unknown as (...args: unknown[]) => void },\n { event: 'agent:spawned', handler: onAgentSpawned as unknown as (...args: unknown[]) => void },\n { event: 'agent:stopped', handler: onAgentStopped as unknown as (...args: unknown[]) => void },\n { event: 'daemon:heartbeat', handler: onDaemonHeartbeat as unknown as (...args: unknown[]) => void },\n );\n\n initialized = true;\n logger.info(COMPONENT, `Command Post initialized — ${registeredAgents.size} agents, ${budgetPolicies.length} budget policies, ${checkouts.size} active checkouts`);\n}\n\n// ─── Paperclip: Issue/Ticket System ──────────────────────────────────────\n\nexport function createIssue(opts: {\n title: string; description?: string; priority?: CPIssue['priority'];\n assigneeAgentId?: string; createdByAgentId?: string; createdByUser?: string;\n goalId?: string; parentId?: string;\n}): CPIssue {\n issueCounter++;\n const issue: CPIssue = {\n id: uuid().slice(0, 8),\n title: opts.title,\n description: opts.description || '',\n status: 'backlog',\n priority: opts.priority || 'medium',\n assigneeAgentId: opts.assigneeAgentId,\n createdByAgentId: opts.createdByAgentId,\n createdByUser: opts.createdByUser || 'board',\n goalId: opts.goalId,\n parentId: opts.parentId,\n issueNumber: issueCounter,\n identifier: `TIT-${issueCounter}`,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n issues.set(issue.id, issue);\n // Cap issues map to prevent unbounded memory growth\n if (issues.size > 1000) {\n const sorted = [...issues.entries()].sort((a, b) =>\n new Date(a[1].createdAt).getTime() - new Date(b[1].createdAt).getTime()\n );\n const toRemove = sorted.slice(0, issues.size - 800); // Keep newest 800\n for (const [id] of toRemove) issues.delete(id);\n }\n saveState();\n addActivity({ type: 'goal_created', message: `Issue ${issue.identifier} created: \"${issue.title}\"`, metadata: { issueId: issue.id } });\n return issue;\n}\n\nexport function updateIssue(id: string, updates: Partial<Pick<CPIssue, 'title' | 'description' | 'status' | 'priority' | 'assigneeAgentId' | 'goalId'>>): CPIssue | null {\n const issue = issues.get(id);\n if (!issue) return null;\n const prev = issue.status;\n Object.assign(issue, updates);\n issue.updatedAt = new Date().toISOString();\n if (updates.status === 'in_progress' && !issue.startedAt) issue.startedAt = issue.updatedAt;\n if (updates.status === 'done' && !issue.completedAt) issue.completedAt = issue.updatedAt;\n saveState();\n if (updates.status && updates.status !== prev) {\n addActivity({ type: 'task_checkin', message: `Issue ${issue.identifier} status: ${prev} → ${updates.status}`, metadata: { issueId: id } });\n }\n return issue;\n}\n\nexport function getIssue(id: string): CPIssue | null {\n return issues.get(id) || null;\n}\n\nexport function listIssues(filters?: { status?: string; assigneeAgentId?: string; goalId?: string }): CPIssue[] {\n let result = Array.from(issues.values());\n if (filters?.status) result = result.filter(i => i.status === filters.status);\n if (filters?.assigneeAgentId) result = result.filter(i => i.assigneeAgentId === filters.assigneeAgentId);\n if (filters?.goalId) result = result.filter(i => i.goalId === filters.goalId);\n return result.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n}\n\nexport function deleteIssue(id: string): boolean {\n if (!issues.has(id)) return false;\n issues.delete(id);\n saveState();\n addActivity({ type: 'issue_deleted', agentId: 'user', message: `Issue ${id} deleted` });\n return true;\n}\n\nexport function checkoutIssue(issueId: string, agentId: string): CPIssue | null {\n const issue = issues.get(issueId);\n if (!issue) return null;\n if (issue.status === 'in_progress' && issue.checkoutRunId && issue.assigneeAgentId !== agentId) return null; // 409: locked\n issue.status = 'in_progress';\n issue.assigneeAgentId = agentId;\n issue.checkoutRunId = uuid().slice(0, 8);\n issue.startedAt = issue.startedAt || new Date().toISOString();\n issue.updatedAt = new Date().toISOString();\n saveState();\n addActivity({ type: 'task_checkout', agentId, message: `Agent \"${agentId}\" checked out issue ${issue.identifier}`, metadata: { issueId } });\n return issue;\n}\n\nexport function addIssueComment(issueId: string, body: string, author: { agentId?: string; user?: string }): CPComment | null {\n if (!issues.has(issueId)) return null;\n const comment: CPComment = {\n id: uuid().slice(0, 8),\n issueId,\n authorAgentId: author.agentId,\n authorUser: author.user || 'board',\n body,\n createdAt: new Date().toISOString(),\n };\n comments.push(comment);\n saveState();\n return comment;\n}\n\nexport function getIssueComments(issueId: string): CPComment[] {\n return comments.filter(c => c.issueId === issueId);\n}\n\n/**\n * Full-text search across CP issues, titles, descriptions, and comments.\n * Returns matching issues sorted by relevance (title match > description > comments).\n */\nexport function searchIssues(query: string): CPIssue[] {\n if (!query || query.trim().length < 2) return [];\n const q = query.toLowerCase().trim();\n const scored = Array.from(issues.values()).map(issue => {\n let score = 0;\n const title = (issue.title || '').toLowerCase();\n const desc = (issue.description || '').toLowerCase();\n const issueComments = getIssueComments(issue.id);\n const commentText = issueComments.map(c => (c.body || '').toLowerCase()).join(' ');\n\n if (title.includes(q)) score += 10;\n if (desc.includes(q)) score += 5;\n if (commentText.includes(q)) score += 2;\n if (issue.id.toLowerCase().includes(q)) score += 3;\n\n // Word-boundary bonus\n const words = q.split(/\\s+/);\n for (const word of words) {\n if (word.length < 2) continue;\n if (title.includes(word)) score += 2;\n if (desc.includes(word)) score += 1;\n }\n\n return { issue, score };\n });\n\n return scored\n .filter(s => s.score > 0)\n .sort((a, b) => b.score - a.score)\n .map(s => s.issue);\n}\n\n// ─── Paperclip: Approval System ──────────────────────────────────────────\n\n/**\n * v4.13 coalescing key — generates a stable signature for an approval so\n * autonomous producers that fire on a cron can reuse a pending approval\n * for the same concern instead of piling up duplicates. Keyed on\n * (type, requestedBy, payload.kind, and either goalId or model — the\n * fields that are identity-like for the concern being raised).\n */\nfunction coalesceKey(opts: {\n type: CPApproval['type']; requestedBy: string; payload: Record<string, unknown>;\n}): string {\n const kind = typeof opts.payload.kind === 'string' ? opts.payload.kind : '';\n const goalId = typeof opts.payload.goalId === 'string' ? opts.payload.goalId : '';\n const model = typeof opts.payload.model === 'string' ? opts.payload.model : '';\n const title = typeof opts.payload.title === 'string' ? opts.payload.title : '';\n // Prefer goalId/model when available, otherwise fall back to title. Title-less\n // concerns (e.g. repeating self_repair) get coalesced by (type, requestedBy, kind).\n const identity = goalId || model || title;\n return `${opts.type}|${opts.requestedBy}|${kind}|${identity}`;\n}\n\nexport function createApproval(opts: {\n type: CPApproval['type']; requestedBy: string; payload: Record<string, unknown>;\n linkedIssueIds?: string[];\n}): CPApproval {\n // Gap 4 (plan-this-logical-ocean): path-scoped auto-approval.\n // Before filing, classify the intent. If the configured autoApprove\n // rules say 'auto', short-circuit to an already-approved CPApproval\n // so the thing never reaches the human queue. Off by default — the\n // (config as any).autoApprove check keeps legacy callers happy\n // before the config schema is loaded.\n try {\n const auto = (config as unknown as { autoApprove?: { enabled?: boolean; rules?: unknown[] } })?.autoApprove;\n if (auto?.enabled) {\n const rules = (auto.rules as ApprovalRule[]) || [];\n if (shouldAutoApprove({ type: opts.type, payload: opts.payload }, { enabled: true, rules })) {\n const approved: CPApproval = {\n id: uuid().slice(0, 8),\n type: opts.type,\n status: 'approved',\n requestedBy: opts.requestedBy,\n payload: opts.payload,\n decidedBy: 'auto:path-classifier',\n decidedAt: new Date().toISOString(),\n decisionNote: 'Auto-approved by path-scoped classifier',\n linkedIssueIds: opts.linkedIssueIds || [],\n createdAt: new Date().toISOString(),\n };\n approvals.set(approved.id, approved);\n saveState();\n addActivity({\n type: 'goal_created',\n message: `Approval auto-approved: ${approved.type} (${opts.payload.kind ?? '-'}) from ${opts.requestedBy}`,\n metadata: { approvalId: approved.id, auto: true, path: opts.payload.path ?? null },\n });\n return approved;\n }\n }\n } catch (err) {\n logger.warn(COMPONENT, `Auto-approval classifier error, falling through to human queue: ${(err as Error).message}`);\n }\n\n // Coalesce: if a pending approval already exists for the same concern,\n // update its payload + timestamp and return it instead of filing a new\n // one. Stops autonomous producers (canary-eval, self-repair daemon,\n // auto-heal runner) from flooding the queue with dupes while a human\n // hasn't decided the first one yet.\n const key = coalesceKey(opts);\n for (const existing of approvals.values()) {\n if (existing.status !== 'pending') continue;\n if (coalesceKey({ type: existing.type, requestedBy: existing.requestedBy, payload: existing.payload as Record<string, unknown> }) === key) {\n existing.payload = opts.payload;\n existing.createdAt = new Date().toISOString();\n saveState();\n logger.debug(COMPONENT, `Approval coalesced into ${existing.id} (key=${key})`);\n return existing;\n }\n }\n\n const approval: CPApproval = {\n id: uuid().slice(0, 8),\n type: opts.type,\n status: 'pending',\n requestedBy: opts.requestedBy,\n payload: opts.payload,\n linkedIssueIds: opts.linkedIssueIds || [],\n createdAt: new Date().toISOString(),\n };\n approvals.set(approval.id, approval);\n // Cap approvals map to prevent unbounded memory growth\n if (approvals.size > 500) {\n const sorted = [...approvals.entries()].sort((a, b) =>\n new Date(a[1].createdAt).getTime() - new Date(b[1].createdAt).getTime()\n );\n const toRemove = sorted.slice(0, approvals.size - 400);\n for (const [id] of toRemove) approvals.delete(id);\n }\n saveState();\n addActivity({ type: 'goal_created', message: `Approval requested: ${approval.type} by ${approval.requestedBy}`, metadata: { approvalId: approval.id } });\n return approval;\n}\n\nexport async function approveApproval(id: string, decidedBy: string, note?: string): Promise<CPApproval | null> {\n const approval = approvals.get(id);\n if (!approval || approval.status !== 'pending') return null;\n approval.status = 'approved';\n approval.decidedBy = decidedBy;\n approval.decidedAt = new Date().toISOString();\n approval.decisionNote = note;\n saveState();\n\n // Paperclip competitive gap fix: wire up approval actions\n // Previously hire_agent was dead code — approving a hire didn't create an agent.\n if (approval.type === 'hire_agent') {\n const { name, role, template, model, task } = approval.payload as {\n name?: string; role?: string; template?: string; model?: string; task?: string;\n };\n if (name) {\n // Resolve model: explicit → template tier → config default\n const config = loadConfig();\n const aliases = config.agent.modelAliases || {};\n let resolvedModel = model || '';\n if (!resolvedModel && template) {\n const { SUB_AGENT_TEMPLATES } = await import('./subAgent.js');\n const tmpl = SUB_AGENT_TEMPLATES[template];\n const tier = (tmpl as Record<string, unknown> | undefined)?.tier as string | undefined;\n resolvedModel = tier ? (aliases[tier] || aliases.cloud || '') : (aliases.cloud || '');\n }\n if (!resolvedModel) {\n resolvedModel = config.agent.model || aliases.cloud || 'ollama/kimi-k2.6:cloud';\n }\n\n // Spawn live agent in multi-agent router\n const spawnResult = spawnAgent({\n name,\n model: resolvedModel,\n systemPrompt: template\n ? `You are the ${name} specialist. You were hired with the \"${template}\" template. Execute tasks efficiently and report back when done.`\n : `You are the ${name} agent. Execute tasks efficiently and report back when done.`,\n channelBindings: [{ channel: 'direct', pattern: name }],\n });\n\n if (!spawnResult.success || !spawnResult.agent) {\n logger.error('CommandPost', `[HireApproval] Failed to spawn agent \"${name}\": ${spawnResult.error}`);\n addActivity({ type: 'error', message: `Failed to hire agent \"${name}\": ${spawnResult.error}`, metadata: { approvalId: id } });\n return approval;\n }\n\n // Register in Command Post registry\n const agent = registerAgent({\n id: spawnResult.agent.id, // sync CP id with multiAgent id\n name,\n role: role || 'general',\n title: role || name,\n model: resolvedModel,\n template,\n status: 'active',\n });\n logger.info('CommandPost', `[HireApproval] Agent \"${name}\" hired and activated (model: ${resolvedModel}, approved by ${decidedBy})`);\n addActivity({ type: 'agent_status_change', message: `Agent \"${name}\" hired and activated (model: ${resolvedModel}, approved by ${decidedBy})`, metadata: { approvalId: id, agentId: agent.id } });\n\n // Optionally create a first task issue for the new agent\n if (task) {\n createIssue({\n title: task,\n description: `Initial task assigned on hire (approval ${id})`,\n priority: 'medium',\n assigneeAgentId: agent.id,\n });\n }\n }\n } else if (approval.type === 'budget_override' && approval.payload.agentId) {\n // Resume paused agent\n updateAgentStatus(approval.payload.agentId as string, 'active');\n addActivity({ type: 'goal_completed', message: `Budget override approved for ${approval.payload.agentId} by ${decidedBy}`, metadata: { approvalId: id } });\n } else if (approval.type === 'custom' && (approval.payload as { kind?: string }).kind === 'restart_titan') {\n // v4.13: approval-gated restart. When approved, audit-log the\n // decision THEN async-exec systemctl restart. The current process\n // will die; next boot writes a 'restart_completed' audit entry.\n const reason = (approval.payload as { reason?: string }).reason || 'no reason given';\n try {\n const { logAudit } = await import('../security/auditLog.js');\n logAudit('security_alert', decidedBy, {\n action: 'restart_titan_approved',\n approvalId: id,\n reason,\n requestedBy: approval.requestedBy,\n });\n } catch { /* audit unavailable — still proceed, restart is more important */ }\n logger.info('CommandPost', `[RestartApproval] TITAN restart approved by ${decidedBy}: ${reason}`);\n addActivity({ type: 'goal_completed', message: `Restart approved by ${decidedBy}: ${reason}`, metadata: { approvalId: id } });\n // Fire-and-forget so the approval response returns before systemctl\n // kills this process. The 1500ms delay gives Express time to flush\n // the /api/command-post/approvals/:id/approve response.\n setTimeout(() => {\n try {\n const proc = spawn('sudo', ['-n', 'systemctl', 'restart', 'titan-gateway.service'], {\n detached: true,\n stdio: 'ignore',\n });\n proc.unref();\n } catch (err) {\n logger.error('CommandPost', `[RestartApproval] systemctl restart failed: ${(err as Error).message}`);\n }\n }, 1500).unref();\n } else if (approval.type === 'goal_proposal' || approval.type === 'soma_proposal') {\n const payload = approval.payload as {\n title?: string; description?: string; priority?: number;\n tags?: string[]; parentGoalId?: string;\n subtasks?: Array<{ title: string; description: string; dependsOn?: string[] }>;\n };\n if (!payload.title || !payload.description) {\n logger.warn('CommandPost', `[GoalProposal] Approval ${id} has malformed payload — missing title/description`);\n addActivity({ type: 'error', message: `Goal proposal ${id} approved but payload was malformed`, metadata: { approvalId: id } });\n } else {\n // Dynamic import to avoid circular dependency (goals.ts imports commandPost types)\n try {\n const { createGoal } = await import('./goals.js');\n // v4.8.0: preserve proposer provenance on the goal so the\n // self-mod pipeline can trace goal → drive → proposal.\n // Uses `soma:<drive>` tag convention already established\n // by pressure.ts.\n const enrichedTags = [...(payload.tags || [])];\n if (approval.requestedBy && approval.requestedBy.startsWith('soma:')\n && !enrichedTags.includes(approval.requestedBy)) {\n enrichedTags.push(approval.requestedBy);\n }\n const goal = createGoal({\n title: payload.title!,\n description: payload.description!,\n priority: payload.priority,\n tags: enrichedTags,\n parentGoalId: payload.parentGoalId,\n subtasks: payload.subtasks,\n force: true, // human explicitly approved this proposal\n });\n // Link the goal back to the approval so UI can track progress\n approval.payload = { ...approval.payload, goalId: goal.id };\n saveState();\n addActivity({\n type: 'goal_created',\n goalId: goal.id,\n message: `Goal proposal approved: \"${goal.title}\" (proposed by ${approval.requestedBy}, approved by ${decidedBy})`,\n metadata: { approvalId: id, proposedBy: approval.requestedBy },\n });\n logger.info('CommandPost', `[GoalProposal] Goal ${goal.id} created from approval ${id}`);\n } catch (err) {\n logger.error('CommandPost', `[GoalProposal] Failed to create goal from approval ${id}: ${(err as Error).message}`);\n addActivity({ type: 'error', message: `Goal proposal ${id} creation failed: ${(err as Error).message}`, metadata: { approvalId: id } });\n }\n }\n } else if (\n approval.type === 'custom'\n && (approval.payload as Record<string, unknown>)?.kind === 'self_mod_pr'\n ) {\n // v4.9.0-local.8: apply the staged self-modification PR. Fire-and-forget\n // so the approval call returns immediately; errors land in logs + a\n // follow-up activity entry.\n const payload = approval.payload as Record<string, unknown>;\n const goalId = payload.goalId as string | undefined;\n if (goalId) {\n (async () => {\n try {\n const { applyStagedPR } = await import('./selfModStaging.js');\n const result = await applyStagedPR(goalId);\n const { recordEpisode } = await import('../memory/episodic.js');\n // v4.10.0-local polish: surface Opus verdict in activity + episode\n const opusNote = result.opusReview\n ? ` · Opus ${result.opusReview.verdict} (conf ${result.opusReview.confidence.toFixed(2)})`\n : '';\n if (result.blockedByReview && result.opusReview) {\n recordEpisode({\n kind: 'self_mod_pr_rejected',\n summary: `Self-mod PR BLOCKED by Opus review (goal ${goalId}): ${result.opusReview.reasoning}`,\n detail: `Verdict: ${result.opusReview.verdict}\\nConcerns:\\n${result.opusReview.concerns.join('\\n- ')}\\nSuggestions:\\n${result.opusReview.suggestions.join('\\n- ')}`,\n tags: ['self-mod', 'pr-blocked-by-review', goalId],\n });\n addActivity({\n type: 'error',\n message: `Self-mod PR blocked by Opus review for goal ${goalId}: ${result.opusReview.reasoning.slice(0, 120)}`,\n metadata: { approvalId: id, goalId, opusReview: result.opusReview },\n });\n return;\n }\n recordEpisode({\n kind: 'self_mod_pr_merged',\n summary: `Self-mod PR applied: ${result.applied.length} file(s) landed, ${result.failed.length} failed (goal ${goalId})${opusNote}`,\n detail: `Applied: ${result.applied.join(', ')}\\nFailed: ${result.failed.map(f => `${f.path} (${f.error})`).join(', ') || 'none'}\\n${result.opusReview ? `Opus reasoning: ${result.opusReview.reasoning}` : ''}`,\n tags: ['self-mod', 'pr-merged', goalId],\n });\n addActivity({\n type: 'goal_completed',\n message: `Self-mod PR applied for goal ${goalId}: ${result.applied.length} file(s) → ${resolveSelfModTargetSafe()}, ${result.failed.length} failures${opusNote}`,\n metadata: { approvalId: id, goalId, applied: result.applied, failed: result.failed, opusReview: result.opusReview },\n });\n } catch (err) {\n logger.warn('CommandPost', `[SelfModApply] Failed: ${(err as Error).message}`);\n addActivity({ type: 'error', message: `Self-mod PR apply failed for goal ${goalId}: ${(err as Error).message}`, metadata: { approvalId: id, goalId } });\n }\n })();\n }\n addActivity({ type: 'goal_completed', message: `Self-mod PR approved by ${decidedBy} — applying…`, metadata: { approvalId: id, goalId } });\n } else if (approval.type === 'custom' && (approval.payload as { kind?: string }).kind === 'driver_blocked') {\n const payload = approval.payload as { goalId?: string; goalTitle?: string };\n if (payload.goalId) {\n // Instant-unblock: tick the driver immediately so the user sees\n // TITAN start working right away instead of waiting up to 10s\n // for the next scheduler loop.\n import('./goalDriver.js').then(({ tickDriver }) => {\n tickDriver(payload.goalId!).catch(() => { /* driver may not exist */ });\n }).catch(() => { /* module load failed */ });\n addActivity({\n type: 'goal_completed',\n message: `Driver unblocked for \"${payload.goalTitle || payload.goalId}\" (approved by ${decidedBy})`,\n metadata: { approvalId: id, goalId: payload.goalId },\n });\n logger.info('CommandPost', `[DriverUnblock] Approval ${id} approved — ticking driver for goal ${payload.goalId}`);\n }\n } else {\n addActivity({ type: 'goal_completed', message: `Approval ${approval.type} approved by ${decidedBy}`, metadata: { approvalId: id } });\n }\n\n return approval;\n}\n\n// Small helper so the async apply block can log the resolved target without\n// threading loadConfig through — silently falls back to the default if the\n// config isn't loaded yet for any reason.\nfunction resolveSelfModTargetSafe(): string {\n try {\n const c = loadConfig();\n const sm = (c.autonomy as unknown as { selfMod?: { target?: string } }).selfMod;\n return sm?.target ?? '/opt/TITAN';\n } catch { return '/opt/TITAN'; }\n}\n\n/**\n * Request a hire approval. Creates a pending approval that, when approved,\n * will register the agent and optionally create their first task.\n */\nexport function requestHireApproval(\n requestedBy: string,\n name: string,\n role: string,\n template?: string,\n model?: string,\n task?: string,\n): CPApproval {\n // Use the full approval pipeline (auto-approval classifier + coalescing)\n // instead of manually constructing and inserting a raw approval.\n const approval = createApproval({\n type: 'hire_agent',\n requestedBy,\n payload: { name, role, template, model, task },\n });\n addActivity({ type: 'agent_status_change', message: `Hire approval requested for \"${name}\" (${role}) by ${requestedBy}`, metadata: { approvalId: approval.id } });\n logger.info('CommandPost', `[HireRequest] Pending approval for \"${name}\" (${role}) (id=${approval.id})`);\n return approval;\n}\n\nexport function rejectApproval(id: string, decidedBy: string, note?: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval || approval.status !== 'pending') return null;\n approval.status = 'rejected';\n approval.decidedBy = decidedBy;\n approval.decidedAt = new Date().toISOString();\n approval.decisionNote = note;\n saveState();\n const activityType: ActivityEntry['type'] =\n approval.type === 'goal_proposal' ? 'goal_proposal_rejected' : 'error';\n addActivity({ type: activityType, message: `Approval ${approval.type} rejected by ${decidedBy}${note ? `: ${note}` : ''}`, metadata: { approvalId: id, proposedBy: approval.requestedBy } });\n\n // v4.9.0-local.8: when a self_mod_pr is rejected, archive the staging\n // bundle so the files don't silently linger. Fire-and-forget.\n if (\n approval.type === 'custom'\n && (approval.payload as Record<string, unknown>)?.kind === 'self_mod_pr'\n ) {\n const payload = approval.payload as Record<string, unknown>;\n const goalId = payload.goalId as string | undefined;\n if (goalId) {\n (async () => {\n try {\n const { rejectStagedPR } = await import('./selfModStaging.js');\n const r = rejectStagedPR(goalId, note ?? 'rejected without note');\n const { recordEpisode } = await import('../memory/episodic.js');\n recordEpisode({\n kind: 'self_mod_pr_rejected',\n summary: `Self-mod PR rejected for goal ${goalId}${note ? `: ${note}` : ''}`,\n detail: `Bundle archived: ${r.archived}`,\n tags: ['self-mod', 'pr-rejected', goalId],\n });\n } catch (err) {\n logger.warn('CommandPost', `[SelfModReject] Failed: ${(err as Error).message}`);\n }\n })();\n }\n }\n return approval;\n}\n\n/**\n * Attach a Soma shadow-rehearsal verdict to an existing pending approval.\n * The verdict is merged into the approval payload under `shadowVerdict` so\n * downstream UI (Approvals tab, Soma view) can render it alongside accept/reject.\n * Returns the updated approval or null if the approval doesn't exist / was decided.\n */\nexport function attachShadowVerdictToApproval(\n approvalId: string,\n verdict: Record<string, unknown>,\n): CPApproval | null {\n const approval = approvals.get(approvalId);\n if (!approval || approval.status !== 'pending') return null;\n approval.payload = { ...approval.payload, shadowVerdict: verdict };\n saveState();\n return approval;\n}\n\n// ─── Threaded Inbox: Reply / Snooze / Batch ─────────────────────────────\n\nexport function replyToApproval(id: string, author: string, body: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval) return null;\n const comment: CPComment = {\n id: uuid().slice(0, 8),\n issueId: id,\n authorUser: author,\n body,\n createdAt: new Date().toISOString(),\n };\n if (!approval.thread) approval.thread = [];\n approval.thread.push(comment);\n saveState();\n addActivity({ type: 'system', message: `Reply on approval ${id} by ${author}`, metadata: { approvalId: id } });\n return approval;\n}\n\nexport function snoozeApproval(id: string, until: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval || approval.status !== 'pending') return null;\n approval.snoozedUntil = until;\n saveState();\n return approval;\n}\n\nexport function unsnoozeApproval(id: string): CPApproval | null {\n const approval = approvals.get(id);\n if (!approval) return null;\n delete approval.snoozedUntil;\n saveState();\n return approval;\n}\n\nexport async function batchApprove(ids: string[], decidedBy: string, note?: string): Promise<{ approved: string[]; failed: string[] }> {\n const approved: string[] = [];\n const failed: string[] = [];\n for (const id of ids) {\n const result = await approveApproval(id, decidedBy, note);\n if (result) approved.push(id); else failed.push(id);\n }\n return { approved, failed };\n}\n\nexport function batchReject(ids: string[], decidedBy: string, note?: string): { rejected: string[]; failed: string[] } {\n const rejected: string[] = [];\n const failed: string[] = [];\n for (const id of ids) {\n const result = rejectApproval(id, decidedBy, note);\n if (result) rejected.push(id); else failed.push(id);\n }\n return { rejected, failed };\n}\n\n// ─── Agent-to-User Messaging ─────────────────────────────────────────────\n\nexport interface AgentMessage {\n id: string;\n agentId: string;\n agentName: string;\n userId: string;\n content: string;\n context?: Record<string, unknown>;\n read: boolean;\n createdAt: string;\n}\n\nconst agentMessages: AgentMessage[] = [];\n\nexport function sendAgentMessage(agentId: string, agentName: string, userId: string, content: string, context?: Record<string, unknown>): AgentMessage {\n const msg: AgentMessage = {\n id: uuid().slice(0, 8),\n agentId,\n agentName,\n userId,\n content,\n context,\n read: false,\n createdAt: new Date().toISOString(),\n };\n agentMessages.push(msg);\n if (agentMessages.length > 500) agentMessages.splice(0, agentMessages.length - 500);\n addActivity({ type: 'system', message: `Message from ${agentName}: ${content.slice(0, 100)}`, metadata: { agentId, messageId: msg.id } });\n return msg;\n}\n\nexport function getAgentMessages(agentId?: string, userId?: string, unreadOnly = false): AgentMessage[] {\n return agentMessages.filter(m => {\n if (agentId && m.agentId !== agentId) return false;\n if (userId && m.userId !== userId) return false;\n if (unreadOnly && m.read) return false;\n return true;\n }).slice().reverse();\n}\n\nexport function markAgentMessageRead(id: string): boolean {\n const msg = agentMessages.find(m => m.id === id);\n if (!msg) return false;\n msg.read = true;\n return true;\n}\n\n/**\n * File a goal proposal from an agent. Creates a pending approval that, when\n * approved, becomes a real goal via createGoal(). Used by the goalProposer\n * during the nightly dreaming cycle.\n */\nexport function requestGoalProposalApproval(\n requestedBy: string,\n proposal: {\n title: string;\n description: string;\n rationale?: string;\n priority?: number;\n tags?: string[];\n parentGoalId?: string;\n subtasks?: Array<{ title: string; description: string; dependsOn?: string[] }>;\n },\n type: 'goal_proposal' | 'soma_proposal' = 'goal_proposal'\n): CPApproval {\n // v5.0.0: Pending queue cap — if there are too many pending approvals,\n // auto-reject the oldest ones to prevent the queue from growing without bound.\n const MAX_PENDING_APPROVALS = 30;\n const pending = Array.from(approvals.values()).filter(a => a.status === 'pending');\n if (pending.length >= MAX_PENDING_APPROVALS) {\n // Sort oldest first, reject enough to get back under the cap\n pending.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());\n const toReject = pending.slice(0, pending.length - MAX_PENDING_APPROVALS + 1);\n for (const old of toReject) {\n old.status = 'rejected';\n old.decidedBy = 'auto:cap';\n old.decidedAt = new Date().toISOString();\n old.decisionNote = `Auto-rejected: pending approval cap (${MAX_PENDING_APPROVALS}) reached`;\n logger.info(COMPONENT, `Auto-rejected approval ${old.id} due to pending cap`);\n }\n if (toReject.length > 0) saveState();\n }\n\n // Dedupe: if a pending proposal with the same title already exists\n // (regardless of which agent proposed it), return the existing one\n // instead of filing a duplicate. Multiple specialists running the\n // proposer concurrently were producing 3× the same goals every tick.\n const normalizedTitle = proposal.title.trim().toLowerCase();\n for (const existing of approvals.values()) {\n if (existing.status !== 'pending') continue;\n if (existing.type !== type) continue;\n const existingTitle = ((existing.payload as { title?: string })?.title || '').trim().toLowerCase();\n if (existingTitle && existingTitle === normalizedTitle) {\n logger.debug(COMPONENT, `${type} dedupe: \"${proposal.title}\" already pending (approval ${existing.id}) — returning existing`);\n return existing;\n }\n }\n const approval = createApproval({\n type,\n requestedBy,\n payload: proposal,\n });\n addActivity({\n type: 'goal_proposal_requested',\n agentId: requestedBy,\n message: `Goal proposal filed by ${requestedBy}: \"${proposal.title}\"`,\n metadata: { approvalId: approval.id, rationale: proposal.rationale },\n });\n return approval;\n}\n\nexport function listApprovals(status?: string): CPApproval[] {\n let result = Array.from(approvals.values());\n if (status) result = result.filter(a => a.status === status);\n return result.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n}\n\nexport function getApproval(id: string): CPApproval | null {\n return approvals.get(id) || null;\n}\n\n// ─── v4.10.0-local (Phase B): approval categorization ─────────────\n\nexport type ApprovalUrgency = 'high' | 'medium' | 'low';\nexport type ApprovalCategory =\n | 'driver_blocked' // driver needs human input RIGHT NOW\n | 'self_mod_pr' // code change to TITAN awaiting review\n | 'self_repair' // self-repair daemon proposal\n | 'goal_proposal' // SOMA/proposer wants a new goal active\n | 'hire_agent' // create a new agent\n | 'budget_override' // spend more / continue past limit\n | 'canary_regression' // model quality drift detected\n | 'other';\n\nexport interface CategorizedApproval extends CPApproval {\n category: ApprovalCategory;\n urgency: ApprovalUrgency;\n ageMins: number;\n summary: string;\n}\n\nexport function categorizeApproval(a: CPApproval): CategorizedApproval {\n const payload = a.payload as Record<string, unknown>;\n const kind = payload?.kind as string | undefined;\n // Category\n let category: ApprovalCategory = 'other';\n if (kind === 'driver_blocked') category = 'driver_blocked';\n else if (kind === 'self_mod_pr') category = 'self_mod_pr';\n else if (kind === 'self_repair') category = 'self_repair';\n else if (a.type === 'goal_proposal' || a.type === 'soma_proposal') category = 'goal_proposal';\n else if (a.type === 'hire_agent') category = 'hire_agent';\n else if (a.type === 'budget_override') category = 'budget_override';\n else if (kind === 'canary_regression') category = 'canary_regression';\n\n // Urgency\n let urgency: ApprovalUrgency = 'low';\n if (category === 'driver_blocked' || category === 'canary_regression') urgency = 'high';\n else if (category === 'self_mod_pr' || category === 'self_repair' || category === 'hire_agent') urgency = 'medium';\n // Explicit payload override wins\n if (payload?.urgency === 'high') urgency = 'high';\n if (payload?.urgency === 'medium' && urgency === 'low') urgency = 'medium';\n\n // Summary line for the UI/digest\n const summary =\n (payload?.question as string) ||\n (payload?.title as string) ||\n (payload?.goalTitle as string) ||\n (payload?.reason as string) ||\n a.type;\n\n return {\n ...a,\n category,\n urgency,\n ageMins: Math.round((Date.now() - new Date(a.createdAt).getTime()) / 60_000),\n summary: String(summary).slice(0, 200),\n };\n}\n\nexport function listCategorizedApprovals(status: string = 'pending'): {\n approvals: CategorizedApproval[];\n byCategory: Record<ApprovalCategory, number>;\n byUrgency: Record<ApprovalUrgency, number>;\n} {\n const cats = listApprovals(status).map(categorizeApproval);\n // Sort: urgency desc, age desc\n const urgOrder: Record<ApprovalUrgency, number> = { high: 3, medium: 2, low: 1 };\n cats.sort((a, b) => (urgOrder[b.urgency] - urgOrder[a.urgency]) || (b.ageMins - a.ageMins));\n\n const byCategory: Record<ApprovalCategory, number> = {\n driver_blocked: 0, self_mod_pr: 0, self_repair: 0, goal_proposal: 0,\n hire_agent: 0, budget_override: 0, canary_regression: 0, other: 0,\n };\n const byUrgency: Record<ApprovalUrgency, number> = { high: 0, medium: 0, low: 0 };\n for (const a of cats) {\n byCategory[a.category]++;\n byUrgency[a.urgency]++;\n }\n return { approvals: cats, byCategory, byUrgency };\n}\n\n// ─── Paperclip: Run Tracking ─────────────────────────────────────────────\n\nexport function startRun(agentId: string, source: CPRun['source'], issueId?: string): CPRun {\n const run: CPRun = {\n id: uuid().slice(0, 8),\n agentId,\n source,\n status: 'running',\n issueId,\n startedAt: new Date().toISOString(),\n toolsUsed: [],\n };\n runs.push(run);\n if (runs.length > 500) runs.splice(0, runs.length - 500);\n saveState();\n return run;\n}\n\nexport function endRun(runId: string, result: { status: 'succeeded' | 'failed' | 'error'; toolsUsed?: string[]; tokenUsage?: CPRun['tokenUsage']; error?: string }): CPRun | null {\n const run = runs.find(r => r.id === runId);\n if (!run) return null;\n run.status = result.status;\n run.finishedAt = new Date().toISOString();\n run.durationMs = new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime();\n if (result.toolsUsed) run.toolsUsed = result.toolsUsed;\n if (result.tokenUsage) run.tokenUsage = result.tokenUsage;\n if (result.error) run.error = result.error;\n saveState();\n return run;\n}\n\nexport function listRuns(agentId?: string, limit = 50): CPRun[] {\n let result = [...runs];\n if (agentId) result = result.filter(r => r.agentId === agentId);\n return result.slice(-limit).reverse();\n}\n\n// ─── Paperclip: Org Chart ────────────────────────────────────────────────\n\nexport function getOrgTree(): OrgNode[] {\n const agents = getRegisteredAgents();\n const agentsById = new Map(agents.map(a => [a.id, a]));\n const childrenMap = new Map<string | undefined, RegisteredAgent[]>();\n\n for (const a of agents) {\n const parent = a.reportsTo || undefined;\n if (!childrenMap.has(parent)) childrenMap.set(parent, []);\n childrenMap.get(parent)!.push(a);\n }\n\n function buildTree(parentId: string | undefined): OrgNode[] {\n const children = childrenMap.get(parentId) || [];\n return children.map(a => ({\n id: a.id,\n name: a.name,\n role: a.role,\n title: a.title,\n status: a.status,\n model: a.model,\n reports: buildTree(a.id),\n }));\n }\n\n return buildTree(undefined);\n}\n\n/**\n * Update an agent's persistent identity (F2). Any field omitted is left\n * untouched; pass `null` to explicitly clear a field. Triggers an activity\n * feed entry so the change is auditable.\n */\nexport function updateAgentIdentity(\n agentId: string,\n updates: {\n voiceId?: string | null;\n personaId?: string | null;\n systemPromptOverride?: string | null;\n memoryNamespace?: string | null;\n characterSummary?: string | null;\n model?: string | null;\n },\n): RegisteredAgent | null {\n const agent = registeredAgents.get(agentId);\n if (!agent) return null;\n\n const changed: string[] = [];\n const apply = <K extends 'voiceId' | 'personaId' | 'systemPromptOverride' | 'memoryNamespace' | 'characterSummary' | 'model'>(key: K) => {\n const v = updates[key];\n if (v === undefined) return;\n const before = agent[key];\n if (v === null) delete agent[key];\n else agent[key] = v;\n if (before !== agent[key]) changed.push(key);\n };\n apply('voiceId');\n apply('personaId');\n apply('systemPromptOverride');\n apply('memoryNamespace');\n apply('characterSummary');\n apply('model');\n\n if (changed.length === 0) return agent;\n\n saveState();\n addActivity({\n type: 'agent_status_change',\n agentId,\n message: `Agent \"${agent.name}\" identity updated: ${changed.join(', ')}`,\n metadata: { fields: changed },\n });\n return agent;\n}\n\n/**\n * Resolve the effective Hindsight memory namespace for an agent.\n * Defaults to `agent:${id}` when no explicit namespace is set.\n */\nexport function getAgentMemoryNamespace(agentId: string): string {\n const agent = registeredAgents.get(agentId);\n if (!agent) return `agent:${agentId}`;\n return agent.memoryNamespace || `agent:${agent.id}`;\n}\n\n/**\n * Resolve the effective TTS voice for an agent. Returns the agent's stored\n * voiceId if set, otherwise undefined — callers should fall back to the\n * global config.voice.ttsVoice. Voice-mode plumbing of this getter is\n * tracked separately; F2 ships identity storage + agent.ts + Hindsight\n * scoping only.\n */\nexport function getAgentVoice(agentId: string): string | undefined {\n const agent = registeredAgents.get(agentId);\n return agent?.voiceId;\n}\n\nexport function updateRegisteredAgent(agentId: string, updates: Partial<Pick<RegisteredAgent, 'reportsTo' | 'role' | 'title' | 'name' | 'model'>>): RegisteredAgent | null {\n const agent = registeredAgents.get(agentId);\n if (!agent) return null;\n if (updates.reportsTo !== undefined) agent.reportsTo = updates.reportsTo || undefined;\n if (updates.role) agent.role = updates.role;\n if (updates.title !== undefined) agent.title = updates.title || undefined;\n if (updates.name) agent.name = updates.name;\n if (updates.model !== undefined) agent.model = updates.model || '';\n saveState();\n return agent;\n}\n\nexport function shutdownCommandPost(): void {\n if (sweepInterval) { clearInterval(sweepInterval); sweepInterval = null; }\n if (heartbeatInterval) { clearInterval(heartbeatInterval); heartbeatInterval = null; }\n if (approvalSweepInterval) { clearInterval(approvalSweepInterval); approvalSweepInterval = null; }\n if (initialized) saveState();\n // Remove event listeners\n for (const { event, handler } of eventListeners) {\n titanEvents.removeListener(event, handler);\n }\n eventListeners.length = 0;\n // Clear all in-memory state for clean re-init\n checkouts.clear();\n budgetPolicies = [];\n registeredAgents.clear();\n activityBuffer.length = 0;\n issues.clear();\n comments.length = 0;\n approvals.clear();\n runs.length = 0;\n issueCounter = 0;\n config = null;\n initialized = false;\n logger.info(COMPONENT, 'Command Post shut down');\n}\n\nexport function isCommandPostEnabled(): boolean {\n return initialized;\n}\n\n// ─── Ancestry Validation ───────────────────────────────────────────────\n\n/**\n * Validate ancestry integrity for a goal — checks for cycles and orphaned\n * parent references. Returns { valid: true } or { valid: false, errors: [...] }.\n */\nexport function validateGoalAncestry(goalId: string): { valid: boolean; errors?: string[] } {\n const errors: string[] = [];\n const goals = listGoals();\n const goalsById = new Map(goals.map(g => [g.id, g]));\n\n // Check goal exists\n const goal = goalsById.get(goalId);\n if (!goal) {\n return { valid: false, errors: [`Goal ${goalId} not found`] };\n }\n\n // Walk ancestry chain and check for cycles\n const visited = new Set<string>();\n let current: Goal | undefined = goal;\n\n while (current) {\n if (visited.has(current.id)) {\n errors.push(`Cycle detected: goal \"${current.id}\" references itself in ancestry chain`);\n return { valid: false, errors };\n }\n visited.add(current.id);\n\n if (current.parentGoalId) {\n const parent = goalsById.get(current.parentGoalId);\n if (!parent) {\n errors.push(`Orphaned parent reference: goal \"${current.id}\" references parent \"${current.parentGoalId}\" which does not exist`);\n return { valid: false, errors };\n }\n current = parent;\n } else {\n break;\n }\n }\n\n // Additional check: goal cannot be its own parent\n if (goal.parentGoalId === goal.id) {\n errors.push(`Self-reference: goal \"${goal.id}\" cannot be its own parent`);\n return { valid: false, errors };\n }\n\n return { valid: true };\n}\n\n/**\n * Validate that setting parentId on a goal would create a valid tree\n * (no cycles, no orphaned parents).\n */\nexport function validateGoalParentAssignment(goalId: string, potentialParentId: string | null): { valid: boolean; errors?: string[] } {\n const errors: string[] = [];\n\n // Can't be own parent\n if (potentialParentId === goalId) {\n errors.push(`Self-reference: goal \"${goalId}\" cannot be its own parent`);\n return { valid: false, errors };\n }\n\n // If parentId is null, goal becomes root — always valid\n if (potentialParentId === null) {\n return { valid: true };\n }\n\n const goals = listGoals();\n const goalsById = new Map(goals.map(g => [g.id, g]));\n\n // Parent must exist\n if (!goalsById.has(potentialParentId)) {\n errors.push(`Orphaned parent: goal \"${potentialParentId}\" does not exist`);\n return { valid: false, errors };\n }\n\n // Check for cycles: walk from potential parent up to root\n const visited = new Set<string>();\n let current: Goal | undefined = goalsById.get(potentialParentId);\n\n while (current) {\n if (visited.has(current.id)) {\n errors.push(`Cycle in parent chain at goal \"${current.id}\"`);\n return { valid: false, errors };\n }\n visited.add(current.id);\n if (current.id === goalId) {\n errors.push(`Cycle detected: setting parent to \"${potentialParentId}\" would create a cycle`);\n return { valid: false, errors };\n }\n current = current.parentGoalId ? goalsById.get(current.parentGoalId) : undefined;\n }\n\n return { valid: true };\n}\n\n// ─── Checkout Sweep ─────────────────────────────────────────────────────\n\n/**\n * Manually trigger expired checkout sweep. Returns count of expired checkouts\n * found and details for audit.\n */\nexport function sweepExpiredCheckoutsManual(): { swept: number; details: { subtaskId: string; agentId: string; goalId: string; expiredAt: string }[] } {\n const details: { subtaskId: string; agentId: string; goalId: string; expiredAt: string }[] = [];\n const now = Date.now();\n\n for (const [id, checkout] of checkouts) {\n if (checkout.status === 'locked' && new Date(checkout.expiresAt).getTime() < now) {\n details.push({\n subtaskId: id,\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n expiredAt: checkout.expiresAt,\n });\n\n checkout.status = 'expired';\n checkouts.delete(id);\n\n addActivity({\n type: 'task_expired',\n agentId: checkout.agentId,\n goalId: checkout.goalId,\n message: `Checkout expired for subtask ${id} (agent: ${checkout.agentId})`,\n });\n\n titanEvents.emit('commandpost:task:expired', { subtaskId: id, agentId: checkout.agentId });\n }\n }\n\n if (details.length > 0) saveState();\n return { swept: details.length, details };\n}\n\n// ─── Stale Agents ────────────────────────────────────────────────────────\n\n/**\n * Detect agents with stale heartbeats (no heartbeat in 2x the heartbeat interval).\n * Returns list of stale agents with their last heartbeat timestamp.\n */\nexport function getStaleAgents(): { id: string; name: string; lastHeartbeat: string; status: string; staleFor: number }[] {\n const interval = config?.heartbeatIntervalMs ?? 60000;\n const threshold = interval * 2;\n const now = Date.now();\n const staleAgents: { id: string; name: string; lastHeartbeat: string; status: string; staleFor: number }[] = [];\n\n for (const [id, agent] of registeredAgents) {\n if (agent.status === 'stopped' || agent.status === 'paused') continue;\n const lastBeat = new Date(agent.lastHeartbeat).getTime();\n const staleMs = now - lastBeat;\n if (staleMs > threshold) {\n staleAgents.push({\n id,\n name: agent.name,\n lastHeartbeat: agent.lastHeartbeat,\n status: agent.status,\n staleFor: Math.floor(staleMs / 1000),\n });\n }\n }\n\n return staleAgents;\n}\n\n// ─── Budget Enforcement API ─────────────────────────────────────────────\n\n/**\n * Enforce budget policy on a specific agent — check current spend vs limit\n * and take action (warn/pause/stop) based on policy config.\n */\nexport function enforceBudgetForAgent(agentId: string): { budgetOk: boolean; policies: { policyId: string; name: string; pct: number; currentSpend: number; limit: number; action: string }[] } {\n const policiesApplied: { policyId: string; name: string; pct: number; currentSpend: number; limit: number; action: string }[] = [];\n\n for (const policy of budgetPolicies) {\n if (!policy.enabled) continue;\n\n // Check if policy applies to this agent\n const applies =\n policy.scope.type === 'global' ||\n (policy.scope.type === 'agent' && policy.scope.targetId === agentId);\n\n if (!applies) continue;\n\n // Reset period if expired\n if (isPeriodExpired(policy)) {\n policy.currentSpend = 0;\n policy.periodStart = new Date().toISOString();\n }\n\n const pct = (policy.currentSpend / policy.limitUsd) * 100;\n policiesApplied.push({\n policyId: policy.id,\n name: policy.name,\n pct,\n currentSpend: policy.currentSpend,\n limit: policy.limitUsd,\n action: policy.action,\n });\n\n // Enforce budget\n if (pct >= 100 && (policy.action === 'pause' || policy.action === 'stop')) {\n addActivity({\n type: 'budget_exceeded',\n agentId,\n message: `Budget \"${policy.name}\" exceeded: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct, action: policy.action },\n });\n\n if (policy.action === 'stop') {\n stopAgent(agentId);\n updateAgentStatus(agentId, 'paused');\n } else if (policy.action === 'pause') {\n updateAgentStatus(agentId, 'paused');\n }\n\n titanEvents.emit('commandpost:budget:exceeded', { policyId: policy.id, agentId, pct, action: policy.action });\n } else if (pct >= policy.warningThresholdPercent) {\n addActivity({\n type: 'budget_warning',\n agentId,\n message: `Budget \"${policy.name}\" at ${pct.toFixed(0)}%: $${policy.currentSpend.toFixed(2)}/$${policy.limitUsd.toFixed(2)}`,\n metadata: { policyId: policy.id, pct },\n });\n titanEvents.emit('commandpost:budget:warning', { policyId: policy.id, agentId, pct });\n }\n }\n\n saveState();\n return {\n budgetOk: policiesApplied.every(p => p.pct < 100),\n policies: policiesApplied,\n };\n}\n\n/**\n * Get budget policy for a specific agent (enriched with usage stats).\n */\nexport function getBudgetPolicyForAgent(agentId: string): { policies: BudgetPolicy[]; totalSpend: number; totalBudget: number; pctUsed: number } {\n const applicablePolicies = budgetPolicies.filter(p =>\n p.enabled && (p.scope.type === 'global' || (p.scope.type === 'agent' && p.scope.targetId === agentId))\n );\n\n const totalSpend = applicablePolicies.reduce((sum, p) => sum + p.currentSpend, 0);\n const totalBudget = applicablePolicies.reduce((sum, p) => sum + p.limitUsd, 0);\n const pctUsed = totalBudget > 0 ? (totalSpend / totalBudget) * 100 : 0;\n\n return {\n policies: applicablePolicies,\n totalSpend,\n totalBudget,\n pctUsed,\n };\n}\n"],"mappings":"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","names":["config"]}
|