@stackmemoryai/stackmemory 0.5.33 → 0.5.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/agents/core/agent-task-manager.js.map +1 -1
  2. package/dist/cli/commands/clear.js +1 -1
  3. package/dist/cli/commands/clear.js.map +1 -1
  4. package/dist/cli/commands/context.js +1 -1
  5. package/dist/cli/commands/context.js.map +1 -1
  6. package/dist/cli/commands/dashboard.js.map +1 -1
  7. package/dist/cli/commands/discovery.js +1 -1
  8. package/dist/cli/commands/discovery.js.map +1 -1
  9. package/dist/cli/commands/handoff.js +1 -1
  10. package/dist/cli/commands/handoff.js.map +1 -1
  11. package/dist/cli/commands/monitor.js +1 -1
  12. package/dist/cli/commands/monitor.js.map +1 -1
  13. package/dist/cli/commands/quality.js +1 -1
  14. package/dist/cli/commands/quality.js.map +1 -1
  15. package/dist/cli/commands/skills.js +1 -1
  16. package/dist/cli/commands/skills.js.map +1 -1
  17. package/dist/cli/commands/workflow.js +1 -1
  18. package/dist/cli/commands/workflow.js.map +1 -1
  19. package/dist/cli/commands/worktree.js +1 -1
  20. package/dist/cli/commands/worktree.js.map +1 -1
  21. package/dist/cli/index.js +1 -1
  22. package/dist/cli/index.js.map +1 -1
  23. package/dist/core/context/auto-context.js.map +1 -1
  24. package/dist/core/context/compaction-handler.js.map +2 -2
  25. package/dist/core/context/context-bridge.js.map +2 -2
  26. package/dist/core/context/dual-stack-manager.js +1 -1
  27. package/dist/core/context/dual-stack-manager.js.map +1 -1
  28. package/dist/core/context/enhanced-rehydration.js.map +1 -1
  29. package/dist/core/context/frame-database.js +43 -10
  30. package/dist/core/context/frame-database.js.map +2 -2
  31. package/dist/core/context/frame-handoff-manager.js.map +1 -1
  32. package/dist/core/context/frame-lifecycle-hooks.js +119 -0
  33. package/dist/core/context/frame-lifecycle-hooks.js.map +7 -0
  34. package/dist/core/context/frame-stack.js +36 -7
  35. package/dist/core/context/frame-stack.js.map +2 -2
  36. package/dist/core/context/incremental-gc.js.map +2 -2
  37. package/dist/core/context/index.js +4 -22
  38. package/dist/core/context/index.js.map +2 -2
  39. package/dist/core/context/refactored-frame-manager.js +170 -37
  40. package/dist/core/context/refactored-frame-manager.js.map +3 -3
  41. package/dist/core/context/shared-context-layer.js.map +1 -1
  42. package/dist/core/context/stack-merge-resolver.js.map +1 -1
  43. package/dist/core/database/database-adapter.js.map +1 -1
  44. package/dist/core/database/paradedb-adapter.js.map +1 -1
  45. package/dist/core/database/query-router.js.map +1 -1
  46. package/dist/core/database/sqlite-adapter.js.map +1 -1
  47. package/dist/core/digest/frame-digest-integration.js.map +1 -1
  48. package/dist/core/digest/hybrid-digest-generator.js.map +1 -1
  49. package/dist/core/digest/types.js.map +1 -1
  50. package/dist/core/errors/index.js +249 -0
  51. package/dist/core/errors/index.js.map +2 -2
  52. package/dist/core/frame/workflow-templates.js.map +2 -2
  53. package/dist/core/merge/conflict-detector.js.map +1 -1
  54. package/dist/core/merge/resolution-engine.js.map +1 -1
  55. package/dist/core/merge/stack-diff.js.map +1 -1
  56. package/dist/core/models/model-router.js +10 -1
  57. package/dist/core/models/model-router.js.map +2 -2
  58. package/dist/core/monitoring/error-handler.js +37 -270
  59. package/dist/core/monitoring/error-handler.js.map +3 -3
  60. package/dist/core/monitoring/session-monitor.js.map +1 -1
  61. package/dist/core/performance/lazy-context-loader.js.map +1 -1
  62. package/dist/core/performance/optimized-frame-context.js.map +1 -1
  63. package/dist/core/retrieval/context-retriever.js.map +1 -1
  64. package/dist/core/retrieval/graph-retrieval.js.map +1 -1
  65. package/dist/core/retrieval/hierarchical-retrieval.js.map +1 -1
  66. package/dist/core/retrieval/llm-context-retrieval.js.map +1 -1
  67. package/dist/core/retrieval/retrieval-benchmarks.js.map +1 -1
  68. package/dist/core/retrieval/summary-generator.js.map +1 -1
  69. package/dist/core/retrieval/types.js.map +1 -1
  70. package/dist/core/storage/chromadb-adapter.js.map +1 -1
  71. package/dist/core/storage/infinite-storage.js.map +1 -1
  72. package/dist/core/storage/two-tier-storage.js.map +1 -1
  73. package/dist/features/tasks/task-aware-context.js.map +1 -1
  74. package/dist/features/web/server/index.js +1 -1
  75. package/dist/features/web/server/index.js.map +1 -1
  76. package/dist/hooks/schemas.js +50 -0
  77. package/dist/hooks/schemas.js.map +2 -2
  78. package/dist/hooks/sms-action-runner.js +47 -1
  79. package/dist/hooks/sms-action-runner.js.map +2 -2
  80. package/dist/hooks/sms-notify.js +63 -1
  81. package/dist/hooks/sms-notify.js.map +2 -2
  82. package/dist/hooks/sms-webhook.js +10 -3
  83. package/dist/hooks/sms-webhook.js.map +2 -2
  84. package/dist/hooks/whatsapp-commands.js +172 -69
  85. package/dist/hooks/whatsapp-commands.js.map +2 -2
  86. package/dist/hooks/whatsapp-sync.js +34 -0
  87. package/dist/hooks/whatsapp-sync.js.map +2 -2
  88. package/dist/index.js +1 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/integrations/mcp/handlers/context-handlers.js.map +1 -1
  91. package/dist/integrations/mcp/handlers/discovery-handlers.js.map +1 -1
  92. package/dist/integrations/mcp/server.js +1 -1
  93. package/dist/integrations/mcp/server.js.map +1 -1
  94. package/dist/integrations/ralph/bridge/ralph-stackmemory-bridge.js +1 -1
  95. package/dist/integrations/ralph/bridge/ralph-stackmemory-bridge.js.map +1 -1
  96. package/dist/integrations/ralph/context/stackmemory-context-loader.js +1 -1
  97. package/dist/integrations/ralph/context/stackmemory-context-loader.js.map +1 -1
  98. package/dist/integrations/ralph/learning/pattern-learner.js +1 -1
  99. package/dist/integrations/ralph/learning/pattern-learner.js.map +1 -1
  100. package/dist/integrations/ralph/orchestration/multi-loop-orchestrator.js +1 -1
  101. package/dist/integrations/ralph/orchestration/multi-loop-orchestrator.js.map +1 -1
  102. package/dist/integrations/ralph/swarm/swarm-coordinator.js +1 -1
  103. package/dist/integrations/ralph/swarm/swarm-coordinator.js.map +1 -1
  104. package/dist/integrations/ralph/visualization/ralph-debugger.js +1 -1
  105. package/dist/integrations/ralph/visualization/ralph-debugger.js.map +1 -1
  106. package/dist/mcp/stackmemory-mcp-server.js +1 -1
  107. package/dist/mcp/stackmemory-mcp-server.js.map +1 -1
  108. package/dist/skills/claude-skills.js.map +1 -1
  109. package/dist/skills/recursive-agent-orchestrator.js.map +1 -1
  110. package/dist/skills/unified-rlm-orchestrator.js.map +1 -1
  111. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/agents/core/agent-task-manager.ts"],
4
- "sourcesContent": ["/**\n * Agent Task Manager - Spotify-inspired task handling for StackMemory\n *\n * Integrates Spotify's background coding agent strategies:\n * - 10-turn session limits with automatic task breakdown\n * - Strong verification loops with incremental feedback\n * - Context-aware task prioritization\n * - LLM judge for semantic validation\n */\n\nimport {\n LinearTaskManager,\n PebblesTask,\n TaskStatus,\n TaskPriority,\n} from '../../features/tasks/linear-task-manager.js';\nimport { logger } from '../../core/monitoring/logger.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { TaskError, ErrorCode } from '../../core/errors/index.js';\n\nexport interface AgentTaskSession {\n id: string;\n frameId: string;\n taskId: string;\n turnCount: number;\n maxTurns: number;\n status: 'active' | 'completed' | 'failed' | 'timeout';\n startedAt: Date;\n completedAt?: Date;\n verificationResults: VerificationResult[];\n contextWindow: string[];\n feedbackLoop: FeedbackEntry[];\n}\n\nexport interface VerificationResult {\n verifierId: string;\n passed: boolean;\n message: string;\n severity: 'error' | 'warning' | 'info';\n timestamp: Date;\n autoFix?: string;\n}\n\nexport interface FeedbackEntry {\n turn: number;\n action: string;\n result: string;\n verificationPassed: boolean;\n contextAdjustment?: string;\n}\n\nexport interface TaskBreakdown {\n parentTaskId: string;\n subtasks: SubtaskDefinition[];\n dependencies: Map<string, string[]>;\n estimatedTurns: number;\n}\n\nexport interface SubtaskDefinition {\n title: string;\n description: string;\n acceptanceCriteria: string[];\n estimatedTurns: number;\n verifiers: string[];\n}\n\n/**\n * Supported agent types\n */\nexport enum AgentType {\n FORMATTER = 'formatter',\n SECURITY = 'security',\n TESTING = 'testing',\n PERFORMANCE = 'performance',\n DOCUMENTATION = 'documentation',\n REFACTORING = 'refactoring'\n}\n\n/**\n * Spotify-inspired Agent Task Manager\n */\nexport class AgentTaskManager {\n private taskStore: LinearTaskManager;\n private frameManager: FrameManager;\n private activeSessions: Map<string, AgentTaskSession> = new Map();\n private sessionTimeouts: Map<string, NodeJS.Timeout> = new Map();\n private agentRegistry: Map<AgentType, any> = new Map();\n\n // Spotify strategy constants\n private readonly MAX_TURNS_PER_SESSION = 10;\n private readonly MAX_SESSION_RETRIES = 3;\n private readonly SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n private readonly CONTEXT_WINDOW_SIZE = 5; // Last 5 significant events\n\n constructor(taskStore: LinearTaskManager, frameManager: FrameManager) {\n this.taskStore = taskStore;\n this.frameManager = frameManager;\n }\n\n /**\n * Start a new agent task session with Spotify's 10-turn limit\n */\n async startTaskSession(\n taskId: string,\n frameId: string\n ): Promise<AgentTaskSession> {\n const task = this.taskStore.getTask(taskId);\n if (!task) {\n throw new TaskError(\n `Task ${taskId} not found`,\n ErrorCode.TASK_NOT_FOUND,\n { taskId }\n );\n }\n\n // Check if task needs breakdown (Spotify strategy)\n if (this.needsBreakdown(task)) {\n const breakdown = await this.breakdownTask(task);\n return this.startMultiTaskSession(breakdown, frameId);\n }\n\n const sessionId = this.generateSessionId(taskId);\n const session: AgentTaskSession = {\n id: sessionId,\n frameId,\n taskId,\n turnCount: 0,\n maxTurns: this.MAX_TURNS_PER_SESSION,\n status: 'active',\n startedAt: new Date(),\n verificationResults: [],\n contextWindow: [],\n feedbackLoop: [],\n };\n\n this.activeSessions.set(sessionId, session);\n this.startSessionTimeout(sessionId);\n\n // Update task status\n this.taskStore.updateTaskStatus(\n taskId,\n 'in_progress',\n 'Agent session started'\n );\n\n logger.info('Started agent task session', {\n sessionId,\n taskId,\n taskTitle: task.title,\n maxTurns: this.MAX_TURNS_PER_SESSION,\n });\n\n return session;\n }\n\n /**\n * Execute a turn in the session with verification\n */\n async executeTurn(\n sessionId: string,\n action: string,\n context: Record<string, any>\n ): Promise<{\n success: boolean;\n feedback: string;\n shouldContinue: boolean;\n verificationResults: VerificationResult[];\n }> {\n const session = this.activeSessions.get(sessionId);\n if (!session || session.status !== 'active') {\n throw new TaskError(\n 'Invalid or inactive session',\n ErrorCode.TASK_INVALID_STATE,\n { sessionId }\n );\n }\n\n session.turnCount++;\n\n // Check turn limit (Spotify strategy)\n if (session.turnCount >= session.maxTurns) {\n return this.handleTurnLimitReached(session);\n }\n\n // Execute action with verification loop\n const verificationResults = await this.runVerificationLoop(\n action,\n context,\n session\n );\n\n // Update context window (keep last N significant events)\n this.updateContextWindow(session, action, verificationResults);\n\n // Generate feedback based on verification\n const feedback = this.generateFeedback(verificationResults);\n const success = verificationResults.every(\n (r) => r.passed || r.severity !== 'error'\n );\n\n // Record in feedback loop\n session.feedbackLoop.push({\n turn: session.turnCount,\n action,\n result: feedback,\n verificationPassed: success,\n contextAdjustment:\n this.suggestContextAdjustment(verificationResults) || undefined,\n });\n\n // Determine if should continue\n const shouldContinue = success && session.turnCount < session.maxTurns;\n\n if (!shouldContinue && success) {\n await this.completeSession(session);\n }\n\n return {\n success,\n feedback,\n shouldContinue,\n verificationResults,\n };\n }\n\n /**\n * Run Spotify-style verification loop\n */\n private async runVerificationLoop(\n action: string,\n context: Record<string, any>,\n session: AgentTaskSession\n ): Promise<VerificationResult[]> {\n const results: VerificationResult[] = [];\n\n // Get applicable verifiers based on context\n const verifiers = this.getApplicableVerifiers(context);\n\n for (const verifier of verifiers) {\n const result = await this.runVerifier(verifier, action, context);\n results.push(result);\n session.verificationResults.push(result);\n\n // Stop on critical errors (Spotify strategy)\n if (!result.passed && result.severity === 'error') {\n logger.warn('Verification failed, stopping execution', {\n verifier: result.verifierId,\n message: result.message,\n });\n break;\n }\n }\n\n return results;\n }\n\n /**\n * Get verifiers applicable to current context\n */\n private getApplicableVerifiers(context: Record<string, any>): string[] {\n const verifiers: string[] = [];\n\n // Add verifiers based on context (Spotify's context-aware approach)\n if (context['codeChange']) {\n verifiers.push('formatter', 'linter', 'type-checker');\n }\n if (context['testsPresent']) {\n verifiers.push('test-runner');\n }\n if (context['hasDocumentation']) {\n verifiers.push('doc-validator');\n }\n if (context['performanceCritical']) {\n verifiers.push('performance-analyzer');\n }\n\n // Always include semantic validator (LLM judge from Spotify)\n verifiers.push('semantic-validator');\n\n return verifiers;\n }\n\n /**\n * Run a single verifier\n */\n private async runVerifier(\n verifierId: string,\n action: string,\n context: Record<string, any>\n ): Promise<VerificationResult> {\n // This would integrate with actual verifiers\n // For now, return mock result\n const mockResults: Record<string, () => VerificationResult> = {\n formatter: () => ({\n verifierId: 'formatter',\n passed: Math.random() > 0.1,\n message: 'Code formatting check',\n severity: 'warning',\n timestamp: new Date(),\n autoFix: 'prettier --write',\n }),\n linter: () => ({\n verifierId: 'linter',\n passed: Math.random() > 0.2,\n message: 'Linting check',\n severity: 'error',\n timestamp: new Date(),\n }),\n 'test-runner': () => ({\n verifierId: 'test-runner',\n passed: Math.random() > 0.3,\n message: 'Test execution',\n severity: 'error',\n timestamp: new Date(),\n }),\n 'semantic-validator': () => ({\n verifierId: 'semantic-validator',\n passed: Math.random() > 0.25, // ~75% pass rate like Spotify\n message: 'Semantic validation against original requirements',\n severity: 'error',\n timestamp: new Date(),\n }),\n };\n\n const verifierFn =\n mockResults[verifierId] ||\n (() => ({\n verifierId,\n passed: true,\n message: 'Unknown verifier',\n severity: 'info' as const,\n timestamp: new Date(),\n }));\n\n return verifierFn();\n }\n\n /**\n * Check if task needs breakdown (Spotify strategy for complex tasks)\n */\n private needsBreakdown(task: PebblesTask): boolean {\n // Heuristics for determining if task is too complex\n const indicators = {\n hasMultipleComponents:\n (task.description?.match(/\\band\\b/gi)?.length || 0) > 2,\n longDescription: (task.description?.length || 0) > 500,\n highComplexityTags: task.tags.some((tag) =>\n ['refactor', 'migration', 'architecture', 'redesign'].includes(\n tag.toLowerCase()\n )\n ),\n hasManydependencies: task.depends_on.length > 3,\n };\n\n const complexityScore = Object.values(indicators).filter(Boolean).length;\n return complexityScore >= 2;\n }\n\n /**\n * Break down complex task into subtasks\n */\n private async breakdownTask(task: PebblesTask): Promise<TaskBreakdown> {\n // This would use LLM to intelligently break down the task\n // For now, return a simple breakdown\n const subtasks: SubtaskDefinition[] = [\n {\n title: `Analyze requirements for ${task.title}`,\n description: 'Understand and document requirements',\n acceptanceCriteria: [\n 'Requirements documented',\n 'Constraints identified',\n ],\n estimatedTurns: 2,\n verifiers: ['semantic-validator'],\n },\n {\n title: `Implement core functionality for ${task.title}`,\n description: 'Build the main implementation',\n acceptanceCriteria: ['Core logic implemented', 'Tests passing'],\n estimatedTurns: 5,\n verifiers: ['linter', 'test-runner'],\n },\n {\n title: `Verify and refine ${task.title}`,\n description: 'Final verification and improvements',\n acceptanceCriteria: ['All tests passing', 'Documentation complete'],\n estimatedTurns: 3,\n verifiers: ['formatter', 'linter', 'test-runner', 'semantic-validator'],\n },\n ];\n\n return {\n parentTaskId: task.id,\n subtasks,\n dependencies: new Map([\n [subtasks[1]!.title, [subtasks[0]!.title]],\n [subtasks[2]!.title, [subtasks[1]!.title]],\n ]),\n estimatedTurns: subtasks.reduce((sum, st) => sum + st.estimatedTurns, 0),\n };\n }\n\n /**\n * Start multi-task session for complex tasks\n */\n private async startMultiTaskSession(\n breakdown: TaskBreakdown,\n frameId: string\n ): Promise<AgentTaskSession> {\n // Create subtasks in task store\n const subtaskIds: string[] = [];\n\n for (const subtask of breakdown.subtasks) {\n const subtaskId = this.taskStore.createTask({\n title: subtask.title,\n description: subtask.description,\n frameId,\n parentId: breakdown.parentTaskId,\n tags: ['agent-subtask', ...subtask.verifiers],\n estimatedEffort: subtask.estimatedTurns * 5, // Rough conversion to minutes\n });\n subtaskIds.push(subtaskId);\n }\n\n // Add dependencies\n const titleToId = new Map(\n breakdown.subtasks.map((st, i) => [st.title, subtaskIds[i]])\n );\n\n for (const [title, deps] of breakdown.dependencies) {\n const taskId = titleToId.get(title);\n if (taskId) {\n for (const dep of deps) {\n const depId = titleToId.get(dep);\n if (depId) {\n this.taskStore.addDependency(taskId, depId);\n }\n }\n }\n }\n\n // Start session for first subtask\n return this.startTaskSession(subtaskIds[0]!, frameId);\n }\n\n /**\n * Update context window with significant events\n */\n private updateContextWindow(\n session: AgentTaskSession,\n action: string,\n verificationResults: VerificationResult[]\n ): void {\n const significantEvent = {\n turn: session.turnCount,\n action: action.substring(0, 100),\n verificationSummary: verificationResults.map((r) => ({\n verifier: r.verifierId,\n passed: r.passed,\n })),\n timestamp: new Date().toISOString(),\n };\n\n session.contextWindow.push(JSON.stringify(significantEvent));\n\n // Keep only last N events (Spotify's context window optimization)\n if (session.contextWindow.length > this.CONTEXT_WINDOW_SIZE) {\n session.contextWindow = session.contextWindow.slice(\n -this.CONTEXT_WINDOW_SIZE\n );\n }\n }\n\n /**\n * Generate feedback from verification results\n */\n private generateFeedback(results: VerificationResult[]): string {\n const failed = results.filter((r) => !r.passed);\n const warnings = results.filter(\n (r) => !r.passed && r.severity === 'warning'\n );\n const errors = results.filter((r) => !r.passed && r.severity === 'error');\n\n if (errors.length > 0) {\n const errorMessages = errors.map((e) => `- ${e.message}`).join('\\n');\n return `Verification failed with ${errors.length} error(s):\\n${errorMessages}`;\n }\n\n if (warnings.length > 0) {\n const warningMessages = warnings.map((w) => `- ${w.message}`).join('\\n');\n return `Verification passed with ${warnings.length} warning(s):\\n${warningMessages}`;\n }\n\n return 'All verifications passed successfully';\n }\n\n /**\n * Suggest context adjustment based on verification results\n */\n private suggestContextAdjustment(\n results: VerificationResult[]\n ): string | undefined {\n const failed = results.filter((r) => !r.passed && r.severity === 'error');\n\n if (failed.length === 0) {\n return undefined;\n }\n\n // Generate suggestions based on failure patterns\n const suggestions: string[] = [];\n\n if (failed.some((r) => r.verifierId === 'test-runner')) {\n suggestions.push('Focus on fixing failing tests');\n }\n if (failed.some((r) => r.verifierId === 'linter')) {\n suggestions.push('Address linting errors before proceeding');\n }\n if (failed.some((r) => r.verifierId === 'semantic-validator')) {\n suggestions.push('Review original requirements and adjust approach');\n }\n\n return suggestions.length > 0 ? suggestions.join('; ') : undefined;\n }\n\n /**\n * Handle turn limit reached\n */\n private async handleTurnLimitReached(session: AgentTaskSession): Promise<{\n success: boolean;\n feedback: string;\n shouldContinue: boolean;\n verificationResults: VerificationResult[];\n }> {\n logger.warn('Session reached turn limit', {\n sessionId: session.id,\n taskId: session.taskId,\n turnCount: session.turnCount,\n });\n\n // Check if task can be considered complete\n const task = this.taskStore.getTask(session.taskId);\n const isComplete = this.assessTaskCompletion(session);\n\n if (isComplete) {\n await this.completeSession(session);\n return {\n success: true,\n feedback: 'Task completed successfully within turn limit',\n shouldContinue: false,\n verificationResults: [],\n };\n }\n\n // Mark session as timeout\n session.status = 'timeout';\n this.taskStore.updateTaskStatus(\n session.taskId,\n 'blocked',\n 'Session timeout - manual review needed'\n );\n\n return {\n success: false,\n feedback: `Session reached ${this.MAX_TURNS_PER_SESSION} turn limit. Task requires manual review or retry.`,\n shouldContinue: false,\n verificationResults: [],\n };\n }\n\n /**\n * Assess if task is complete enough\n */\n private assessTaskCompletion(session: AgentTaskSession): boolean {\n // Check if recent verifications are passing\n const recentResults = session.verificationResults.slice(-5);\n const recentPassRate =\n recentResults.filter((r) => r.passed).length / recentResults.length;\n\n // Check if semantic validator passed recently (Spotify's LLM judge)\n const semanticPassed = recentResults.some(\n (r) => r.verifierId === 'semantic-validator' && r.passed\n );\n\n return recentPassRate >= 0.8 && semanticPassed;\n }\n\n /**\n * Complete a session\n */\n private async completeSession(session: AgentTaskSession): Promise<void> {\n session.status = 'completed';\n session.completedAt = new Date();\n\n // Update task status\n this.taskStore.updateTaskStatus(\n session.taskId,\n 'completed',\n 'Agent session completed'\n );\n\n // Clear timeout\n const timeout = this.sessionTimeouts.get(session.id);\n if (timeout) {\n clearTimeout(timeout);\n this.sessionTimeouts.delete(session.id);\n }\n\n // Generate and save session summary to frame\n const summary = this.generateSessionSummary(session);\n this.frameManager.addEvent('observation', {\n type: 'session_summary',\n frameId: session.frameId,\n summary,\n });\n\n logger.info('Session completed', {\n sessionId: session.id,\n taskId: session.taskId,\n turnCount: session.turnCount,\n duration: session.completedAt.getTime() - session.startedAt.getTime(),\n });\n }\n\n /**\n * Generate session summary for frame digest\n */\n private generateSessionSummary(\n session: AgentTaskSession\n ): Record<string, any> {\n const verificationStats = {\n total: session.verificationResults.length,\n passed: session.verificationResults.filter((r) => r.passed).length,\n failed: session.verificationResults.filter((r) => !r.passed).length,\n };\n\n return {\n sessionId: session.id,\n taskId: session.taskId,\n status: session.status,\n turnCount: session.turnCount,\n duration: session.completedAt\n ? session.completedAt.getTime() - session.startedAt.getTime()\n : 0,\n verificationStats,\n feedbackLoop: session.feedbackLoop.slice(-3), // Last 3 feedback entries\n contextWindow: session.contextWindow.slice(-2), // Last 2 context entries\n };\n }\n\n /**\n * Start timeout for session\n */\n private startSessionTimeout(sessionId: string): void {\n const timeout = setTimeout(() => {\n const session = this.activeSessions.get(sessionId);\n if (session && session.status === 'active') {\n session.status = 'timeout';\n this.taskStore.updateTaskStatus(\n session.taskId,\n 'blocked',\n 'Session timeout - no activity'\n );\n logger.warn('Session timed out due to inactivity', { sessionId });\n }\n }, this.SESSION_TIMEOUT_MS);\n\n this.sessionTimeouts.set(sessionId, timeout);\n }\n\n /**\n * Generate unique session ID\n */\n private generateSessionId(taskId: string): string {\n return `session-${taskId}-${Date.now()}`;\n }\n\n /**\n * Get active sessions summary\n */\n getActiveSessions(): Array<{\n sessionId: string;\n taskId: string;\n turnCount: number;\n status: string;\n startedAt: Date;\n }> {\n return Array.from(this.activeSessions.values()).map((session) => ({\n sessionId: session.id,\n taskId: session.taskId,\n turnCount: session.turnCount,\n status: session.status,\n startedAt: session.startedAt,\n }));\n }\n\n /**\n * Retry a failed session (Spotify's 3-retry strategy)\n */\n async retrySession(sessionId: string): Promise<AgentTaskSession | null> {\n const session = this.activeSessions.get(sessionId);\n if (!session || session.status === 'active') {\n return null;\n }\n\n // Count previous retries\n const retryCount = Array.from(this.activeSessions.values()).filter(\n (s) => s.taskId === session.taskId && s.status === 'failed'\n ).length;\n\n if (retryCount >= this.MAX_SESSION_RETRIES) {\n logger.warn('Max retries reached for task', {\n taskId: session.taskId,\n retries: retryCount,\n });\n return null;\n }\n\n // Start new session with learned context\n const newSession = await this.startTaskSession(\n session.taskId,\n session.frameId\n );\n\n // Transfer learned context from previous session\n newSession.contextWindow = session.contextWindow.slice(-3);\n newSession.feedbackLoop = [\n {\n turn: 0,\n action: 'Session retry with learned context',\n result: `Retrying after ${retryCount} previous attempts`,\n verificationPassed: true,\n contextAdjustment: session.feedbackLoop\n .filter((f) => f.contextAdjustment)\n .map((f) => f.contextAdjustment)\n .join('; '),\n },\n ];\n\n return newSession;\n }\n}\n"],
4
+ "sourcesContent": ["/**\n * Agent Task Manager - Spotify-inspired task handling for StackMemory\n *\n * Integrates Spotify's background coding agent strategies:\n * - 10-turn session limits with automatic task breakdown\n * - Strong verification loops with incremental feedback\n * - Context-aware task prioritization\n * - LLM judge for semantic validation\n */\n\nimport {\n LinearTaskManager,\n PebblesTask,\n TaskStatus,\n TaskPriority,\n} from '../../features/tasks/linear-task-manager.js';\nimport { logger } from '../../core/monitoring/logger.js';\nimport { FrameManager } from '../../core/context/index.js';\nimport { TaskError, ErrorCode } from '../../core/errors/index.js';\n\nexport interface AgentTaskSession {\n id: string;\n frameId: string;\n taskId: string;\n turnCount: number;\n maxTurns: number;\n status: 'active' | 'completed' | 'failed' | 'timeout';\n startedAt: Date;\n completedAt?: Date;\n verificationResults: VerificationResult[];\n contextWindow: string[];\n feedbackLoop: FeedbackEntry[];\n}\n\nexport interface VerificationResult {\n verifierId: string;\n passed: boolean;\n message: string;\n severity: 'error' | 'warning' | 'info';\n timestamp: Date;\n autoFix?: string;\n}\n\nexport interface FeedbackEntry {\n turn: number;\n action: string;\n result: string;\n verificationPassed: boolean;\n contextAdjustment?: string;\n}\n\nexport interface TaskBreakdown {\n parentTaskId: string;\n subtasks: SubtaskDefinition[];\n dependencies: Map<string, string[]>;\n estimatedTurns: number;\n}\n\nexport interface SubtaskDefinition {\n title: string;\n description: string;\n acceptanceCriteria: string[];\n estimatedTurns: number;\n verifiers: string[];\n}\n\n/**\n * Supported agent types\n */\nexport enum AgentType {\n FORMATTER = 'formatter',\n SECURITY = 'security',\n TESTING = 'testing',\n PERFORMANCE = 'performance',\n DOCUMENTATION = 'documentation',\n REFACTORING = 'refactoring'\n}\n\n/**\n * Spotify-inspired Agent Task Manager\n */\nexport class AgentTaskManager {\n private taskStore: LinearTaskManager;\n private frameManager: FrameManager;\n private activeSessions: Map<string, AgentTaskSession> = new Map();\n private sessionTimeouts: Map<string, NodeJS.Timeout> = new Map();\n private agentRegistry: Map<AgentType, any> = new Map();\n\n // Spotify strategy constants\n private readonly MAX_TURNS_PER_SESSION = 10;\n private readonly MAX_SESSION_RETRIES = 3;\n private readonly SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n private readonly CONTEXT_WINDOW_SIZE = 5; // Last 5 significant events\n\n constructor(taskStore: LinearTaskManager, frameManager: FrameManager) {\n this.taskStore = taskStore;\n this.frameManager = frameManager;\n }\n\n /**\n * Start a new agent task session with Spotify's 10-turn limit\n */\n async startTaskSession(\n taskId: string,\n frameId: string\n ): Promise<AgentTaskSession> {\n const task = this.taskStore.getTask(taskId);\n if (!task) {\n throw new TaskError(\n `Task ${taskId} not found`,\n ErrorCode.TASK_NOT_FOUND,\n { taskId }\n );\n }\n\n // Check if task needs breakdown (Spotify strategy)\n if (this.needsBreakdown(task)) {\n const breakdown = await this.breakdownTask(task);\n return this.startMultiTaskSession(breakdown, frameId);\n }\n\n const sessionId = this.generateSessionId(taskId);\n const session: AgentTaskSession = {\n id: sessionId,\n frameId,\n taskId,\n turnCount: 0,\n maxTurns: this.MAX_TURNS_PER_SESSION,\n status: 'active',\n startedAt: new Date(),\n verificationResults: [],\n contextWindow: [],\n feedbackLoop: [],\n };\n\n this.activeSessions.set(sessionId, session);\n this.startSessionTimeout(sessionId);\n\n // Update task status\n this.taskStore.updateTaskStatus(\n taskId,\n 'in_progress',\n 'Agent session started'\n );\n\n logger.info('Started agent task session', {\n sessionId,\n taskId,\n taskTitle: task.title,\n maxTurns: this.MAX_TURNS_PER_SESSION,\n });\n\n return session;\n }\n\n /**\n * Execute a turn in the session with verification\n */\n async executeTurn(\n sessionId: string,\n action: string,\n context: Record<string, any>\n ): Promise<{\n success: boolean;\n feedback: string;\n shouldContinue: boolean;\n verificationResults: VerificationResult[];\n }> {\n const session = this.activeSessions.get(sessionId);\n if (!session || session.status !== 'active') {\n throw new TaskError(\n 'Invalid or inactive session',\n ErrorCode.TASK_INVALID_STATE,\n { sessionId }\n );\n }\n\n session.turnCount++;\n\n // Check turn limit (Spotify strategy)\n if (session.turnCount >= session.maxTurns) {\n return this.handleTurnLimitReached(session);\n }\n\n // Execute action with verification loop\n const verificationResults = await this.runVerificationLoop(\n action,\n context,\n session\n );\n\n // Update context window (keep last N significant events)\n this.updateContextWindow(session, action, verificationResults);\n\n // Generate feedback based on verification\n const feedback = this.generateFeedback(verificationResults);\n const success = verificationResults.every(\n (r) => r.passed || r.severity !== 'error'\n );\n\n // Record in feedback loop\n session.feedbackLoop.push({\n turn: session.turnCount,\n action,\n result: feedback,\n verificationPassed: success,\n contextAdjustment:\n this.suggestContextAdjustment(verificationResults) || undefined,\n });\n\n // Determine if should continue\n const shouldContinue = success && session.turnCount < session.maxTurns;\n\n if (!shouldContinue && success) {\n await this.completeSession(session);\n }\n\n return {\n success,\n feedback,\n shouldContinue,\n verificationResults,\n };\n }\n\n /**\n * Run Spotify-style verification loop\n */\n private async runVerificationLoop(\n action: string,\n context: Record<string, any>,\n session: AgentTaskSession\n ): Promise<VerificationResult[]> {\n const results: VerificationResult[] = [];\n\n // Get applicable verifiers based on context\n const verifiers = this.getApplicableVerifiers(context);\n\n for (const verifier of verifiers) {\n const result = await this.runVerifier(verifier, action, context);\n results.push(result);\n session.verificationResults.push(result);\n\n // Stop on critical errors (Spotify strategy)\n if (!result.passed && result.severity === 'error') {\n logger.warn('Verification failed, stopping execution', {\n verifier: result.verifierId,\n message: result.message,\n });\n break;\n }\n }\n\n return results;\n }\n\n /**\n * Get verifiers applicable to current context\n */\n private getApplicableVerifiers(context: Record<string, any>): string[] {\n const verifiers: string[] = [];\n\n // Add verifiers based on context (Spotify's context-aware approach)\n if (context['codeChange']) {\n verifiers.push('formatter', 'linter', 'type-checker');\n }\n if (context['testsPresent']) {\n verifiers.push('test-runner');\n }\n if (context['hasDocumentation']) {\n verifiers.push('doc-validator');\n }\n if (context['performanceCritical']) {\n verifiers.push('performance-analyzer');\n }\n\n // Always include semantic validator (LLM judge from Spotify)\n verifiers.push('semantic-validator');\n\n return verifiers;\n }\n\n /**\n * Run a single verifier\n */\n private async runVerifier(\n verifierId: string,\n action: string,\n context: Record<string, any>\n ): Promise<VerificationResult> {\n // This would integrate with actual verifiers\n // For now, return mock result\n const mockResults: Record<string, () => VerificationResult> = {\n formatter: () => ({\n verifierId: 'formatter',\n passed: Math.random() > 0.1,\n message: 'Code formatting check',\n severity: 'warning',\n timestamp: new Date(),\n autoFix: 'prettier --write',\n }),\n linter: () => ({\n verifierId: 'linter',\n passed: Math.random() > 0.2,\n message: 'Linting check',\n severity: 'error',\n timestamp: new Date(),\n }),\n 'test-runner': () => ({\n verifierId: 'test-runner',\n passed: Math.random() > 0.3,\n message: 'Test execution',\n severity: 'error',\n timestamp: new Date(),\n }),\n 'semantic-validator': () => ({\n verifierId: 'semantic-validator',\n passed: Math.random() > 0.25, // ~75% pass rate like Spotify\n message: 'Semantic validation against original requirements',\n severity: 'error',\n timestamp: new Date(),\n }),\n };\n\n const verifierFn =\n mockResults[verifierId] ||\n (() => ({\n verifierId,\n passed: true,\n message: 'Unknown verifier',\n severity: 'info' as const,\n timestamp: new Date(),\n }));\n\n return verifierFn();\n }\n\n /**\n * Check if task needs breakdown (Spotify strategy for complex tasks)\n */\n private needsBreakdown(task: PebblesTask): boolean {\n // Heuristics for determining if task is too complex\n const indicators = {\n hasMultipleComponents:\n (task.description?.match(/\\band\\b/gi)?.length || 0) > 2,\n longDescription: (task.description?.length || 0) > 500,\n highComplexityTags: task.tags.some((tag) =>\n ['refactor', 'migration', 'architecture', 'redesign'].includes(\n tag.toLowerCase()\n )\n ),\n hasManydependencies: task.depends_on.length > 3,\n };\n\n const complexityScore = Object.values(indicators).filter(Boolean).length;\n return complexityScore >= 2;\n }\n\n /**\n * Break down complex task into subtasks\n */\n private async breakdownTask(task: PebblesTask): Promise<TaskBreakdown> {\n // This would use LLM to intelligently break down the task\n // For now, return a simple breakdown\n const subtasks: SubtaskDefinition[] = [\n {\n title: `Analyze requirements for ${task.title}`,\n description: 'Understand and document requirements',\n acceptanceCriteria: [\n 'Requirements documented',\n 'Constraints identified',\n ],\n estimatedTurns: 2,\n verifiers: ['semantic-validator'],\n },\n {\n title: `Implement core functionality for ${task.title}`,\n description: 'Build the main implementation',\n acceptanceCriteria: ['Core logic implemented', 'Tests passing'],\n estimatedTurns: 5,\n verifiers: ['linter', 'test-runner'],\n },\n {\n title: `Verify and refine ${task.title}`,\n description: 'Final verification and improvements',\n acceptanceCriteria: ['All tests passing', 'Documentation complete'],\n estimatedTurns: 3,\n verifiers: ['formatter', 'linter', 'test-runner', 'semantic-validator'],\n },\n ];\n\n return {\n parentTaskId: task.id,\n subtasks,\n dependencies: new Map([\n [subtasks[1]!.title, [subtasks[0]!.title]],\n [subtasks[2]!.title, [subtasks[1]!.title]],\n ]),\n estimatedTurns: subtasks.reduce((sum, st) => sum + st.estimatedTurns, 0),\n };\n }\n\n /**\n * Start multi-task session for complex tasks\n */\n private async startMultiTaskSession(\n breakdown: TaskBreakdown,\n frameId: string\n ): Promise<AgentTaskSession> {\n // Create subtasks in task store\n const subtaskIds: string[] = [];\n\n for (const subtask of breakdown.subtasks) {\n const subtaskId = this.taskStore.createTask({\n title: subtask.title,\n description: subtask.description,\n frameId,\n parentId: breakdown.parentTaskId,\n tags: ['agent-subtask', ...subtask.verifiers],\n estimatedEffort: subtask.estimatedTurns * 5, // Rough conversion to minutes\n });\n subtaskIds.push(subtaskId);\n }\n\n // Add dependencies\n const titleToId = new Map(\n breakdown.subtasks.map((st, i) => [st.title, subtaskIds[i]])\n );\n\n for (const [title, deps] of breakdown.dependencies) {\n const taskId = titleToId.get(title);\n if (taskId) {\n for (const dep of deps) {\n const depId = titleToId.get(dep);\n if (depId) {\n this.taskStore.addDependency(taskId, depId);\n }\n }\n }\n }\n\n // Start session for first subtask\n return this.startTaskSession(subtaskIds[0]!, frameId);\n }\n\n /**\n * Update context window with significant events\n */\n private updateContextWindow(\n session: AgentTaskSession,\n action: string,\n verificationResults: VerificationResult[]\n ): void {\n const significantEvent = {\n turn: session.turnCount,\n action: action.substring(0, 100),\n verificationSummary: verificationResults.map((r) => ({\n verifier: r.verifierId,\n passed: r.passed,\n })),\n timestamp: new Date().toISOString(),\n };\n\n session.contextWindow.push(JSON.stringify(significantEvent));\n\n // Keep only last N events (Spotify's context window optimization)\n if (session.contextWindow.length > this.CONTEXT_WINDOW_SIZE) {\n session.contextWindow = session.contextWindow.slice(\n -this.CONTEXT_WINDOW_SIZE\n );\n }\n }\n\n /**\n * Generate feedback from verification results\n */\n private generateFeedback(results: VerificationResult[]): string {\n const failed = results.filter((r) => !r.passed);\n const warnings = results.filter(\n (r) => !r.passed && r.severity === 'warning'\n );\n const errors = results.filter((r) => !r.passed && r.severity === 'error');\n\n if (errors.length > 0) {\n const errorMessages = errors.map((e) => `- ${e.message}`).join('\\n');\n return `Verification failed with ${errors.length} error(s):\\n${errorMessages}`;\n }\n\n if (warnings.length > 0) {\n const warningMessages = warnings.map((w) => `- ${w.message}`).join('\\n');\n return `Verification passed with ${warnings.length} warning(s):\\n${warningMessages}`;\n }\n\n return 'All verifications passed successfully';\n }\n\n /**\n * Suggest context adjustment based on verification results\n */\n private suggestContextAdjustment(\n results: VerificationResult[]\n ): string | undefined {\n const failed = results.filter((r) => !r.passed && r.severity === 'error');\n\n if (failed.length === 0) {\n return undefined;\n }\n\n // Generate suggestions based on failure patterns\n const suggestions: string[] = [];\n\n if (failed.some((r) => r.verifierId === 'test-runner')) {\n suggestions.push('Focus on fixing failing tests');\n }\n if (failed.some((r) => r.verifierId === 'linter')) {\n suggestions.push('Address linting errors before proceeding');\n }\n if (failed.some((r) => r.verifierId === 'semantic-validator')) {\n suggestions.push('Review original requirements and adjust approach');\n }\n\n return suggestions.length > 0 ? suggestions.join('; ') : undefined;\n }\n\n /**\n * Handle turn limit reached\n */\n private async handleTurnLimitReached(session: AgentTaskSession): Promise<{\n success: boolean;\n feedback: string;\n shouldContinue: boolean;\n verificationResults: VerificationResult[];\n }> {\n logger.warn('Session reached turn limit', {\n sessionId: session.id,\n taskId: session.taskId,\n turnCount: session.turnCount,\n });\n\n // Check if task can be considered complete\n const task = this.taskStore.getTask(session.taskId);\n const isComplete = this.assessTaskCompletion(session);\n\n if (isComplete) {\n await this.completeSession(session);\n return {\n success: true,\n feedback: 'Task completed successfully within turn limit',\n shouldContinue: false,\n verificationResults: [],\n };\n }\n\n // Mark session as timeout\n session.status = 'timeout';\n this.taskStore.updateTaskStatus(\n session.taskId,\n 'blocked',\n 'Session timeout - manual review needed'\n );\n\n return {\n success: false,\n feedback: `Session reached ${this.MAX_TURNS_PER_SESSION} turn limit. Task requires manual review or retry.`,\n shouldContinue: false,\n verificationResults: [],\n };\n }\n\n /**\n * Assess if task is complete enough\n */\n private assessTaskCompletion(session: AgentTaskSession): boolean {\n // Check if recent verifications are passing\n const recentResults = session.verificationResults.slice(-5);\n const recentPassRate =\n recentResults.filter((r) => r.passed).length / recentResults.length;\n\n // Check if semantic validator passed recently (Spotify's LLM judge)\n const semanticPassed = recentResults.some(\n (r) => r.verifierId === 'semantic-validator' && r.passed\n );\n\n return recentPassRate >= 0.8 && semanticPassed;\n }\n\n /**\n * Complete a session\n */\n private async completeSession(session: AgentTaskSession): Promise<void> {\n session.status = 'completed';\n session.completedAt = new Date();\n\n // Update task status\n this.taskStore.updateTaskStatus(\n session.taskId,\n 'completed',\n 'Agent session completed'\n );\n\n // Clear timeout\n const timeout = this.sessionTimeouts.get(session.id);\n if (timeout) {\n clearTimeout(timeout);\n this.sessionTimeouts.delete(session.id);\n }\n\n // Generate and save session summary to frame\n const summary = this.generateSessionSummary(session);\n this.frameManager.addEvent('observation', {\n type: 'session_summary',\n frameId: session.frameId,\n summary,\n });\n\n logger.info('Session completed', {\n sessionId: session.id,\n taskId: session.taskId,\n turnCount: session.turnCount,\n duration: session.completedAt.getTime() - session.startedAt.getTime(),\n });\n }\n\n /**\n * Generate session summary for frame digest\n */\n private generateSessionSummary(\n session: AgentTaskSession\n ): Record<string, any> {\n const verificationStats = {\n total: session.verificationResults.length,\n passed: session.verificationResults.filter((r) => r.passed).length,\n failed: session.verificationResults.filter((r) => !r.passed).length,\n };\n\n return {\n sessionId: session.id,\n taskId: session.taskId,\n status: session.status,\n turnCount: session.turnCount,\n duration: session.completedAt\n ? session.completedAt.getTime() - session.startedAt.getTime()\n : 0,\n verificationStats,\n feedbackLoop: session.feedbackLoop.slice(-3), // Last 3 feedback entries\n contextWindow: session.contextWindow.slice(-2), // Last 2 context entries\n };\n }\n\n /**\n * Start timeout for session\n */\n private startSessionTimeout(sessionId: string): void {\n const timeout = setTimeout(() => {\n const session = this.activeSessions.get(sessionId);\n if (session && session.status === 'active') {\n session.status = 'timeout';\n this.taskStore.updateTaskStatus(\n session.taskId,\n 'blocked',\n 'Session timeout - no activity'\n );\n logger.warn('Session timed out due to inactivity', { sessionId });\n }\n }, this.SESSION_TIMEOUT_MS);\n\n this.sessionTimeouts.set(sessionId, timeout);\n }\n\n /**\n * Generate unique session ID\n */\n private generateSessionId(taskId: string): string {\n return `session-${taskId}-${Date.now()}`;\n }\n\n /**\n * Get active sessions summary\n */\n getActiveSessions(): Array<{\n sessionId: string;\n taskId: string;\n turnCount: number;\n status: string;\n startedAt: Date;\n }> {\n return Array.from(this.activeSessions.values()).map((session) => ({\n sessionId: session.id,\n taskId: session.taskId,\n turnCount: session.turnCount,\n status: session.status,\n startedAt: session.startedAt,\n }));\n }\n\n /**\n * Retry a failed session (Spotify's 3-retry strategy)\n */\n async retrySession(sessionId: string): Promise<AgentTaskSession | null> {\n const session = this.activeSessions.get(sessionId);\n if (!session || session.status === 'active') {\n return null;\n }\n\n // Count previous retries\n const retryCount = Array.from(this.activeSessions.values()).filter(\n (s) => s.taskId === session.taskId && s.status === 'failed'\n ).length;\n\n if (retryCount >= this.MAX_SESSION_RETRIES) {\n logger.warn('Max retries reached for task', {\n taskId: session.taskId,\n retries: retryCount,\n });\n return null;\n }\n\n // Start new session with learned context\n const newSession = await this.startTaskSession(\n session.taskId,\n session.frameId\n );\n\n // Transfer learned context from previous session\n newSession.contextWindow = session.contextWindow.slice(-3);\n newSession.feedbackLoop = [\n {\n turn: 0,\n action: 'Session retry with learned context',\n result: `Retrying after ${retryCount} previous attempts`,\n verificationPassed: true,\n contextAdjustment: session.feedbackLoop\n .filter((f) => f.contextAdjustment)\n .map((f) => f.contextAdjustment)\n .join('; '),\n },\n ];\n\n return newSession;\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["AgentType"]
7
7
  }
@@ -11,7 +11,7 @@ import * as path from "path";
11
11
  import Database from "better-sqlite3";
12
12
  import { existsSync } from "fs";
13
13
  import { ClearSurvival } from "../../core/session/clear-survival.js";
14
- import { FrameManager } from "../../core/context/frame-manager.js";
14
+ import { FrameManager } from "../../core/context/index.js";
15
15
  import { sessionManager } from "../../core/session/session-manager.js";
16
16
  const clearCommand = new Command("clear").description("Manage context clearing with ledger preservation").option("--save", "Save continuity ledger before clearing").option("--restore", "Restore from continuity ledger").option("--check", "Check if clear is recommended").option("--auto", "Automatically save if needed and clear").option("--status", "Show current context usage").option("--show-ledger", "Display current ledger").action(async (options) => {
17
17
  const spinner = ora();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/commands/clear.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * Clear command for StackMemory\n * Manages context clearing with ledger preservation\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport Database from 'better-sqlite3';\nimport { existsSync } from 'fs';\nimport { ClearSurvival } from '../../core/session/clear-survival.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { HandoffGenerator } from '../../core/session/handoff-generator.js';\nimport { sessionManager } from '../../core/session/session-manager.js';\nimport { getEnv, getOptionalEnv } from '../../utils/env.js';\n\nconst clearCommand = new Command('clear')\n .description('Manage context clearing with ledger preservation')\n .option('--save', 'Save continuity ledger before clearing')\n .option('--restore', 'Restore from continuity ledger')\n .option('--check', 'Check if clear is recommended')\n .option('--auto', 'Automatically save if needed and clear')\n .option('--status', 'Show current context usage')\n .option('--show-ledger', 'Display current ledger')\n .action(async (options) => {\n const spinner = ora();\n\n try {\n // Initialize managers\n const projectRoot = process.cwd();\n const dbPath = path.join(projectRoot, '.stackmemory', 'context.db');\n\n // Check if StackMemory is initialized\n if (!existsSync(dbPath)) {\n console.error(\n chalk.red('\u2717 StackMemory not initialized in this directory')\n );\n console.log(chalk.yellow('Run: stackmemory init'));\n process.exit(1);\n }\n\n const db = new Database(dbPath);\n\n // Initialize session manager\n await sessionManager.initialize();\n const session = await sessionManager.getOrCreateSession({\n projectPath: projectRoot,\n });\n\n const frameManager = new FrameManager(db, session.projectId);\n // For testing - use a mock handoff generator\n const handoffGenerator = {\n generateHandoff: () => Promise.resolve('Mock handoff'),\n getHandoffPath: () => 'mock.md',\n };\n // Create a mock DatabaseManager for ClearSurvival\n const dbManager = {\n getCurrentSessionId: () => Promise.resolve(session.id),\n getSession: () => Promise.resolve(session),\n } as any;\n const clearSurvival = new ClearSurvival(\n frameManager,\n dbManager,\n handoffGenerator as any,\n projectRoot\n );\n\n // Handle different options\n if (options.status) {\n await showContextStatus(clearSurvival);\n } else if (options.check) {\n await checkIfClearRecommended(clearSurvival);\n } else if (options.save) {\n await saveLedger(clearSurvival, spinner);\n } else if (options.restore) {\n await restoreFromLedger(clearSurvival, spinner);\n } else if (options.showLedger) {\n await showLedger(projectRoot);\n } else if (options.auto) {\n await autoClear(clearSurvival, spinner);\n } else {\n // Default: Show status and options\n await showContextStatus(clearSurvival);\n console.log('\\nOptions:');\n console.log(' --status Show current context usage');\n console.log(' --check Check if clear is recommended');\n console.log(' --save Save continuity ledger');\n console.log(' --restore Restore from ledger');\n console.log(' --auto Auto-save if needed and clear');\n }\n } catch (error: unknown) {\n // Don't exit in tests - just log the error\n console.error(chalk.red('Error: ' + (error as Error).message));\n if (process.env['NODE_ENV'] !== 'test') {\n process.exit(1);\n }\n }\n });\n\nasync function showContextStatus(clearSurvival: ClearSurvival): Promise<void> {\n const usage = await clearSurvival.getContextUsage();\n const status = clearSurvival.assessContextStatus(usage);\n\n console.log(chalk.bold('\\n\uD83D\uDCCA Context Usage Status'));\n console.log('\u2500'.repeat(40));\n\n const percentage = Math.round(usage.percentageUsed);\n const statusColor = getStatusColor(status);\n\n console.log(`Usage: ${percentage}% ${getProgressBar(percentage)}`);\n console.log(`Status: ${statusColor}`);\n console.log(`Active Frames: ${usage.activeFrames}`);\n console.log(`Total Frames: ${usage.totalFrames}`);\n console.log(`Sessions: ${usage.sessionCount}`);\n\n if (status === 'critical' || status === 'saved') {\n console.log(\n chalk.yellow('\\n\u26A0\uFE0F Consider clearing context to improve performance')\n );\n console.log(chalk.cyan('Run: stackmemory clear --save'));\n }\n}\n\nasync function checkIfClearRecommended(\n clearSurvival: ClearSurvival\n): Promise<void> {\n const usage = await clearSurvival.getContextUsage();\n const status = clearSurvival.assessContextStatus(usage);\n\n if (status === 'critical' || status === 'saved') {\n console.log(chalk.yellow('\u2713 Clear recommended'));\n console.log(`Context usage: ${Math.round(usage.percentageUsed)}%`);\n process.exit(0);\n } else {\n console.log(chalk.green('\u2717 Clear not needed'));\n console.log(`Context usage: ${Math.round(usage.percentageUsed)}%`);\n process.exit(1);\n }\n}\n\nasync function saveLedger(\n clearSurvival: ClearSurvival,\n spinner: ora.Ora\n): Promise<void> {\n spinner.start('Saving continuity ledger...');\n\n const ledgerPath = await clearSurvival.saveContinuityLedger();\n\n spinner.succeed(chalk.green('Continuity ledger saved'));\n console.log(chalk.cyan(`Location: ${ledgerPath}`));\n\n // Show what was saved\n const ledger = JSON.parse(await fs.readFile(ledgerPath, 'utf-8'));\n console.log('\\nSaved:');\n console.log(` \u2022 ${ledger.activeFrames.length} active frames`);\n console.log(` \u2022 ${ledger.decisions.length} key decisions`);\n console.log(\n ` \u2022 ${ledger.context.importantTasks?.length || 0} important tasks`\n );\n}\n\nasync function restoreFromLedger(\n clearSurvival: ClearSurvival,\n spinner: ora.Ora\n): Promise<void> {\n spinner.start('Restoring from continuity ledger...');\n\n const result = await clearSurvival.restoreFromLedger();\n\n if (result.success) {\n spinner.succeed(chalk.green('Context restored from ledger'));\n console.log('\\nRestored:');\n console.log(` \u2022 ${result.restoredFrames} frames`);\n console.log(` \u2022 ${result.restoredDecisions} decisions`);\n } else {\n spinner.fail(chalk.red('Failed to restore from ledger'));\n console.log(chalk.yellow(result.message));\n }\n}\n\nasync function showLedger(projectRoot: string): Promise<void> {\n const ledgerPath = path.join(projectRoot, '.stackmemory', 'continuity.json');\n\n if (!existsSync(ledgerPath)) {\n console.log(chalk.yellow('No continuity ledger found'));\n return;\n }\n\n const ledger = JSON.parse(await fs.readFile(ledgerPath, 'utf-8'));\n\n console.log(chalk.bold('\\n\uD83D\uDCD6 Continuity Ledger'));\n console.log('\u2500'.repeat(40));\n console.log(`Created: ${new Date(ledger.timestamp).toLocaleString()}`);\n console.log(`Active Frames: ${ledger.activeFrames.length}`);\n console.log(`Key Decisions: ${ledger.decisions.length}`);\n\n if (ledger.activeFrames.length > 0) {\n console.log('\\nActive Work:');\n ledger.activeFrames.slice(0, 5).forEach((frame: any) => {\n console.log(` \u2022 ${frame.name} (${frame.type})`);\n });\n }\n\n if (ledger.decisions.length > 0) {\n console.log('\\nKey Decisions:');\n ledger.decisions.slice(0, 3).forEach((decision: any) => {\n console.log(` \u2022 ${decision.decision}`);\n });\n }\n}\n\nasync function autoClear(\n clearSurvival: ClearSurvival,\n spinner: ora.Ora\n): Promise<void> {\n const usage = await clearSurvival.getContextUsage();\n const status = clearSurvival.assessContextStatus(usage);\n\n if (status === 'critical' || status === 'saved') {\n spinner.start('Auto-saving ledger before clear...');\n await clearSurvival.saveContinuityLedger();\n spinner.succeed('Ledger saved');\n\n spinner.start('Clearing context...');\n // Note: Actual clear implementation would go here\n // For now, just simulate\n await new Promise((resolve) => setTimeout(resolve, 1000));\n spinner.succeed('Context cleared successfully');\n } else {\n console.log(chalk.green('Context usage is healthy, no clear needed'));\n }\n}\n\nfunction getProgressBar(percentage: number): string {\n const filled = Math.round(percentage / 5);\n const empty = 20 - filled;\n\n let bar = '[';\n bar += chalk.green('\u25A0').repeat(Math.min(filled, 10));\n bar += chalk.yellow('\u25A0').repeat(Math.max(0, Math.min(filled - 10, 5)));\n bar += chalk.red('\u25A0').repeat(Math.max(0, filled - 15));\n bar += chalk.gray('\u25A1').repeat(empty);\n bar += ']';\n\n return bar;\n}\n\nfunction getStatusColor(status: string): string {\n switch (status) {\n case 'healthy':\n return chalk.green('\u2713 Healthy (<50%)');\n case 'moderate':\n return chalk.blue('\u26A1 Moderate (50-70%)');\n case 'critical':\n return chalk.yellow('\u26A0\uFE0F Critical (70-85%)');\n case 'saved':\n return chalk.red('\uD83D\uDCBE Auto-saved (>85%)');\n default:\n return status;\n }\n}\n\n// Export for use in main CLI\nexport default clearCommand;\n"],
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * Clear command for StackMemory\n * Manages context clearing with ledger preservation\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport Database from 'better-sqlite3';\nimport { existsSync } from 'fs';\nimport { ClearSurvival } from '../../core/session/clear-survival.js';\nimport { FrameManager } from '../../core/context/index.js';\nimport { HandoffGenerator } from '../../core/session/handoff-generator.js';\nimport { sessionManager } from '../../core/session/session-manager.js';\nimport { getEnv, getOptionalEnv } from '../../utils/env.js';\n\nconst clearCommand = new Command('clear')\n .description('Manage context clearing with ledger preservation')\n .option('--save', 'Save continuity ledger before clearing')\n .option('--restore', 'Restore from continuity ledger')\n .option('--check', 'Check if clear is recommended')\n .option('--auto', 'Automatically save if needed and clear')\n .option('--status', 'Show current context usage')\n .option('--show-ledger', 'Display current ledger')\n .action(async (options) => {\n const spinner = ora();\n\n try {\n // Initialize managers\n const projectRoot = process.cwd();\n const dbPath = path.join(projectRoot, '.stackmemory', 'context.db');\n\n // Check if StackMemory is initialized\n if (!existsSync(dbPath)) {\n console.error(\n chalk.red('\u2717 StackMemory not initialized in this directory')\n );\n console.log(chalk.yellow('Run: stackmemory init'));\n process.exit(1);\n }\n\n const db = new Database(dbPath);\n\n // Initialize session manager\n await sessionManager.initialize();\n const session = await sessionManager.getOrCreateSession({\n projectPath: projectRoot,\n });\n\n const frameManager = new FrameManager(db, session.projectId);\n // For testing - use a mock handoff generator\n const handoffGenerator = {\n generateHandoff: () => Promise.resolve('Mock handoff'),\n getHandoffPath: () => 'mock.md',\n };\n // Create a mock DatabaseManager for ClearSurvival\n const dbManager = {\n getCurrentSessionId: () => Promise.resolve(session.id),\n getSession: () => Promise.resolve(session),\n } as any;\n const clearSurvival = new ClearSurvival(\n frameManager,\n dbManager,\n handoffGenerator as any,\n projectRoot\n );\n\n // Handle different options\n if (options.status) {\n await showContextStatus(clearSurvival);\n } else if (options.check) {\n await checkIfClearRecommended(clearSurvival);\n } else if (options.save) {\n await saveLedger(clearSurvival, spinner);\n } else if (options.restore) {\n await restoreFromLedger(clearSurvival, spinner);\n } else if (options.showLedger) {\n await showLedger(projectRoot);\n } else if (options.auto) {\n await autoClear(clearSurvival, spinner);\n } else {\n // Default: Show status and options\n await showContextStatus(clearSurvival);\n console.log('\\nOptions:');\n console.log(' --status Show current context usage');\n console.log(' --check Check if clear is recommended');\n console.log(' --save Save continuity ledger');\n console.log(' --restore Restore from ledger');\n console.log(' --auto Auto-save if needed and clear');\n }\n } catch (error: unknown) {\n // Don't exit in tests - just log the error\n console.error(chalk.red('Error: ' + (error as Error).message));\n if (process.env['NODE_ENV'] !== 'test') {\n process.exit(1);\n }\n }\n });\n\nasync function showContextStatus(clearSurvival: ClearSurvival): Promise<void> {\n const usage = await clearSurvival.getContextUsage();\n const status = clearSurvival.assessContextStatus(usage);\n\n console.log(chalk.bold('\\n\uD83D\uDCCA Context Usage Status'));\n console.log('\u2500'.repeat(40));\n\n const percentage = Math.round(usage.percentageUsed);\n const statusColor = getStatusColor(status);\n\n console.log(`Usage: ${percentage}% ${getProgressBar(percentage)}`);\n console.log(`Status: ${statusColor}`);\n console.log(`Active Frames: ${usage.activeFrames}`);\n console.log(`Total Frames: ${usage.totalFrames}`);\n console.log(`Sessions: ${usage.sessionCount}`);\n\n if (status === 'critical' || status === 'saved') {\n console.log(\n chalk.yellow('\\n\u26A0\uFE0F Consider clearing context to improve performance')\n );\n console.log(chalk.cyan('Run: stackmemory clear --save'));\n }\n}\n\nasync function checkIfClearRecommended(\n clearSurvival: ClearSurvival\n): Promise<void> {\n const usage = await clearSurvival.getContextUsage();\n const status = clearSurvival.assessContextStatus(usage);\n\n if (status === 'critical' || status === 'saved') {\n console.log(chalk.yellow('\u2713 Clear recommended'));\n console.log(`Context usage: ${Math.round(usage.percentageUsed)}%`);\n process.exit(0);\n } else {\n console.log(chalk.green('\u2717 Clear not needed'));\n console.log(`Context usage: ${Math.round(usage.percentageUsed)}%`);\n process.exit(1);\n }\n}\n\nasync function saveLedger(\n clearSurvival: ClearSurvival,\n spinner: ora.Ora\n): Promise<void> {\n spinner.start('Saving continuity ledger...');\n\n const ledgerPath = await clearSurvival.saveContinuityLedger();\n\n spinner.succeed(chalk.green('Continuity ledger saved'));\n console.log(chalk.cyan(`Location: ${ledgerPath}`));\n\n // Show what was saved\n const ledger = JSON.parse(await fs.readFile(ledgerPath, 'utf-8'));\n console.log('\\nSaved:');\n console.log(` \u2022 ${ledger.activeFrames.length} active frames`);\n console.log(` \u2022 ${ledger.decisions.length} key decisions`);\n console.log(\n ` \u2022 ${ledger.context.importantTasks?.length || 0} important tasks`\n );\n}\n\nasync function restoreFromLedger(\n clearSurvival: ClearSurvival,\n spinner: ora.Ora\n): Promise<void> {\n spinner.start('Restoring from continuity ledger...');\n\n const result = await clearSurvival.restoreFromLedger();\n\n if (result.success) {\n spinner.succeed(chalk.green('Context restored from ledger'));\n console.log('\\nRestored:');\n console.log(` \u2022 ${result.restoredFrames} frames`);\n console.log(` \u2022 ${result.restoredDecisions} decisions`);\n } else {\n spinner.fail(chalk.red('Failed to restore from ledger'));\n console.log(chalk.yellow(result.message));\n }\n}\n\nasync function showLedger(projectRoot: string): Promise<void> {\n const ledgerPath = path.join(projectRoot, '.stackmemory', 'continuity.json');\n\n if (!existsSync(ledgerPath)) {\n console.log(chalk.yellow('No continuity ledger found'));\n return;\n }\n\n const ledger = JSON.parse(await fs.readFile(ledgerPath, 'utf-8'));\n\n console.log(chalk.bold('\\n\uD83D\uDCD6 Continuity Ledger'));\n console.log('\u2500'.repeat(40));\n console.log(`Created: ${new Date(ledger.timestamp).toLocaleString()}`);\n console.log(`Active Frames: ${ledger.activeFrames.length}`);\n console.log(`Key Decisions: ${ledger.decisions.length}`);\n\n if (ledger.activeFrames.length > 0) {\n console.log('\\nActive Work:');\n ledger.activeFrames.slice(0, 5).forEach((frame: any) => {\n console.log(` \u2022 ${frame.name} (${frame.type})`);\n });\n }\n\n if (ledger.decisions.length > 0) {\n console.log('\\nKey Decisions:');\n ledger.decisions.slice(0, 3).forEach((decision: any) => {\n console.log(` \u2022 ${decision.decision}`);\n });\n }\n}\n\nasync function autoClear(\n clearSurvival: ClearSurvival,\n spinner: ora.Ora\n): Promise<void> {\n const usage = await clearSurvival.getContextUsage();\n const status = clearSurvival.assessContextStatus(usage);\n\n if (status === 'critical' || status === 'saved') {\n spinner.start('Auto-saving ledger before clear...');\n await clearSurvival.saveContinuityLedger();\n spinner.succeed('Ledger saved');\n\n spinner.start('Clearing context...');\n // Note: Actual clear implementation would go here\n // For now, just simulate\n await new Promise((resolve) => setTimeout(resolve, 1000));\n spinner.succeed('Context cleared successfully');\n } else {\n console.log(chalk.green('Context usage is healthy, no clear needed'));\n }\n}\n\nfunction getProgressBar(percentage: number): string {\n const filled = Math.round(percentage / 5);\n const empty = 20 - filled;\n\n let bar = '[';\n bar += chalk.green('\u25A0').repeat(Math.min(filled, 10));\n bar += chalk.yellow('\u25A0').repeat(Math.max(0, Math.min(filled - 10, 5)));\n bar += chalk.red('\u25A0').repeat(Math.max(0, filled - 15));\n bar += chalk.gray('\u25A1').repeat(empty);\n bar += ']';\n\n return bar;\n}\n\nfunction getStatusColor(status: string): string {\n switch (status) {\n case 'healthy':\n return chalk.green('\u2713 Healthy (<50%)');\n case 'moderate':\n return chalk.blue('\u26A1 Moderate (50-70%)');\n case 'critical':\n return chalk.yellow('\u26A0\uFE0F Critical (70-85%)');\n case 'saved':\n return chalk.red('\uD83D\uDCBE Auto-saved (>85%)');\n default:\n return status;\n }\n}\n\n// Export for use in main CLI\nexport default clearCommand;\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  import Database from "better-sqlite3";
7
7
  import { join } from "path";
8
8
  import { existsSync } from "fs";
9
- import { FrameManager } from "../../core/context/frame-manager.js";
9
+ import { FrameManager } from "../../core/context/index.js";
10
10
  import { createContextRehydrateCommand } from "./context-rehydrate.js";
11
11
  function createContextCommands() {
12
12
  const context = new Command("context").alias("ctx").description("Manage context stack");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/commands/context.ts"],
4
- "sourcesContent": ["/**\n * Context Commands for StackMemory CLI\n * Manage context stack (show, push, pop)\n */\n\nimport { Command } from 'commander';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport { FrameManager, FrameType } from '../../core/context/frame-manager.js';\nimport { createContextRehydrateCommand } from './context-rehydrate.js';\n\n// Type-safe environment variable access\n\nexport function createContextCommands(): Command {\n const context = new Command('context')\n .alias('ctx')\n .description('Manage context stack');\n\n // Show current context\n context\n .command('show')\n .alias('status')\n .description('Show current context stack')\n .option('-v, --verbose', 'Show detailed information')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n // Get project ID - try metadata table, fallback to default\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(\n `\n SELECT value FROM metadata WHERE key = 'project_id'\n `\n )\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {\n // metadata table doesn't exist, use default\n }\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n const depth = frameManager.getStackDepth();\n const activePath = frameManager.getActiveFramePath();\n\n console.log(`\\n\uD83D\uDCDA Context Stack\\n`);\n console.log(`Project: ${projectId}`);\n console.log(`Depth: ${depth}`);\n console.log(`Active frames: ${activePath.length}\\n`);\n\n if (activePath.length === 0) {\n console.log('No active context frames.\\n');\n console.log('Use \"stackmemory context push\" to create one.');\n } else {\n const typeIcon: Record<string, string> = {\n session: '\uD83D\uDD37',\n task: '\uD83D\uDCCB',\n command: '\u26A1',\n file: '\uD83D\uDCC4',\n decision: '\uD83D\uDCA1',\n };\n\n console.log('Stack (bottom to top):');\n activePath.forEach((frame, i) => {\n const icon = typeIcon[frame.type] || '\uD83D\uDCE6';\n const indent = ' '.repeat(i);\n console.log(\n `${indent}${i === activePath.length - 1 ? '\u2514\u2500' : '\u251C\u2500'} ${icon} ${frame.name || frame.frame_id.slice(0, 10)}`\n );\n\n if (options.verbose) {\n console.log(`${indent} ID: ${frame.frame_id}`);\n console.log(`${indent} Type: ${frame.type}`);\n console.log(\n `${indent} Created: ${new Date(frame.created_at * 1000).toLocaleString()}`\n );\n }\n });\n }\n\n console.log('');\n } catch (error: unknown) {\n console.error('\u274C Failed to show context:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Push new context frame\n context\n .command('push <name>')\n .description('Push a new context frame onto the stack')\n .option(\n '-t, --type <type>',\n 'Frame type (session, task, command, file, decision)',\n 'task'\n )\n .option('-m, --metadata <json>', 'Additional metadata as JSON')\n .action(async (name, options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n // Get current top frame as parent\n const activePath = frameManager.getActiveFramePath();\n const parentId =\n activePath.length > 0\n ? activePath[activePath.length - 1].frame_id\n : undefined;\n\n // Parse metadata if provided\n let inputs = {};\n if (options.metadata) {\n try {\n inputs = JSON.parse(options.metadata);\n } catch {\n console.log('\u26A0\uFE0F Invalid metadata JSON, ignoring');\n }\n }\n\n const frameId = frameManager.createFrame({\n type: options.type as FrameType,\n name,\n inputs,\n parentFrameId: parentId,\n });\n\n console.log(`\u2705 Pushed context frame: ${name}`);\n console.log(` ID: ${frameId.slice(0, 10)}`);\n console.log(` Type: ${options.type}`);\n console.log(` Depth: ${frameManager.getStackDepth()}`);\n } catch (error: unknown) {\n console.error('\u274C Failed to push context:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Pop context frame\n context\n .command('pop')\n .description('Pop the top context frame from the stack')\n .option('-a, --all', 'Pop all frames (clear stack)')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n const activePath = frameManager.getActiveFramePath();\n\n if (activePath.length === 0) {\n console.log('\uD83D\uDCDA Stack is already empty.');\n return;\n }\n\n if (options.all) {\n // Close all frames from top to bottom\n for (let i = activePath.length - 1; i >= 0; i--) {\n frameManager.closeFrame(activePath[i].frame_id);\n }\n console.log(`\u2705 Cleared all ${activePath.length} context frames.`);\n } else {\n // Close just the top frame\n const topFrame = activePath[activePath.length - 1];\n frameManager.closeFrame(topFrame.frame_id);\n console.log(\n `\u2705 Popped: ${topFrame.name || topFrame.frame_id.slice(0, 10)}`\n );\n console.log(` Depth: ${frameManager.getStackDepth()}`);\n }\n } catch (error: unknown) {\n console.error('\u274C Failed to pop context:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Add event to current context\n context\n .command('add <type> <message>')\n .description(\n 'Add an event to current context (types: observation, decision, error)'\n )\n .action(async (type, message) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n const activePath = frameManager.getActiveFramePath();\n\n if (activePath.length === 0) {\n console.log('\u26A0\uFE0F No active context frame. Creating one...');\n frameManager.createFrame({\n type: 'task',\n name: 'cli-session',\n inputs: {},\n });\n }\n\n const currentFrame = frameManager.getActiveFramePath().slice(-1)[0];\n\n const validTypes = [\n 'observation',\n 'decision',\n 'error',\n 'action',\n 'result',\n ];\n if (!validTypes.includes(type)) {\n console.log(`\u26A0\uFE0F Unknown event type \"${type}\". Using \"observation\".`);\n type = 'observation';\n }\n\n frameManager.addEvent(\n type,\n { message, content: message },\n currentFrame.frame_id\n );\n\n console.log(\n `\u2705 Added ${type}: ${message.slice(0, 50)}${message.length > 50 ? '...' : ''}`\n );\n } catch (error: unknown) {\n console.error('\u274C Failed to add event:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Worktree integration commands\n context\n .command('worktree [action]')\n .description('Manage Claude worktree contexts')\n .option('-i, --instance <id>', 'Instance ID')\n .option('-b, --branch <name>', 'Branch name')\n .option('-l, --list', 'List worktree contexts')\n .action(async (action, options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n if (options.list || action === 'list') {\n // List all worktree contexts\n const worktreeFrames = db\n .prepare(\n `\n SELECT * FROM frames \n WHERE project_id = ? \n AND type = 'session' \n AND inputs LIKE '%worktree%'\n ORDER BY created_at DESC\n LIMIT 10\n `\n )\n .all(projectId) as any[];\n\n console.log('\\n\uD83C\uDF33 Worktree Contexts\\n');\n if (worktreeFrames.length === 0) {\n console.log('No worktree contexts found.');\n } else {\n worktreeFrames.forEach((frame) => {\n const inputs = JSON.parse(frame.inputs || '{}');\n const instanceId = inputs.instanceId || 'unknown';\n const branch = inputs.branch || 'unknown';\n const created = new Date(\n frame.created_at * 1000\n ).toLocaleString();\n console.log(`\uD83D\uDCCD ${frame.name || frame.frame_id.slice(0, 10)}`);\n console.log(` Instance: ${instanceId}`);\n console.log(` Branch: ${branch}`);\n console.log(` Created: ${created}`);\n console.log('');\n });\n }\n } else if (action === 'save') {\n // Save current worktree context\n const instanceId =\n options.instance || process.env['CLAUDE_INSTANCE_ID'];\n const branch = options.branch || 'unknown';\n\n if (!instanceId) {\n console.log('\u26A0\uFE0F No instance ID provided or detected.');\n return;\n }\n\n const frameId = frameManager.createFrame({\n type: 'task',\n name: `worktree-${branch}`,\n inputs: {\n worktree: true,\n instanceId,\n branch,\n path: process.cwd(),\n },\n });\n\n console.log(`\u2705 Saved worktree context for ${branch}`);\n console.log(` Instance: ${instanceId}`);\n console.log(` Frame ID: ${frameId.slice(0, 10)}`);\n } else if (action === 'load') {\n // Load worktree context\n const instanceId =\n options.instance || process.env['CLAUDE_INSTANCE_ID'];\n\n if (!instanceId) {\n console.log('\u26A0\uFE0F No instance ID provided.');\n return;\n }\n\n const worktreeFrame = db\n .prepare(\n `\n SELECT * FROM frames \n WHERE project_id = ? \n AND type = 'session' \n AND inputs LIKE ?\n ORDER BY created_at DESC\n LIMIT 1\n `\n )\n .get(projectId, `%\"instanceId\":\"${instanceId}\"%`) as any;\n\n if (worktreeFrame) {\n const inputs = JSON.parse(worktreeFrame.inputs || '{}');\n console.log(`\u2705 Loaded worktree context`);\n console.log(` Branch: ${inputs.branch}`);\n console.log(` Instance: ${inputs.instanceId}`);\n console.log(` Path: ${inputs.path}`);\n } else {\n console.log('\u26A0\uFE0F No worktree context found for this instance.');\n }\n } else {\n console.log('Usage: stackmemory context worktree [save|load|list]');\n }\n } catch (error: unknown) {\n console.error(\n '\u274C Failed to manage worktree context:',\n (error as Error).message\n );\n } finally {\n db.close();\n }\n });\n\n // Add rehydrate subcommand\n context.addCommand(createContextRehydrateCommand());\n\n return context;\n}\n"],
4
+ "sourcesContent": ["/**\n * Context Commands for StackMemory CLI\n * Manage context stack (show, push, pop)\n */\n\nimport { Command } from 'commander';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport { FrameManager, FrameType } from '../../core/context/index.js';\nimport { createContextRehydrateCommand } from './context-rehydrate.js';\n\n// Type-safe environment variable access\n\nexport function createContextCommands(): Command {\n const context = new Command('context')\n .alias('ctx')\n .description('Manage context stack');\n\n // Show current context\n context\n .command('show')\n .alias('status')\n .description('Show current context stack')\n .option('-v, --verbose', 'Show detailed information')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n // Get project ID - try metadata table, fallback to default\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(\n `\n SELECT value FROM metadata WHERE key = 'project_id'\n `\n )\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {\n // metadata table doesn't exist, use default\n }\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n const depth = frameManager.getStackDepth();\n const activePath = frameManager.getActiveFramePath();\n\n console.log(`\\n\uD83D\uDCDA Context Stack\\n`);\n console.log(`Project: ${projectId}`);\n console.log(`Depth: ${depth}`);\n console.log(`Active frames: ${activePath.length}\\n`);\n\n if (activePath.length === 0) {\n console.log('No active context frames.\\n');\n console.log('Use \"stackmemory context push\" to create one.');\n } else {\n const typeIcon: Record<string, string> = {\n session: '\uD83D\uDD37',\n task: '\uD83D\uDCCB',\n command: '\u26A1',\n file: '\uD83D\uDCC4',\n decision: '\uD83D\uDCA1',\n };\n\n console.log('Stack (bottom to top):');\n activePath.forEach((frame, i) => {\n const icon = typeIcon[frame.type] || '\uD83D\uDCE6';\n const indent = ' '.repeat(i);\n console.log(\n `${indent}${i === activePath.length - 1 ? '\u2514\u2500' : '\u251C\u2500'} ${icon} ${frame.name || frame.frame_id.slice(0, 10)}`\n );\n\n if (options.verbose) {\n console.log(`${indent} ID: ${frame.frame_id}`);\n console.log(`${indent} Type: ${frame.type}`);\n console.log(\n `${indent} Created: ${new Date(frame.created_at * 1000).toLocaleString()}`\n );\n }\n });\n }\n\n console.log('');\n } catch (error: unknown) {\n console.error('\u274C Failed to show context:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Push new context frame\n context\n .command('push <name>')\n .description('Push a new context frame onto the stack')\n .option(\n '-t, --type <type>',\n 'Frame type (session, task, command, file, decision)',\n 'task'\n )\n .option('-m, --metadata <json>', 'Additional metadata as JSON')\n .action(async (name, options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n // Get current top frame as parent\n const activePath = frameManager.getActiveFramePath();\n const parentId =\n activePath.length > 0\n ? activePath[activePath.length - 1].frame_id\n : undefined;\n\n // Parse metadata if provided\n let inputs = {};\n if (options.metadata) {\n try {\n inputs = JSON.parse(options.metadata);\n } catch {\n console.log('\u26A0\uFE0F Invalid metadata JSON, ignoring');\n }\n }\n\n const frameId = frameManager.createFrame({\n type: options.type as FrameType,\n name,\n inputs,\n parentFrameId: parentId,\n });\n\n console.log(`\u2705 Pushed context frame: ${name}`);\n console.log(` ID: ${frameId.slice(0, 10)}`);\n console.log(` Type: ${options.type}`);\n console.log(` Depth: ${frameManager.getStackDepth()}`);\n } catch (error: unknown) {\n console.error('\u274C Failed to push context:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Pop context frame\n context\n .command('pop')\n .description('Pop the top context frame from the stack')\n .option('-a, --all', 'Pop all frames (clear stack)')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n const activePath = frameManager.getActiveFramePath();\n\n if (activePath.length === 0) {\n console.log('\uD83D\uDCDA Stack is already empty.');\n return;\n }\n\n if (options.all) {\n // Close all frames from top to bottom\n for (let i = activePath.length - 1; i >= 0; i--) {\n frameManager.closeFrame(activePath[i].frame_id);\n }\n console.log(`\u2705 Cleared all ${activePath.length} context frames.`);\n } else {\n // Close just the top frame\n const topFrame = activePath[activePath.length - 1];\n frameManager.closeFrame(topFrame.frame_id);\n console.log(\n `\u2705 Popped: ${topFrame.name || topFrame.frame_id.slice(0, 10)}`\n );\n console.log(` Depth: ${frameManager.getStackDepth()}`);\n }\n } catch (error: unknown) {\n console.error('\u274C Failed to pop context:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Add event to current context\n context\n .command('add <type> <message>')\n .description(\n 'Add an event to current context (types: observation, decision, error)'\n )\n .action(async (type, message) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n const activePath = frameManager.getActiveFramePath();\n\n if (activePath.length === 0) {\n console.log('\u26A0\uFE0F No active context frame. Creating one...');\n frameManager.createFrame({\n type: 'task',\n name: 'cli-session',\n inputs: {},\n });\n }\n\n const currentFrame = frameManager.getActiveFramePath().slice(-1)[0];\n\n const validTypes = [\n 'observation',\n 'decision',\n 'error',\n 'action',\n 'result',\n ];\n if (!validTypes.includes(type)) {\n console.log(`\u26A0\uFE0F Unknown event type \"${type}\". Using \"observation\".`);\n type = 'observation';\n }\n\n frameManager.addEvent(\n type,\n { message, content: message },\n currentFrame.frame_id\n );\n\n console.log(\n `\u2705 Added ${type}: ${message.slice(0, 50)}${message.length > 50 ? '...' : ''}`\n );\n } catch (error: unknown) {\n console.error('\u274C Failed to add event:', (error as Error).message);\n } finally {\n db.close();\n }\n });\n\n // Worktree integration commands\n context\n .command('worktree [action]')\n .description('Manage Claude worktree contexts')\n .option('-i, --instance <id>', 'Instance ID')\n .option('-b, --branch <name>', 'Branch name')\n .option('-l, --list', 'List worktree contexts')\n .action(async (action, options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const projectRow = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (projectRow?.value) projectId = projectRow.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n\n if (options.list || action === 'list') {\n // List all worktree contexts\n const worktreeFrames = db\n .prepare(\n `\n SELECT * FROM frames \n WHERE project_id = ? \n AND type = 'session' \n AND inputs LIKE '%worktree%'\n ORDER BY created_at DESC\n LIMIT 10\n `\n )\n .all(projectId) as any[];\n\n console.log('\\n\uD83C\uDF33 Worktree Contexts\\n');\n if (worktreeFrames.length === 0) {\n console.log('No worktree contexts found.');\n } else {\n worktreeFrames.forEach((frame) => {\n const inputs = JSON.parse(frame.inputs || '{}');\n const instanceId = inputs.instanceId || 'unknown';\n const branch = inputs.branch || 'unknown';\n const created = new Date(\n frame.created_at * 1000\n ).toLocaleString();\n console.log(`\uD83D\uDCCD ${frame.name || frame.frame_id.slice(0, 10)}`);\n console.log(` Instance: ${instanceId}`);\n console.log(` Branch: ${branch}`);\n console.log(` Created: ${created}`);\n console.log('');\n });\n }\n } else if (action === 'save') {\n // Save current worktree context\n const instanceId =\n options.instance || process.env['CLAUDE_INSTANCE_ID'];\n const branch = options.branch || 'unknown';\n\n if (!instanceId) {\n console.log('\u26A0\uFE0F No instance ID provided or detected.');\n return;\n }\n\n const frameId = frameManager.createFrame({\n type: 'task',\n name: `worktree-${branch}`,\n inputs: {\n worktree: true,\n instanceId,\n branch,\n path: process.cwd(),\n },\n });\n\n console.log(`\u2705 Saved worktree context for ${branch}`);\n console.log(` Instance: ${instanceId}`);\n console.log(` Frame ID: ${frameId.slice(0, 10)}`);\n } else if (action === 'load') {\n // Load worktree context\n const instanceId =\n options.instance || process.env['CLAUDE_INSTANCE_ID'];\n\n if (!instanceId) {\n console.log('\u26A0\uFE0F No instance ID provided.');\n return;\n }\n\n const worktreeFrame = db\n .prepare(\n `\n SELECT * FROM frames \n WHERE project_id = ? \n AND type = 'session' \n AND inputs LIKE ?\n ORDER BY created_at DESC\n LIMIT 1\n `\n )\n .get(projectId, `%\"instanceId\":\"${instanceId}\"%`) as any;\n\n if (worktreeFrame) {\n const inputs = JSON.parse(worktreeFrame.inputs || '{}');\n console.log(`\u2705 Loaded worktree context`);\n console.log(` Branch: ${inputs.branch}`);\n console.log(` Instance: ${inputs.instanceId}`);\n console.log(` Path: ${inputs.path}`);\n } else {\n console.log('\u26A0\uFE0F No worktree context found for this instance.');\n }\n } else {\n console.log('Usage: stackmemory context worktree [save|load|list]');\n }\n } catch (error: unknown) {\n console.error(\n '\u274C Failed to manage worktree context:',\n (error as Error).message\n );\n } finally {\n db.close();\n }\n });\n\n // Add rehydrate subcommand\n context.addCommand(createContextRehydrateCommand());\n\n return context;\n}\n"],
5
5
  "mappings": ";;;;AAKA,SAAS,eAAe;AACxB,OAAO,cAAc;AACrB,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAC3B,SAAS,oBAA+B;AACxC,SAAS,qCAAqC;AAIvC,SAAS,wBAAiC;AAC/C,QAAM,UAAU,IAAI,QAAQ,SAAS,EAClC,MAAM,KAAK,EACX,YAAY,sBAAsB;AAGrC,UACG,QAAQ,MAAM,EACd,MAAM,QAAQ,EACd,YAAY,4BAA4B,EACxC,OAAO,iBAAiB,2BAA2B,EACnD,OAAO,OAAO,YAAY;AACzB,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,KAAK,aAAa,gBAAgB,YAAY;AAE7D,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,KAAK,IAAI,SAAS,MAAM;AAE9B,QAAI;AAEF,UAAI,YAAY;AAChB,UAAI;AACF,cAAM,aAAa,GAChB;AAAA,UACC;AAAA;AAAA;AAAA,QAGF,EACC,IAAI;AACP,YAAI,YAAY,MAAO,aAAY,WAAW;AAAA,MAChD,QAAQ;AAAA,MAER;AAEA,YAAM,eAAe,IAAI,aAAa,IAAI,WAAW;AAAA,QACnD,mBAAmB;AAAA,MACrB,CAAC;AAED,YAAM,QAAQ,aAAa,cAAc;AACzC,YAAM,aAAa,aAAa,mBAAmB;AAEnD,cAAQ,IAAI;AAAA;AAAA,CAAsB;AAClC,cAAQ,IAAI,YAAY,SAAS,EAAE;AACnC,cAAQ,IAAI,UAAU,KAAK,EAAE;AAC7B,cAAQ,IAAI,kBAAkB,WAAW,MAAM;AAAA,CAAI;AAEnD,UAAI,WAAW,WAAW,GAAG;AAC3B,gBAAQ,IAAI,6BAA6B;AACzC,gBAAQ,IAAI,+CAA+C;AAAA,MAC7D,OAAO;AACL,cAAM,WAAmC;AAAA,UACvC,SAAS;AAAA,UACT,MAAM;AAAA,UACN,SAAS;AAAA,UACT,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAEA,gBAAQ,IAAI,wBAAwB;AACpC,mBAAW,QAAQ,CAAC,OAAO,MAAM;AAC/B,gBAAM,OAAO,SAAS,MAAM,IAAI,KAAK;AACrC,gBAAM,SAAS,KAAK,OAAO,CAAC;AAC5B,kBAAQ;AAAA,YACN,GAAG,MAAM,GAAG,MAAM,WAAW,SAAS,IAAI,iBAAO,cAAI,IAAI,IAAI,IAAI,MAAM,QAAQ,MAAM,SAAS,MAAM,GAAG,EAAE,CAAC;AAAA,UAC5G;AAEA,cAAI,QAAQ,SAAS;AACnB,oBAAQ,IAAI,GAAG,MAAM,UAAU,MAAM,QAAQ,EAAE;AAC/C,oBAAQ,IAAI,GAAG,MAAM,YAAY,MAAM,IAAI,EAAE;AAC7C,oBAAQ;AAAA,cACN,GAAG,MAAM,eAAe,IAAI,KAAK,MAAM,aAAa,GAAI,EAAE,eAAe,CAAC;AAAA,YAC5E;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,cAAQ,IAAI,EAAE;AAAA,IAChB,SAAS,OAAgB;AACvB,cAAQ,MAAM,kCAA8B,MAAgB,OAAO;AAAA,IACrE,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,aAAa,EACrB,YAAY,yCAAyC,EACrD;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EACC,OAAO,yBAAyB,6BAA6B,EAC7D,OAAO,OAAO,MAAM,YAAY;AAC/B,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,KAAK,aAAa,gBAAgB,YAAY;AAE7D,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,KAAK,IAAI,SAAS,MAAM;AAE9B,QAAI;AACF,UAAI,YAAY;AAChB,UAAI;AACF,cAAM,aAAa,GAChB,QAAQ,qDAAqD,EAC7D,IAAI;AACP,YAAI,YAAY,MAAO,aAAY,WAAW;AAAA,MAChD,QAAQ;AAAA,MAAC;AAET,YAAM,eAAe,IAAI,aAAa,IAAI,WAAW;AAAA,QACnD,mBAAmB;AAAA,MACrB,CAAC;AAGD,YAAM,aAAa,aAAa,mBAAmB;AACnD,YAAM,WACJ,WAAW,SAAS,IAChB,WAAW,WAAW,SAAS,CAAC,EAAE,WAClC;AAGN,UAAI,SAAS,CAAC;AACd,UAAI,QAAQ,UAAU;AACpB,YAAI;AACF,mBAAS,KAAK,MAAM,QAAQ,QAAQ;AAAA,QACtC,QAAQ;AACN,kBAAQ,IAAI,8CAAoC;AAAA,QAClD;AAAA,MACF;AAEA,YAAM,UAAU,aAAa,YAAY;AAAA,QACvC,MAAM,QAAQ;AAAA,QACd;AAAA,QACA;AAAA,QACA,eAAe;AAAA,MACjB,CAAC;AAED,cAAQ,IAAI,gCAA2B,IAAI,EAAE;AAC7C,cAAQ,IAAI,UAAU,QAAQ,MAAM,GAAG,EAAE,CAAC,EAAE;AAC5C,cAAQ,IAAI,YAAY,QAAQ,IAAI,EAAE;AACtC,cAAQ,IAAI,aAAa,aAAa,cAAc,CAAC,EAAE;AAAA,IACzD,SAAS,OAAgB;AACvB,cAAQ,MAAM,kCAA8B,MAAgB,OAAO;AAAA,IACrE,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,KAAK,EACb,YAAY,0CAA0C,EACtD,OAAO,aAAa,8BAA8B,EAClD,OAAO,OAAO,YAAY;AACzB,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,KAAK,aAAa,gBAAgB,YAAY;AAE7D,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,KAAK,IAAI,SAAS,MAAM;AAE9B,QAAI;AACF,UAAI,YAAY;AAChB,UAAI;AACF,cAAM,aAAa,GAChB,QAAQ,qDAAqD,EAC7D,IAAI;AACP,YAAI,YAAY,MAAO,aAAY,WAAW;AAAA,MAChD,QAAQ;AAAA,MAAC;AAET,YAAM,eAAe,IAAI,aAAa,IAAI,WAAW;AAAA,QACnD,mBAAmB;AAAA,MACrB,CAAC;AAED,YAAM,aAAa,aAAa,mBAAmB;AAEnD,UAAI,WAAW,WAAW,GAAG;AAC3B,gBAAQ,IAAI,mCAA4B;AACxC;AAAA,MACF;AAEA,UAAI,QAAQ,KAAK;AAEf,iBAAS,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;AAC/C,uBAAa,WAAW,WAAW,CAAC,EAAE,QAAQ;AAAA,QAChD;AACA,gBAAQ,IAAI,sBAAiB,WAAW,MAAM,kBAAkB;AAAA,MAClE,OAAO;AAEL,cAAM,WAAW,WAAW,WAAW,SAAS,CAAC;AACjD,qBAAa,WAAW,SAAS,QAAQ;AACzC,gBAAQ;AAAA,UACN,kBAAa,SAAS,QAAQ,SAAS,SAAS,MAAM,GAAG,EAAE,CAAC;AAAA,QAC9D;AACA,gBAAQ,IAAI,aAAa,aAAa,cAAc,CAAC,EAAE;AAAA,MACzD;AAAA,IACF,SAAS,OAAgB;AACvB,cAAQ,MAAM,iCAA6B,MAAgB,OAAO;AAAA,IACpE,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,sBAAsB,EAC9B;AAAA,IACC;AAAA,EACF,EACC,OAAO,OAAO,MAAM,YAAY;AAC/B,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,KAAK,aAAa,gBAAgB,YAAY;AAE7D,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,KAAK,IAAI,SAAS,MAAM;AAE9B,QAAI;AACF,UAAI,YAAY;AAChB,UAAI;AACF,cAAM,aAAa,GAChB,QAAQ,qDAAqD,EAC7D,IAAI;AACP,YAAI,YAAY,MAAO,aAAY,WAAW;AAAA,MAChD,QAAQ;AAAA,MAAC;AAET,YAAM,eAAe,IAAI,aAAa,IAAI,WAAW;AAAA,QACnD,mBAAmB;AAAA,MACrB,CAAC;AAED,YAAM,aAAa,aAAa,mBAAmB;AAEnD,UAAI,WAAW,WAAW,GAAG;AAC3B,gBAAQ,IAAI,uDAA6C;AACzD,qBAAa,YAAY;AAAA,UACvB,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ,CAAC;AAAA,QACX,CAAC;AAAA,MACH;AAEA,YAAM,eAAe,aAAa,mBAAmB,EAAE,MAAM,EAAE,EAAE,CAAC;AAElE,YAAM,aAAa;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,CAAC,WAAW,SAAS,IAAI,GAAG;AAC9B,gBAAQ,IAAI,oCAA0B,IAAI,yBAAyB;AACnE,eAAO;AAAA,MACT;AAEA,mBAAa;AAAA,QACX;AAAA,QACA,EAAE,SAAS,SAAS,QAAQ;AAAA,QAC5B,aAAa;AAAA,MACf;AAEA,cAAQ;AAAA,QACN,gBAAW,IAAI,KAAK,QAAQ,MAAM,GAAG,EAAE,CAAC,GAAG,QAAQ,SAAS,KAAK,QAAQ,EAAE;AAAA,MAC7E;AAAA,IACF,SAAS,OAAgB;AACvB,cAAQ,MAAM,+BAA2B,MAAgB,OAAO;AAAA,IAClE,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,mBAAmB,EAC3B,YAAY,iCAAiC,EAC7C,OAAO,uBAAuB,aAAa,EAC3C,OAAO,uBAAuB,aAAa,EAC3C,OAAO,cAAc,wBAAwB,EAC7C,OAAO,OAAO,QAAQ,YAAY;AACjC,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,KAAK,aAAa,gBAAgB,YAAY;AAE7D,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,KAAK,IAAI,SAAS,MAAM;AAE9B,QAAI;AACF,UAAI,YAAY;AAChB,UAAI;AACF,cAAM,aAAa,GAChB,QAAQ,qDAAqD,EAC7D,IAAI;AACP,YAAI,YAAY,MAAO,aAAY,WAAW;AAAA,MAChD,QAAQ;AAAA,MAAC;AAET,YAAM,eAAe,IAAI,aAAa,IAAI,WAAW;AAAA,QACnD,mBAAmB;AAAA,MACrB,CAAC;AAED,UAAI,QAAQ,QAAQ,WAAW,QAAQ;AAErC,cAAM,iBAAiB,GACpB;AAAA,UACC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQF,EACC,IAAI,SAAS;AAEhB,gBAAQ,IAAI,iCAA0B;AACtC,YAAI,eAAe,WAAW,GAAG;AAC/B,kBAAQ,IAAI,6BAA6B;AAAA,QAC3C,OAAO;AACL,yBAAe,QAAQ,CAAC,UAAU;AAChC,kBAAM,SAAS,KAAK,MAAM,MAAM,UAAU,IAAI;AAC9C,kBAAM,aAAa,OAAO,cAAc;AACxC,kBAAM,SAAS,OAAO,UAAU;AAChC,kBAAM,UAAU,IAAI;AAAA,cAClB,MAAM,aAAa;AAAA,YACrB,EAAE,eAAe;AACjB,oBAAQ,IAAI,aAAM,MAAM,QAAQ,MAAM,SAAS,MAAM,GAAG,EAAE,CAAC,EAAE;AAC7D,oBAAQ,IAAI,gBAAgB,UAAU,EAAE;AACxC,oBAAQ,IAAI,cAAc,MAAM,EAAE;AAClC,oBAAQ,IAAI,eAAe,OAAO,EAAE;AACpC,oBAAQ,IAAI,EAAE;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF,WAAW,WAAW,QAAQ;AAE5B,cAAM,aACJ,QAAQ,YAAY,QAAQ,IAAI,oBAAoB;AACtD,cAAM,SAAS,QAAQ,UAAU;AAEjC,YAAI,CAAC,YAAY;AACf,kBAAQ,IAAI,mDAAyC;AACrD;AAAA,QACF;AAEA,cAAM,UAAU,aAAa,YAAY;AAAA,UACvC,MAAM;AAAA,UACN,MAAM,YAAY,MAAM;AAAA,UACxB,QAAQ;AAAA,YACN,UAAU;AAAA,YACV;AAAA,YACA;AAAA,YACA,MAAM,QAAQ,IAAI;AAAA,UACpB;AAAA,QACF,CAAC;AAED,gBAAQ,IAAI,qCAAgC,MAAM,EAAE;AACpD,gBAAQ,IAAI,gBAAgB,UAAU,EAAE;AACxC,gBAAQ,IAAI,gBAAgB,QAAQ,MAAM,GAAG,EAAE,CAAC,EAAE;AAAA,MACpD,WAAW,WAAW,QAAQ;AAE5B,cAAM,aACJ,QAAQ,YAAY,QAAQ,IAAI,oBAAoB;AAEtD,YAAI,CAAC,YAAY;AACf,kBAAQ,IAAI,uCAA6B;AACzC;AAAA,QACF;AAEA,cAAM,gBAAgB,GACnB;AAAA,UACC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQF,EACC,IAAI,WAAW,kBAAkB,UAAU,IAAI;AAElD,YAAI,eAAe;AACjB,gBAAM,SAAS,KAAK,MAAM,cAAc,UAAU,IAAI;AACtD,kBAAQ,IAAI,gCAA2B;AACvC,kBAAQ,IAAI,cAAc,OAAO,MAAM,EAAE;AACzC,kBAAQ,IAAI,gBAAgB,OAAO,UAAU,EAAE;AAC/C,kBAAQ,IAAI,YAAY,OAAO,IAAI,EAAE;AAAA,QACvC,OAAO;AACL,kBAAQ,IAAI,2DAAiD;AAAA,QAC/D;AAAA,MACF,OAAO;AACL,gBAAQ,IAAI,sDAAsD;AAAA,MACpE;AAAA,IACF,SAAS,OAAgB;AACvB,cAAQ;AAAA,QACN;AAAA,QACC,MAAgB;AAAA,MACnB;AAAA,IACF,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AAGH,UAAQ,WAAW,8BAA8B,CAAC;AAElD,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/commands/dashboard.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * Dashboard Command - Display monitoring dashboard in terminal\n */\n\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { SessionManager } from '../../core/session/session-manager.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport const dashboardCommand = {\n command: 'dashboard',\n describe: 'Display monitoring dashboard in terminal',\n builder: (yargs: any) => {\n return yargs\n .option('watch', {\n alias: 'w',\n type: 'boolean',\n description: 'Auto-refresh dashboard',\n default: false,\n })\n .option('interval', {\n alias: 'i',\n type: 'number',\n description: 'Refresh interval in seconds',\n default: 5,\n });\n },\n handler: async (argv: any) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const displayDashboard = async () => {\n console.clear();\n\n // Header\n console.log(\n chalk.cyan.bold(\n '\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'\n )\n );\n console.log(\n chalk.cyan.bold(\n ' \uD83D\uDE80 StackMemory Monitoring Dashboard '\n )\n );\n console.log(\n chalk.cyan.bold(\n '\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'\n )\n );\n console.log();\n\n const sessionManager = new SessionManager({ enableMonitoring: false });\n await sessionManager.initialize();\n\n const db = new Database(dbPath);\n\n // Get sessions\n const sessions = await sessionManager.listSessions({\n state: 'active',\n limit: 5,\n });\n\n // Sessions Table\n const sessionsTable = new Table({\n head: [\n chalk.white('Session ID'),\n chalk.white('Status'),\n chalk.white('Branch'),\n chalk.white('Duration'),\n chalk.white('Last Active'),\n ],\n style: { head: [], border: [] },\n });\n\n sessions.forEach((session) => {\n const duration = Math.round(\n (Date.now() - session.startedAt) / 1000 / 60\n );\n const lastActive = Math.round(\n (Date.now() - session.lastActiveAt) / 1000 / 60\n );\n const status =\n session.state === 'active'\n ? chalk.green('\u25CF Active')\n : session.state === 'completed'\n ? chalk.gray('\u25CF Completed')\n : chalk.yellow('\u25CF Idle');\n\n sessionsTable.push([\n session.sessionId.substring(0, 8),\n status,\n session.branch || 'main',\n `${duration}m`,\n `${lastActive}m ago`,\n ]);\n });\n\n console.log(chalk.yellow.bold('\uD83D\uDCCA Active Sessions'));\n console.log(sessionsTable.toString());\n console.log();\n\n // Frame Statistics\n const frameStats = db\n .prepare(\n `\n SELECT \n COUNT(*) as total,\n SUM(CASE WHEN state = 'active' THEN 1 ELSE 0 END) as active,\n COUNT(DISTINCT run_id) as sessions\n FROM frames\n `\n )\n .get() as any;\n\n const statsTable = new Table({\n head: [chalk.white('Metric'), chalk.white('Value')],\n style: { head: [], border: [] },\n });\n\n statsTable.push(\n ['Total Frames', frameStats.total || 0],\n ['Active Frames', chalk.green(frameStats.active || 0)],\n ['Total Sessions', frameStats.sessions || 0]\n );\n\n console.log(chalk.yellow.bold('\uD83D\uDCC8 Frame Statistics'));\n console.log(statsTable.toString());\n console.log();\n\n // Recent Activity\n const recentActivity = db\n .prepare(\n `\n SELECT \n name,\n type,\n state,\n datetime(created_at, 'unixepoch') as created\n FROM frames\n ORDER BY created_at DESC\n LIMIT 5\n `\n )\n .all() as any[];\n\n if (recentActivity.length > 0) {\n const activityTable = new Table({\n head: [\n chalk.white('Frame'),\n chalk.white('Type'),\n chalk.white('Status'),\n chalk.white('Created'),\n ],\n style: { head: [], border: [] },\n });\n\n recentActivity.forEach((frame) => {\n const status =\n frame.state === 'active'\n ? chalk.green('Active')\n : chalk.gray('Closed');\n\n activityTable.push([\n frame.name.substring(0, 30),\n frame.type,\n status,\n frame.created,\n ]);\n });\n\n console.log(chalk.yellow.bold('\uD83D\uDD50 Recent Activity'));\n console.log(activityTable.toString());\n console.log();\n }\n\n // Memory Usage\n const contextUsage = await estimateContextUsage(db);\n const usageBar = createProgressBar(contextUsage, 100);\n\n console.log(chalk.yellow.bold('\uD83D\uDCBE Context Usage'));\n console.log(`${usageBar} ${contextUsage}%`);\n console.log();\n\n db.close();\n\n // Footer\n if (argv.watch) {\n console.log(\n chalk.gray(\n `Auto-refreshing every ${argv.interval} seconds. Press Ctrl+C to exit.`\n )\n );\n } else {\n console.log(chalk.gray('Run with --watch to auto-refresh'));\n }\n };\n\n try {\n await displayDashboard();\n\n if (argv.watch) {\n const interval = setInterval(async () => {\n await displayDashboard();\n }, argv.interval * 1000);\n\n process.on('SIGINT', () => {\n clearInterval(interval);\n console.clear();\n console.log(chalk.green('\u2705 Dashboard closed'));\n process.exit(0);\n });\n }\n } catch (error: unknown) {\n console.error(chalk.red('\u274C Dashboard error:'), (error as Error).message);\n process.exit(1);\n }\n },\n};\n\nfunction createProgressBar(value: number, max: number): string {\n const percentage = Math.min(100, Math.round((value / max) * 100));\n const filled = Math.round(percentage / 5);\n const empty = 20 - filled;\n\n let color = chalk.green;\n if (percentage > 80) color = chalk.red;\n else if (percentage > 60) color = chalk.yellow;\n\n return color('\u2588'.repeat(filled)) + chalk.gray('\u2591'.repeat(empty));\n}\n\nasync function estimateContextUsage(db: Database): Promise<number> {\n const result = db\n .prepare(\n `\n SELECT \n COUNT(*) as frame_count,\n SUM(LENGTH(inputs)) as input_size,\n SUM(LENGTH(outputs)) as output_size\n FROM frames\n WHERE state = 'active'\n `\n )\n .get() as any;\n\n // Rough estimate: assume average token is 4 bytes\n const totalBytes = (result.input_size || 0) + (result.output_size || 0);\n const estimatedTokens = totalBytes / 4;\n const maxTokens = 128000; // Claude's context window\n\n return Math.round((estimatedTokens / maxTokens) * 100);\n}\n"],
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * Dashboard Command - Display monitoring dashboard in terminal\n */\n\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { SessionManager } from '../../core/session/session-manager.js';\nimport { FrameManager } from '../../core/context/index.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport const dashboardCommand = {\n command: 'dashboard',\n describe: 'Display monitoring dashboard in terminal',\n builder: (yargs: any) => {\n return yargs\n .option('watch', {\n alias: 'w',\n type: 'boolean',\n description: 'Auto-refresh dashboard',\n default: false,\n })\n .option('interval', {\n alias: 'i',\n type: 'number',\n description: 'Refresh interval in seconds',\n default: 5,\n });\n },\n handler: async (argv: any) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const displayDashboard = async () => {\n console.clear();\n\n // Header\n console.log(\n chalk.cyan.bold(\n '\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'\n )\n );\n console.log(\n chalk.cyan.bold(\n ' \uD83D\uDE80 StackMemory Monitoring Dashboard '\n )\n );\n console.log(\n chalk.cyan.bold(\n '\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'\n )\n );\n console.log();\n\n const sessionManager = new SessionManager({ enableMonitoring: false });\n await sessionManager.initialize();\n\n const db = new Database(dbPath);\n\n // Get sessions\n const sessions = await sessionManager.listSessions({\n state: 'active',\n limit: 5,\n });\n\n // Sessions Table\n const sessionsTable = new Table({\n head: [\n chalk.white('Session ID'),\n chalk.white('Status'),\n chalk.white('Branch'),\n chalk.white('Duration'),\n chalk.white('Last Active'),\n ],\n style: { head: [], border: [] },\n });\n\n sessions.forEach((session) => {\n const duration = Math.round(\n (Date.now() - session.startedAt) / 1000 / 60\n );\n const lastActive = Math.round(\n (Date.now() - session.lastActiveAt) / 1000 / 60\n );\n const status =\n session.state === 'active'\n ? chalk.green('\u25CF Active')\n : session.state === 'completed'\n ? chalk.gray('\u25CF Completed')\n : chalk.yellow('\u25CF Idle');\n\n sessionsTable.push([\n session.sessionId.substring(0, 8),\n status,\n session.branch || 'main',\n `${duration}m`,\n `${lastActive}m ago`,\n ]);\n });\n\n console.log(chalk.yellow.bold('\uD83D\uDCCA Active Sessions'));\n console.log(sessionsTable.toString());\n console.log();\n\n // Frame Statistics\n const frameStats = db\n .prepare(\n `\n SELECT \n COUNT(*) as total,\n SUM(CASE WHEN state = 'active' THEN 1 ELSE 0 END) as active,\n COUNT(DISTINCT run_id) as sessions\n FROM frames\n `\n )\n .get() as any;\n\n const statsTable = new Table({\n head: [chalk.white('Metric'), chalk.white('Value')],\n style: { head: [], border: [] },\n });\n\n statsTable.push(\n ['Total Frames', frameStats.total || 0],\n ['Active Frames', chalk.green(frameStats.active || 0)],\n ['Total Sessions', frameStats.sessions || 0]\n );\n\n console.log(chalk.yellow.bold('\uD83D\uDCC8 Frame Statistics'));\n console.log(statsTable.toString());\n console.log();\n\n // Recent Activity\n const recentActivity = db\n .prepare(\n `\n SELECT \n name,\n type,\n state,\n datetime(created_at, 'unixepoch') as created\n FROM frames\n ORDER BY created_at DESC\n LIMIT 5\n `\n )\n .all() as any[];\n\n if (recentActivity.length > 0) {\n const activityTable = new Table({\n head: [\n chalk.white('Frame'),\n chalk.white('Type'),\n chalk.white('Status'),\n chalk.white('Created'),\n ],\n style: { head: [], border: [] },\n });\n\n recentActivity.forEach((frame) => {\n const status =\n frame.state === 'active'\n ? chalk.green('Active')\n : chalk.gray('Closed');\n\n activityTable.push([\n frame.name.substring(0, 30),\n frame.type,\n status,\n frame.created,\n ]);\n });\n\n console.log(chalk.yellow.bold('\uD83D\uDD50 Recent Activity'));\n console.log(activityTable.toString());\n console.log();\n }\n\n // Memory Usage\n const contextUsage = await estimateContextUsage(db);\n const usageBar = createProgressBar(contextUsage, 100);\n\n console.log(chalk.yellow.bold('\uD83D\uDCBE Context Usage'));\n console.log(`${usageBar} ${contextUsage}%`);\n console.log();\n\n db.close();\n\n // Footer\n if (argv.watch) {\n console.log(\n chalk.gray(\n `Auto-refreshing every ${argv.interval} seconds. Press Ctrl+C to exit.`\n )\n );\n } else {\n console.log(chalk.gray('Run with --watch to auto-refresh'));\n }\n };\n\n try {\n await displayDashboard();\n\n if (argv.watch) {\n const interval = setInterval(async () => {\n await displayDashboard();\n }, argv.interval * 1000);\n\n process.on('SIGINT', () => {\n clearInterval(interval);\n console.clear();\n console.log(chalk.green('\u2705 Dashboard closed'));\n process.exit(0);\n });\n }\n } catch (error: unknown) {\n console.error(chalk.red('\u274C Dashboard error:'), (error as Error).message);\n process.exit(1);\n }\n },\n};\n\nfunction createProgressBar(value: number, max: number): string {\n const percentage = Math.min(100, Math.round((value / max) * 100));\n const filled = Math.round(percentage / 5);\n const empty = 20 - filled;\n\n let color = chalk.green;\n if (percentage > 80) color = chalk.red;\n else if (percentage > 60) color = chalk.yellow;\n\n return color('\u2588'.repeat(filled)) + chalk.gray('\u2591'.repeat(empty));\n}\n\nasync function estimateContextUsage(db: Database): Promise<number> {\n const result = db\n .prepare(\n `\n SELECT \n COUNT(*) as frame_count,\n SUM(LENGTH(inputs)) as input_size,\n SUM(LENGTH(outputs)) as output_size\n FROM frames\n WHERE state = 'active'\n `\n )\n .get() as any;\n\n // Rough estimate: assume average token is 4 bytes\n const totalBytes = (result.input_size || 0) + (result.output_size || 0);\n const estimatedTokens = totalBytes / 4;\n const maxTokens = 128000; // Claude's context window\n\n return Math.round((estimatedTokens / maxTokens) * 100);\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -7,7 +7,7 @@ import Database from "better-sqlite3";
7
7
  import { join } from "path";
8
8
  import { existsSync } from "fs";
9
9
  import chalk from "chalk";
10
- import { FrameManager } from "../../core/context/frame-manager.js";
10
+ import { FrameManager } from "../../core/context/index.js";
11
11
  import { LLMContextRetrieval } from "../../core/retrieval/index.js";
12
12
  import { DiscoveryHandlers } from "../../integrations/mcp/handlers/discovery-handlers.js";
13
13
  function createDiscoveryCommands() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/cli/commands/discovery.ts"],
4
- "sourcesContent": ["/**\n * Discovery CLI Commands\n * Discover relevant files based on current context\n */\n\nimport { Command } from 'commander';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport chalk from 'chalk';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { LLMContextRetrieval } from '../../core/retrieval/index.js';\nimport { DiscoveryHandlers } from '../../integrations/mcp/handlers/discovery-handlers.js';\n\nexport function createDiscoveryCommands(): Command {\n const discovery = new Command('discovery')\n .alias('discover')\n .description('Discover relevant files based on current context');\n\n // Main discovery command\n discovery\n .command('files')\n .alias('f')\n .description('Discover files relevant to current context')\n .option('-q, --query <text>', 'Focus discovery on specific query')\n .option(\n '-d, --depth <level>',\n 'Search depth: shallow, medium, deep',\n 'medium'\n )\n .option('-m, --max <n>', 'Maximum files to return', '20')\n .option('-i, --include <patterns>', 'Include patterns (comma-separated)')\n .option('-e, --exclude <patterns>', 'Exclude patterns (comma-separated)')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n console.log(chalk.gray('Run \"stackmemory init\" first.'));\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n console.log(chalk.blue('\\nDiscovering relevant files...\\n'));\n\n const result = await handlers.handleDiscover({\n query: options.query,\n depth: options.depth as 'shallow' | 'medium' | 'deep',\n maxFiles: parseInt(options.max),\n includePatterns: options.include?.split(','),\n excludePatterns: options.exclude?.split(','),\n });\n\n // Display results\n const metadata = result.metadata;\n\n console.log(chalk.cyan('Context Summary'));\n console.log(chalk.gray(metadata.contextSummary));\n console.log('');\n\n console.log(chalk.cyan('Keywords Extracted'));\n console.log(chalk.gray(metadata.keywords.slice(0, 15).join(', ')));\n console.log('');\n\n console.log(chalk.cyan('Relevant Files'));\n for (const file of metadata.files.slice(0, parseInt(options.max))) {\n const icon =\n file.relevance === 'high'\n ? chalk.green('[HIGH]')\n : file.relevance === 'medium'\n ? chalk.yellow('[MED]')\n : chalk.gray('[LOW]');\n console.log(`${icon} ${chalk.white(file.path)}`);\n console.log(chalk.gray(` ${file.reason}`));\n }\n\n if (Object.keys(metadata.mdContext).length > 0) {\n console.log('');\n console.log(chalk.cyan('MD Files Parsed'));\n for (const mdFile of Object.keys(metadata.mdContext)) {\n console.log(chalk.gray(` - ${mdFile}`));\n }\n }\n\n console.log('');\n } finally {\n db.close();\n }\n });\n\n // Related files command\n discovery\n .command('related')\n .alias('r')\n .description('Find files related to a specific file or concept')\n .option('-f, --file <path>', 'File to find related files for')\n .option('-c, --concept <text>', 'Concept to search for')\n .option('-m, --max <n>', 'Maximum files to return', '10')\n .action(async (options) => {\n if (!options.file && !options.concept) {\n console.log(chalk.red('Either --file or --concept is required'));\n return;\n }\n\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n const target = options.file || options.concept;\n console.log(chalk.blue(`\\nFinding files related to: ${target}\\n`));\n\n const result = await handlers.handleRelatedFiles({\n file: options.file,\n concept: options.concept,\n maxFiles: parseInt(options.max),\n });\n\n const files = result.metadata.relatedFiles;\n\n if (files.length === 0) {\n console.log(chalk.gray('No related files found.'));\n return;\n }\n\n for (const file of files) {\n const icon =\n file.relevance === 'high'\n ? chalk.green('[HIGH]')\n : chalk.yellow('[MED]');\n console.log(`${icon} ${chalk.white(file.path)}`);\n console.log(chalk.gray(` ${file.reason}`));\n }\n\n console.log('');\n } finally {\n db.close();\n }\n });\n\n // Session summary command\n discovery\n .command('session')\n .alias('s')\n .description('Get current session summary')\n .option('--no-files', 'Exclude recent files')\n .option('--no-decisions', 'Exclude recent decisions')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n const result = await handlers.handleSessionSummary({\n includeFiles: options.files !== false,\n includeDecisions: options.decisions !== false,\n });\n\n const summary = result.metadata;\n\n console.log(chalk.blue('\\nSession Summary\\n'));\n\n console.log(`${chalk.cyan('Current Goal:')} ${summary.currentGoal}`);\n console.log(`${chalk.cyan('Active Frames:')} ${summary.activeFrames}`);\n console.log(`${chalk.cyan('Stack Depth:')} ${summary.stackDepth}`);\n\n if (summary.recentFiles?.length > 0) {\n console.log(chalk.cyan('\\nRecent Files:'));\n for (const f of summary.recentFiles.slice(0, 10)) {\n console.log(chalk.gray(` - ${f}`));\n }\n }\n\n if (summary.decisions?.length > 0) {\n console.log(chalk.cyan('\\nRecent Decisions:'));\n for (const d of summary.decisions.slice(0, 5)) {\n console.log(\n chalk.gray(\n ` [${d.type}] ${d.text.slice(0, 60)}${d.text.length > 60 ? '...' : ''}`\n )\n );\n }\n }\n\n console.log('');\n } finally {\n db.close();\n }\n });\n\n // Quick context command (default)\n discovery\n .command('quick', { isDefault: true })\n .description('Quick discovery based on current context')\n .action(async () => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n console.log(chalk.gray('Run \"stackmemory init\" first.'));\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n console.log(chalk.blue('\\nQuick Discovery\\n'));\n\n // Get session summary first\n const sessionResult = await handlers.handleSessionSummary({\n includeFiles: true,\n includeDecisions: true,\n });\n const session = sessionResult.metadata;\n\n console.log(`${chalk.cyan('Current:')} ${session.currentGoal}`);\n console.log(`${chalk.cyan('Stack:')} ${session.stackDepth} frames`);\n console.log('');\n\n // Quick file discovery\n const discoverResult = await handlers.handleDiscover({\n depth: 'shallow',\n maxFiles: 10,\n });\n const discovery = discoverResult.metadata;\n\n console.log(\n chalk.cyan('Keywords: ') +\n chalk.gray(discovery.keywords.slice(0, 8).join(', '))\n );\n console.log('');\n\n console.log(chalk.cyan('Top Relevant Files:'));\n for (const file of discovery.files.slice(0, 5)) {\n const icon =\n file.relevance === 'high' ? chalk.green('*') : chalk.yellow('-');\n console.log(`${icon} ${file.path}`);\n }\n\n if (session.decisions?.length > 0) {\n console.log('');\n console.log(chalk.cyan('Recent Decisions:'));\n for (const d of session.decisions.slice(0, 3)) {\n console.log(chalk.gray(` [${d.type}] ${d.text.slice(0, 50)}...`));\n }\n }\n\n console.log('');\n console.log(\n chalk.gray('Use \"stackmemory discovery files\" for detailed discovery')\n );\n } finally {\n db.close();\n }\n });\n\n return discovery;\n}\n"],
4
+ "sourcesContent": ["/**\n * Discovery CLI Commands\n * Discover relevant files based on current context\n */\n\nimport { Command } from 'commander';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport chalk from 'chalk';\nimport { FrameManager } from '../../core/context/index.js';\nimport { LLMContextRetrieval } from '../../core/retrieval/index.js';\nimport { DiscoveryHandlers } from '../../integrations/mcp/handlers/discovery-handlers.js';\n\nexport function createDiscoveryCommands(): Command {\n const discovery = new Command('discovery')\n .alias('discover')\n .description('Discover relevant files based on current context');\n\n // Main discovery command\n discovery\n .command('files')\n .alias('f')\n .description('Discover files relevant to current context')\n .option('-q, --query <text>', 'Focus discovery on specific query')\n .option(\n '-d, --depth <level>',\n 'Search depth: shallow, medium, deep',\n 'medium'\n )\n .option('-m, --max <n>', 'Maximum files to return', '20')\n .option('-i, --include <patterns>', 'Include patterns (comma-separated)')\n .option('-e, --exclude <patterns>', 'Exclude patterns (comma-separated)')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n console.log(chalk.gray('Run \"stackmemory init\" first.'));\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n console.log(chalk.blue('\\nDiscovering relevant files...\\n'));\n\n const result = await handlers.handleDiscover({\n query: options.query,\n depth: options.depth as 'shallow' | 'medium' | 'deep',\n maxFiles: parseInt(options.max),\n includePatterns: options.include?.split(','),\n excludePatterns: options.exclude?.split(','),\n });\n\n // Display results\n const metadata = result.metadata;\n\n console.log(chalk.cyan('Context Summary'));\n console.log(chalk.gray(metadata.contextSummary));\n console.log('');\n\n console.log(chalk.cyan('Keywords Extracted'));\n console.log(chalk.gray(metadata.keywords.slice(0, 15).join(', ')));\n console.log('');\n\n console.log(chalk.cyan('Relevant Files'));\n for (const file of metadata.files.slice(0, parseInt(options.max))) {\n const icon =\n file.relevance === 'high'\n ? chalk.green('[HIGH]')\n : file.relevance === 'medium'\n ? chalk.yellow('[MED]')\n : chalk.gray('[LOW]');\n console.log(`${icon} ${chalk.white(file.path)}`);\n console.log(chalk.gray(` ${file.reason}`));\n }\n\n if (Object.keys(metadata.mdContext).length > 0) {\n console.log('');\n console.log(chalk.cyan('MD Files Parsed'));\n for (const mdFile of Object.keys(metadata.mdContext)) {\n console.log(chalk.gray(` - ${mdFile}`));\n }\n }\n\n console.log('');\n } finally {\n db.close();\n }\n });\n\n // Related files command\n discovery\n .command('related')\n .alias('r')\n .description('Find files related to a specific file or concept')\n .option('-f, --file <path>', 'File to find related files for')\n .option('-c, --concept <text>', 'Concept to search for')\n .option('-m, --max <n>', 'Maximum files to return', '10')\n .action(async (options) => {\n if (!options.file && !options.concept) {\n console.log(chalk.red('Either --file or --concept is required'));\n return;\n }\n\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n const target = options.file || options.concept;\n console.log(chalk.blue(`\\nFinding files related to: ${target}\\n`));\n\n const result = await handlers.handleRelatedFiles({\n file: options.file,\n concept: options.concept,\n maxFiles: parseInt(options.max),\n });\n\n const files = result.metadata.relatedFiles;\n\n if (files.length === 0) {\n console.log(chalk.gray('No related files found.'));\n return;\n }\n\n for (const file of files) {\n const icon =\n file.relevance === 'high'\n ? chalk.green('[HIGH]')\n : chalk.yellow('[MED]');\n console.log(`${icon} ${chalk.white(file.path)}`);\n console.log(chalk.gray(` ${file.reason}`));\n }\n\n console.log('');\n } finally {\n db.close();\n }\n });\n\n // Session summary command\n discovery\n .command('session')\n .alias('s')\n .description('Get current session summary')\n .option('--no-files', 'Exclude recent files')\n .option('--no-decisions', 'Exclude recent decisions')\n .action(async (options) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n const result = await handlers.handleSessionSummary({\n includeFiles: options.files !== false,\n includeDecisions: options.decisions !== false,\n });\n\n const summary = result.metadata;\n\n console.log(chalk.blue('\\nSession Summary\\n'));\n\n console.log(`${chalk.cyan('Current Goal:')} ${summary.currentGoal}`);\n console.log(`${chalk.cyan('Active Frames:')} ${summary.activeFrames}`);\n console.log(`${chalk.cyan('Stack Depth:')} ${summary.stackDepth}`);\n\n if (summary.recentFiles?.length > 0) {\n console.log(chalk.cyan('\\nRecent Files:'));\n for (const f of summary.recentFiles.slice(0, 10)) {\n console.log(chalk.gray(` - ${f}`));\n }\n }\n\n if (summary.decisions?.length > 0) {\n console.log(chalk.cyan('\\nRecent Decisions:'));\n for (const d of summary.decisions.slice(0, 5)) {\n console.log(\n chalk.gray(\n ` [${d.type}] ${d.text.slice(0, 60)}${d.text.length > 60 ? '...' : ''}`\n )\n );\n }\n }\n\n console.log('');\n } finally {\n db.close();\n }\n });\n\n // Quick context command (default)\n discovery\n .command('quick', { isDefault: true })\n .description('Quick discovery based on current context')\n .action(async () => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n chalk.red('StackMemory not initialized in this directory.')\n );\n console.log(chalk.gray('Run \"stackmemory init\" first.'));\n return;\n }\n\n const db = new Database(dbPath);\n\n try {\n let projectId = 'default';\n try {\n const row = db\n .prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)\n .get() as any;\n if (row?.value) projectId = row.value;\n } catch {}\n\n const frameManager = new FrameManager(db, projectId, {\n skipContextBridge: true,\n });\n const contextRetrieval = new LLMContextRetrieval(\n db,\n frameManager,\n projectId\n );\n const handlers = new DiscoveryHandlers({\n frameManager,\n contextRetrieval,\n db,\n projectRoot,\n });\n\n console.log(chalk.blue('\\nQuick Discovery\\n'));\n\n // Get session summary first\n const sessionResult = await handlers.handleSessionSummary({\n includeFiles: true,\n includeDecisions: true,\n });\n const session = sessionResult.metadata;\n\n console.log(`${chalk.cyan('Current:')} ${session.currentGoal}`);\n console.log(`${chalk.cyan('Stack:')} ${session.stackDepth} frames`);\n console.log('');\n\n // Quick file discovery\n const discoverResult = await handlers.handleDiscover({\n depth: 'shallow',\n maxFiles: 10,\n });\n const discovery = discoverResult.metadata;\n\n console.log(\n chalk.cyan('Keywords: ') +\n chalk.gray(discovery.keywords.slice(0, 8).join(', '))\n );\n console.log('');\n\n console.log(chalk.cyan('Top Relevant Files:'));\n for (const file of discovery.files.slice(0, 5)) {\n const icon =\n file.relevance === 'high' ? chalk.green('*') : chalk.yellow('-');\n console.log(`${icon} ${file.path}`);\n }\n\n if (session.decisions?.length > 0) {\n console.log('');\n console.log(chalk.cyan('Recent Decisions:'));\n for (const d of session.decisions.slice(0, 3)) {\n console.log(chalk.gray(` [${d.type}] ${d.text.slice(0, 50)}...`));\n }\n }\n\n console.log('');\n console.log(\n chalk.gray('Use \"stackmemory discovery files\" for detailed discovery')\n );\n } finally {\n db.close();\n }\n });\n\n return discovery;\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["discovery"]
7
7
  }
@@ -15,7 +15,7 @@ import {
15
15
  import { join } from "path";
16
16
  import Database from "better-sqlite3";
17
17
  import { z } from "zod";
18
- import { FrameManager } from "../../core/context/frame-manager.js";
18
+ import { FrameManager } from "../../core/context/index.js";
19
19
  import { LinearTaskManager } from "../../features/tasks/linear-task-manager.js";
20
20
  import { logger } from "../../core/monitoring/logger.js";
21
21
  import { EnhancedHandoffGenerator } from "../../core/session/enhanced-handoff.js";