@stackmemoryai/stackmemory 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/skills/claude-skills.ts"],
4
- "sourcesContent": ["/**\n * Claude Skills for StackMemory\n * Custom skills that integrate with Claude Code to enhance workflow\n */\n\nimport {\n FrameHandoffManager,\n type HandoffMetadata,\n} from '../core/context/frame-handoff-manager.js';\nimport { DualStackManager } from '../core/context/dual-stack-manager.js';\nimport { SQLiteAdapter } from '../core/database/sqlite-adapter.js';\nimport { ContextRetriever } from '../core/retrieval/context-retriever.js';\nimport type { FrameManager } from '../core/context/frame-manager.js';\nimport { logger } from '../core/monitoring/logger.js';\nimport {\n RepoIngestionSkill,\n type RepoIngestionOptions,\n} from './repo-ingestion-skill.js';\nimport { DashboardLauncherSkill } from './dashboard-launcher.js';\nimport {\n RecursiveAgentOrchestrator,\n type RLMOptions,\n} from './recursive-agent-orchestrator.js';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport type { Frame } from '../core/context/frame-manager.js';\n\n// Type definitions for Dig skill\ninterface Pattern {\n type: string;\n frequency: number;\n examples: string[];\n}\n\ninterface Decision {\n timestamp: string;\n decision: string;\n context: string;\n}\n\ninterface TimelineEntry {\n timestamp: string;\n event: string;\n description: string;\n}\n\nexport interface SkillContext {\n projectId: string;\n userId: string;\n dualStackManager: DualStackManager;\n handoffManager: FrameHandoffManager;\n contextRetriever: ContextRetriever;\n database: SQLiteAdapter;\n frameManager?: FrameManager;\n}\n\nexport interface SkillResult {\n success: boolean;\n message: string;\n data?: unknown;\n action?: string;\n}\n\n/**\n * Skill 1: Frame Handoff Orchestrator\n * Streamlines frame handoffs between team members\n */\nexport class HandoffSkill {\n constructor(private context: SkillContext) {}\n\n async execute(\n targetUser: string,\n message: string,\n options?: {\n frames?: string[];\n priority?: 'low' | 'medium' | 'high' | 'critical';\n autoDetect?: boolean;\n }\n ): Promise<SkillResult> {\n try {\n const activeStack = this.context.dualStackManager.getActiveStack();\n\n // Auto-detect frames if not specified\n let framesToHandoff = options?.frames || [];\n if (options?.autoDetect !== false && framesToHandoff.length === 0) {\n // Get recent frames that are completed or have errors\n const allFrames = await activeStack.getAllFrames();\n // Filter for completed frames OR frames with errors (not both conditions required)\n const relevantFrames = allFrames.filter(\n (f) =>\n f.state === 'completed' ||\n (f.outputs &&\n Array.isArray(f.outputs) &&\n f.outputs.some((o) => o.type === 'error'))\n );\n framesToHandoff = relevantFrames\n .slice(-5) // Last 5 relevant frames\n .map((f) => f.frameId);\n }\n\n if (framesToHandoff.length === 0) {\n return {\n success: false,\n message:\n 'No frames to handoff. Specify frames or complete some work first.',\n };\n }\n\n // Generate comprehensive handoff summary\n const frameDetails = await Promise.all(\n framesToHandoff.map((id) => activeStack.getFrame(id))\n );\n\n const summary = this.generateHandoffSummary(frameDetails, message);\n\n // Create handoff metadata\n const metadata: HandoffMetadata = {\n initiatedAt: new Date(),\n initiatorId: this.context.userId,\n targetUserId: targetUser,\n frameContext: {\n totalFrames: framesToHandoff.length,\n frameTypes: [\n ...new Set(frameDetails.map((f) => f?.type || 'unknown')),\n ],\n estimatedSize: JSON.stringify(frameDetails).length,\n dependencies: this.extractDependencies(frameDetails),\n },\n businessContext: {\n priority: options?.priority || 'medium',\n stakeholders: [targetUser],\n },\n };\n\n // Get target stack (shared or create new)\n const availableStacks =\n await this.context.dualStackManager.getAvailableStacks();\n let targetStackId = availableStacks.find(\n (s) => s.type === 'shared'\n )?.stackId;\n\n if (!targetStackId) {\n targetStackId = await this.context.dualStackManager.createSharedStack(\n 'team',\n `Handoff: ${message.slice(0, 50)}`,\n this.context.userId\n );\n }\n\n // Initiate handoff\n const handoffId = await this.context.handoffManager.initiateHandoff(\n targetStackId,\n framesToHandoff,\n metadata,\n targetUser,\n summary\n );\n\n // Create action items for recipient\n const actionItems = this.generateActionItems(frameDetails);\n\n return {\n success: true,\n message: `Handoff initiated to @${targetUser}`,\n data: {\n handoffId,\n frameCount: framesToHandoff.length,\n priority: options?.priority || 'medium',\n actionItems,\n targetStack: targetStackId,\n },\n action: `Notified ${targetUser}. Handoff ID: ${handoffId}`,\n };\n } catch (error: unknown) {\n logger.error('Handoff skill error:', error);\n return {\n success: false,\n message: `Failed to initiate handoff: ${error.message}`,\n };\n }\n }\n\n private generateHandoffSummary(frames: Frame[], message: string): string {\n const completed = frames.filter((f) => f?.state === 'completed').length;\n const blocked = frames.filter((f) =>\n f?.outputs?.some((o) => o.type === 'error')\n ).length;\n\n return `\n## Handoff Summary\n**Message**: ${message}\n**Frames**: ${frames.length} total (${completed} completed, ${blocked} blocked)\n\n### Work Completed:\n${frames\n .filter((f) => f?.state === 'completed')\n .map((f) => `- ${f.name}: ${f.digest_deterministic?.summary || 'No summary'}`)\n .join('\\n')}\n\n### Attention Required:\n${\n frames\n .filter((f) => f?.outputs?.some((o) => o.type === 'error'))\n .map(\n (f) =>\n `- ${f.name}: ${f.outputs.find((o) => o.type === 'error')?.content || 'Error'}`\n )\n .join('\\n') || 'None'\n}\n\n### Context:\n${frames\n .map((f) => f?.digest_ai?.context || '')\n .filter(Boolean)\n .join('\\n')}\n `.trim();\n }\n\n private extractDependencies(frames: Frame[]): string[] {\n const deps = new Set<string>();\n frames.forEach((frame) => {\n if (frame?.inputs?.dependencies) {\n if (Array.isArray(frame.inputs.dependencies)) {\n frame.inputs.dependencies.forEach((d) => deps.add(d));\n }\n }\n // Extract from outputs\n if (frame?.outputs) {\n frame.outputs.forEach((output) => {\n if (output.type === 'dependency') {\n deps.add(output.content);\n }\n });\n }\n });\n return Array.from(deps);\n }\n\n private generateActionItems(frames: Frame[]): string[] {\n const items: string[] = [];\n\n frames.forEach((frame) => {\n // Check for TODOs in outputs\n if (frame?.outputs) {\n frame.outputs.forEach((output) => {\n if (output.type === 'todo' || output.content?.includes('TODO')) {\n items.push(output.content);\n }\n });\n }\n\n // Check for errors that need resolution\n if (frame?.outputs?.some((o) => o.type === 'error')) {\n items.push(`Resolve error in ${frame.name}`);\n }\n\n // Check for pending tests - look in multiple places\n if (\n frame?.inputs?.tests === 'pending' ||\n frame?.type === 'implementation' ||\n (frame?.name && frame.name.toLowerCase().includes('implementation'))\n ) {\n items.push(`Write tests for ${frame.name}`);\n }\n });\n\n return items;\n }\n}\n\n/**\n * Skill 7: Recovery Checkpoint Manager\n * Create and manage recovery points\n */\nexport class CheckpointSkill {\n private checkpointDir: string;\n\n constructor(private context: SkillContext) {\n this.checkpointDir = path.join(\n os.homedir(),\n '.stackmemory',\n 'checkpoints',\n context.projectId\n );\n fs.mkdirSync(this.checkpointDir, { recursive: true });\n }\n\n async create(\n description: string,\n options?: {\n autoDetectRisky?: boolean;\n includeFiles?: string[];\n metadata?: Record<string, unknown>;\n }\n ): Promise<SkillResult> {\n try {\n const timestamp = Date.now();\n const checkpointId = `checkpoint-${timestamp}-${Math.random().toString(36).slice(2, 8)}`;\n\n // Get current context\n const activeStack = this.context.dualStackManager.getActiveStack();\n const currentContext = this.context.dualStackManager.getCurrentContext();\n const allFrames = await activeStack.getAllFrames();\n\n // Create checkpoint data\n const checkpoint = {\n id: checkpointId,\n timestamp,\n description,\n context: {\n stackId: currentContext.stackId,\n stackType: currentContext.type,\n userId: this.context.userId,\n projectId: this.context.projectId,\n },\n frames: allFrames,\n metadata: {\n ...options?.metadata,\n frameCount: allFrames.length,\n activeFrames: allFrames.filter((f) => f.state === 'active').length,\n completedFrames: allFrames.filter((f) => f.state === 'completed')\n .length,\n },\n files: options?.includeFiles || [],\n };\n\n // Save checkpoint\n const checkpointPath = path.join(\n this.checkpointDir,\n `${checkpointId}.json`\n );\n fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2));\n\n // Save file backups if specified\n if (options?.includeFiles && options.includeFiles.length > 0) {\n const filesDir = path.join(this.checkpointDir, checkpointId, 'files');\n fs.mkdirSync(filesDir, { recursive: true });\n\n for (const file of options.includeFiles) {\n if (fs.existsSync(file)) {\n const basename = path.basename(file);\n const backupPath = path.join(filesDir, basename);\n fs.copyFileSync(file, backupPath);\n }\n }\n }\n\n // Auto-detect risky operations\n if (options?.autoDetectRisky) {\n const riskyPatterns = [\n 'migration',\n 'database',\n 'deploy',\n 'production',\n 'delete',\n 'remove',\n 'drop',\n 'migrate', // Add more specific pattern\n ];\n\n const isRisky = allFrames.some((frame) => {\n const nameMatches =\n frame.name &&\n riskyPatterns.some((pattern) =>\n frame.name.toLowerCase().includes(pattern)\n );\n const commandMatches =\n frame.inputs?.command &&\n riskyPatterns.some((pattern) =>\n frame.inputs.command.toLowerCase().includes(pattern)\n );\n return nameMatches || commandMatches;\n });\n\n if (isRisky) {\n checkpoint.metadata.riskyOperation = true;\n checkpoint.metadata.autoCheckpoint = true;\n }\n }\n\n // Update the checkpoint data after risky operation detection\n fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2));\n\n logger.info(`Created checkpoint: ${checkpointId}`);\n\n return {\n success: true,\n message: `Checkpoint created: ${description}`,\n data: {\n checkpointId,\n timestamp: new Date(timestamp).toISOString(),\n frameCount: checkpoint.metadata.frameCount,\n location: checkpointPath,\n },\n action: `Saved checkpoint ${checkpointId}`,\n };\n } catch (error: unknown) {\n logger.error('Checkpoint creation error:', error);\n return {\n success: false,\n message: `Failed to create checkpoint: ${error.message}`,\n };\n }\n }\n\n async restore(checkpointId: string): Promise<SkillResult> {\n try {\n const checkpointPath = path.join(\n this.checkpointDir,\n `${checkpointId}.json`\n );\n\n if (!fs.existsSync(checkpointPath)) {\n // Try to find by partial ID\n const files = fs.readdirSync(this.checkpointDir);\n const match = files.find((f) => f.includes(checkpointId));\n if (match) {\n checkpointId = match.replace('.json', '');\n } else {\n return {\n success: false,\n message: `Checkpoint not found: ${checkpointId}`,\n };\n }\n }\n\n const checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n\n // Switch to checkpoint's stack\n await this.context.dualStackManager.switchToStack(\n checkpoint.context.stackId\n );\n\n // Restore frames (this is a simplified version - real implementation would be more complex)\n // const activeStack = this.context.dualStackManager.getActiveStack();\n\n // Clear current frames and restore from checkpoint\n // Note: This is a conceptual implementation - actual frame restoration\n // would need more sophisticated state management\n\n // Restore files if they exist\n const filesDir = path.join(this.checkpointDir, checkpointId, 'files');\n if (fs.existsSync(filesDir)) {\n const files = fs.readdirSync(filesDir);\n for (const file of files) {\n const backupPath = path.join(filesDir, file);\n const originalPath = checkpoint.files.find(\n (f) => path.basename(f) === file\n );\n if (originalPath && fs.existsSync(backupPath)) {\n fs.copyFileSync(backupPath, originalPath);\n }\n }\n }\n\n logger.info(`Restored checkpoint: ${checkpointId}`);\n\n return {\n success: true,\n message: `Restored to checkpoint: ${checkpoint.description}`,\n data: {\n checkpointId,\n timestamp: new Date(checkpoint.timestamp).toISOString(),\n frameCount: checkpoint.metadata.frameCount,\n filesRestored: checkpoint.files.length,\n },\n action: `Restored checkpoint from ${new Date(checkpoint.timestamp).toLocaleString()}`,\n };\n } catch (error: unknown) {\n logger.error('Checkpoint restoration error:', error);\n return {\n success: false,\n message: `Failed to restore checkpoint: ${error.message}`,\n };\n }\n }\n\n async list(options?: { limit?: number; since?: Date }): Promise<SkillResult> {\n try {\n const files = fs\n .readdirSync(this.checkpointDir)\n .filter((f) => f.endsWith('.json'))\n .map((f) => {\n const checkpointPath = path.join(this.checkpointDir, f);\n const checkpoint = JSON.parse(\n fs.readFileSync(checkpointPath, 'utf-8')\n );\n return checkpoint;\n })\n .filter((c) => !options?.since || c.timestamp > options.since.getTime())\n .sort((a, b) => b.timestamp - a.timestamp)\n .slice(0, options?.limit || 10);\n\n return {\n success: true,\n message: `Found ${files.length} checkpoints`,\n data: files.map((c) => ({\n id: c.id,\n description: c.description,\n timestamp: new Date(c.timestamp).toISOString(),\n frameCount: c.metadata.frameCount,\n risky: c.metadata.riskyOperation || false,\n })),\n };\n } catch (error: unknown) {\n logger.error('Checkpoint list error:', error);\n return {\n success: false,\n message: `Failed to list checkpoints: ${error.message}`,\n };\n }\n }\n\n async diff(checkpoint1: string, checkpoint2: string): Promise<SkillResult> {\n try {\n const cp1 = await this.loadCheckpoint(checkpoint1);\n const cp2 = await this.loadCheckpoint(checkpoint2);\n\n if (!cp1 || !cp2) {\n return {\n success: false,\n message: 'One or both checkpoints not found',\n };\n }\n\n const diff = {\n timeDiff: Math.abs(cp2.timestamp - cp1.timestamp),\n framesDiff: cp2.frames.length - cp1.frames.length,\n newFrames: cp2.frames.filter(\n (f2) => !cp1.frames.some((f1) => f1.frameId === f2.frameId)\n ),\n removedFrames: cp1.frames.filter(\n (f1) => !cp2.frames.some((f2) => f2.frameId === f1.frameId)\n ),\n modifiedFrames: cp2.frames.filter((f2) => {\n const f1 = cp1.frames.find((f) => f.frameId === f2.frameId);\n return f1 && JSON.stringify(f1) !== JSON.stringify(f2);\n }),\n };\n\n return {\n success: true,\n message: `Diff between ${cp1.description} and ${cp2.description}`,\n data: {\n timeDiff: `${Math.round(diff.timeDiff / 1000 / 60)} minutes`,\n framesDiff:\n diff.framesDiff > 0 ? `+${diff.framesDiff}` : `${diff.framesDiff}`,\n newFrames: diff.newFrames.length,\n removedFrames: diff.removedFrames.length,\n modifiedFrames: diff.modifiedFrames.length,\n details: diff,\n },\n };\n } catch (error: unknown) {\n logger.error('Checkpoint diff error:', error);\n return {\n success: false,\n message: `Failed to diff checkpoints: ${error.message}`,\n };\n }\n }\n\n private async loadCheckpoint(checkpointId: string): Promise<unknown> {\n const checkpointPath = path.join(\n this.checkpointDir,\n `${checkpointId}.json`\n );\n if (fs.existsSync(checkpointPath)) {\n return JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n }\n\n // Try partial match\n const files = fs.readdirSync(this.checkpointDir);\n const match = files.find((f) => f.includes(checkpointId));\n if (match) {\n const path = path.join(this.checkpointDir, match);\n return JSON.parse(fs.readFileSync(path, 'utf-8'));\n }\n\n return null;\n }\n}\n\n/**\n * Skill 2: Context Archaeologist\n * Deep historical context retrieval across sessions\n */\nexport class ArchaeologistSkill {\n constructor(private context: SkillContext) {}\n\n async dig(\n query: string,\n options?: {\n depth?: string; // e.g., \"6months\", \"30days\", \"all\"\n patterns?: boolean;\n decisions?: boolean;\n timeline?: boolean;\n }\n ): Promise<SkillResult> {\n try {\n // Parse depth\n const depth = this.parseDepth(options?.depth || '30days');\n const since = new Date(Date.now() - depth);\n\n // Use context retriever for semantic search\n const results = await this.context.contextRetriever.retrieve({\n query,\n projectId: this.context.projectId,\n limit: 50,\n minScore: 0.3,\n });\n\n // Filter by date if specified\n const filtered = results.filter(\n (r) => !depth || new Date(r.timestamp) > since\n );\n\n // Extract patterns if requested\n let patterns: Pattern[] = [];\n if (options?.patterns) {\n patterns = this.extractPatterns(filtered);\n }\n\n // Extract decisions if requested\n let decisions: Decision[] = [];\n if (options?.decisions) {\n decisions = this.extractDecisions(filtered);\n }\n\n // Generate timeline if requested\n let timeline: TimelineEntry[] = [];\n if (options?.timeline) {\n timeline = this.generateTimeline(filtered);\n }\n\n // Find most relevant context\n const topResults = filtered.slice(0, 10);\n const summary = this.generateArchaeologySummary(\n topResults,\n patterns,\n decisions,\n timeline\n );\n\n return {\n success: true,\n message: `Found ${filtered.length} relevant results`,\n data: {\n totalResults: filtered.length,\n timeRange: {\n from: since.toISOString(),\n to: new Date().toISOString(),\n },\n topResults: topResults.map((r) => ({\n frameId: r.frameId,\n score: r.score,\n timestamp: r.timestamp,\n summary: r.content.slice(0, 100) + '...',\n })),\n patterns,\n decisions,\n timeline,\n summary,\n },\n action: `Analyzed ${filtered.length} frames from ${options?.depth || '30days'} of history`,\n };\n } catch (error: unknown) {\n logger.error('Archaeology skill error:', error);\n return {\n success: false,\n message: `Failed to dig through context: ${error.message}`,\n };\n }\n }\n\n private parseDepth(depth: string): number {\n const match = depth.match(/^(\\d+)(days?|weeks?|months?|years?|all)$/i);\n if (!match) {\n return 30 * 24 * 60 * 60 * 1000; // Default 30 days\n }\n\n const [, num, unit] = match;\n const value = parseInt(num);\n\n switch (unit.toLowerCase()) {\n case 'day':\n case 'days':\n return value * 24 * 60 * 60 * 1000;\n case 'week':\n case 'weeks':\n return value * 7 * 24 * 60 * 60 * 1000;\n case 'month':\n case 'months':\n return value * 30 * 24 * 60 * 60 * 1000;\n case 'year':\n case 'years':\n return value * 365 * 24 * 60 * 60 * 1000;\n case 'all':\n return Number.MAX_SAFE_INTEGER;\n default:\n return 30 * 24 * 60 * 60 * 1000;\n }\n }\n\n private extractPatterns(results: Frame[]): Pattern[] {\n const patterns: Map<string, number> = new Map();\n\n // Common patterns to look for\n const patternTypes = [\n { regex: /test.*then.*implement/i, name: 'TDD' },\n { regex: /refactor/i, name: 'Refactoring' },\n { regex: /debug|fix|error|bug/i, name: 'Debugging' },\n { regex: /implement.*feature/i, name: 'Feature Development' },\n { regex: /review|code review/i, name: 'Code Review' },\n { regex: /deploy|release/i, name: 'Deployment' },\n { regex: /optimize|performance/i, name: 'Optimization' },\n ];\n\n results.forEach((result) => {\n patternTypes.forEach((pattern) => {\n if (pattern.regex.test(result.content)) {\n patterns.set(pattern.name, (patterns.get(pattern.name) || 0) + 1);\n }\n });\n });\n\n return Array.from(patterns.entries())\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n }\n\n private extractDecisions(results: Frame[]): Decision[] {\n const decisions: Decision[] = [];\n\n // Keywords that indicate decisions\n const decisionKeywords = [\n 'decided',\n 'chose',\n 'selected',\n 'will use',\n 'going with',\n 'approach',\n 'strategy',\n 'solution',\n ];\n\n results.forEach((result) => {\n const content = result.content.toLowerCase();\n if (decisionKeywords.some((keyword) => content.includes(keyword))) {\n // Extract sentence containing the decision\n const sentences = result.content.split(/[.!?]+/);\n const decisionSentence = sentences.find((s) =>\n decisionKeywords.some((k) => s.toLowerCase().includes(k))\n );\n\n if (decisionSentence) {\n decisions.push({\n frameId: result.frameId,\n timestamp: result.timestamp,\n decision: decisionSentence.trim(),\n context: result.content.slice(0, 200),\n });\n }\n }\n });\n\n return decisions.slice(0, 10); // Top 10 decisions\n }\n\n private generateTimeline(results: Frame[]): TimelineEntry[] {\n // Group by day\n const timeline: Map<string, Frame[]> = new Map();\n\n results.forEach((result) => {\n const date = new Date(result.timestamp).toDateString();\n if (!timeline.has(date)) {\n timeline.set(date, []);\n }\n const dateItems = timeline.get(date);\n if (dateItems) {\n dateItems.push(result);\n }\n });\n\n return Array.from(timeline.entries())\n .map(([date, items]) => ({\n date,\n itemCount: items.length,\n highlights: items.slice(0, 3).map((item) => ({\n frameId: item.frameId,\n summary: item.content.slice(0, 50) + '...',\n })),\n }))\n .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());\n }\n\n private generateArchaeologySummary(\n results: Frame[],\n patterns: Pattern[],\n decisions: Decision[],\n timeline: TimelineEntry[]\n ): string {\n let summary = '## Context Archaeology Report\\n\\n';\n\n if (results.length > 0) {\n summary += `### Most Relevant Context (${results.length} results)\\n`;\n results.slice(0, 3).forEach((r) => {\n summary += `- **${new Date(r.timestamp).toLocaleDateString()}**: ${r.content.slice(0, 100)}...\\n`;\n });\n summary += '\\n';\n }\n\n if (patterns.length > 0) {\n summary += `### Detected Patterns\\n`;\n patterns.slice(0, 5).forEach((p) => {\n summary += `- ${p.name}: ${p.count} occurrences\\n`;\n });\n summary += '\\n';\n }\n\n if (decisions.length > 0) {\n summary += `### Key Decisions\\n`;\n decisions.slice(0, 5).forEach((d) => {\n summary += `- **${new Date(d.timestamp).toLocaleDateString()}**: ${d.decision}\\n`;\n });\n summary += '\\n';\n }\n\n if (timeline.length > 0) {\n summary += `### Activity Timeline\\n`;\n timeline.slice(0, 5).forEach((t) => {\n summary += `- **${t.date}**: ${t.itemCount} activities\\n`;\n });\n }\n\n return summary;\n }\n}\n\n/**\n * Main Claude Skills Manager\n */\nexport class ClaudeSkillsManager {\n private handoffSkill: HandoffSkill;\n private checkpointSkill: CheckpointSkill;\n private archaeologistSkill: ArchaeologistSkill;\n private dashboardLauncher: DashboardLauncherSkill;\n private repoIngestionSkill: RepoIngestionSkill | null = null;\n private rlmOrchestrator: RecursiveAgentOrchestrator | null = null;\n\n constructor(private context: SkillContext) {\n this.handoffSkill = new HandoffSkill(context);\n this.checkpointSkill = new CheckpointSkill(context);\n this.archaeologistSkill = new ArchaeologistSkill(context);\n\n // Initialize dashboard launcher (lazy import to avoid circular deps)\n import('./dashboard-launcher.js').then((module) => {\n this.dashboardLauncher = new module.DashboardLauncherSkill();\n // Don't auto-launch dashboard to avoid startup errors\n // User can manually launch with 'stackmemory skills dashboard launch'\n logger.info('Dashboard launcher initialized (manual launch required)');\n });\n\n // Initialize repo ingestion skill if ChromaDB is configured\n const chromaConfig = {\n apiKey: process.env['CHROMADB_API_KEY'] || '',\n tenant: process.env['CHROMADB_TENANT'] || '',\n database: process.env['CHROMADB_DATABASE'] || 'stackmemory',\n collectionName: process.env['CHROMADB_COLLECTION'] || 'stackmemory_repos',\n };\n\n if (chromaConfig.apiKey && chromaConfig.tenant) {\n this.repoIngestionSkill = new RepoIngestionSkill(\n chromaConfig,\n context.userId,\n process.env['CHROMADB_TEAM_ID']\n );\n this.repoIngestionSkill.initialize().catch((error: unknown) => {\n logger.warn('Repo ingestion skill initialization failed:', error);\n });\n }\n\n // Initialize RLM Orchestrator\n // Import dynamically to avoid circular dependencies\n import('../features/tasks/linear-task-manager.js')\n .then((module) => {\n const taskStore = new module.LinearTaskManager();\n\n // Use frameManager from context if available\n const frameManager = context.frameManager;\n if (!frameManager) {\n throw new Error(\n 'FrameManager not provided in context - required for RLM orchestrator'\n );\n }\n\n this.rlmOrchestrator = new RecursiveAgentOrchestrator(\n frameManager,\n context.dualStackManager,\n context.contextRetriever,\n taskStore\n );\n\n logger.info('RLM Orchestrator initialized');\n })\n .catch((error: unknown) => {\n logger.warn('RLM Orchestrator initialization failed:', error);\n });\n }\n\n async executeSkill(\n skillName: string,\n args: string[],\n options?: Record<string, unknown>\n ): Promise<SkillResult> {\n switch (skillName) {\n case 'handoff':\n return this.handoffSkill.execute(args[0], args[1], options);\n\n case 'checkpoint':\n const subcommand = args[0];\n switch (subcommand) {\n case 'create':\n return this.checkpointSkill.create(args[1], options);\n case 'restore':\n return this.checkpointSkill.restore(args[1]);\n case 'list':\n return this.checkpointSkill.list(options);\n case 'diff':\n return this.checkpointSkill.diff(args[1], args[2]);\n default:\n return {\n success: false,\n message: `Unknown checkpoint subcommand: ${subcommand}`,\n };\n }\n\n case 'dig':\n return this.archaeologistSkill.dig(args[0], options);\n\n case 'lint':\n // Linting task using RLM orchestrator with linting agent\n if (!this.rlmOrchestrator) {\n return {\n success: false,\n message:\n 'RLM Orchestrator not initialized. Please wait a moment and try again.',\n };\n }\n\n const lintPath = args[0] || process.cwd();\n const lintOptions = {\n ...options,\n // Force use of linting agent\n agents: ['linting'],\n maxParallel: 1,\n reviewStages: 1,\n verboseLogging: true,\n } as RLMOptions;\n\n const lintTask = `Perform comprehensive linting on ${lintPath}: Check for syntax errors, type issues, formatting violations, security vulnerabilities, performance anti-patterns, and unused code. Provide actionable fixes.`;\n\n try {\n const result = await this.rlmOrchestrator.execute(\n lintTask,\n { path: lintPath, ...options },\n lintOptions\n );\n\n return {\n success: result.success,\n message: `Linting ${result.success ? 'completed' : 'failed'}`,\n data: {\n issuesFound: result.issuesFound,\n issuesFixed: result.issuesFixed,\n duration: `${result.duration}ms`,\n totalTokens: result.totalTokens,\n details: result.rootNode,\n },\n };\n } catch (error) {\n return {\n success: false,\n message: `Linting failed: ${error.message}`,\n };\n }\n\n case 'rlm':\n if (!this.rlmOrchestrator) {\n return {\n success: false,\n message:\n 'RLM Orchestrator not initialized. Please wait a moment and try again.',\n };\n }\n return this.rlmOrchestrator.execute(args[0], options as RLMOptions);\n\n case 'repo':\n case 'ingest':\n if (!this.repoIngestionSkill) {\n return {\n success: false,\n message:\n 'Repo ingestion skill not initialized. Please configure ChromaDB.',\n };\n }\n\n const repoCommand = args[0];\n switch (repoCommand) {\n case 'ingest':\n const repoPath = args[1] || process.cwd();\n const repoName = args[2] || path.basename(repoPath);\n return await this.repoIngestionSkill.ingestRepository(\n repoPath,\n repoName,\n options as RepoIngestionOptions\n );\n\n case 'update':\n const updatePath = args[1] || process.cwd();\n const updateName = args[2] || path.basename(updatePath);\n return await this.repoIngestionSkill.updateRepository(\n updatePath,\n updateName,\n options as RepoIngestionOptions\n );\n\n case 'search':\n const query = args[1];\n if (!query) {\n return {\n success: false,\n message: 'Search query required',\n };\n }\n const results = await this.repoIngestionSkill.searchCode(query, {\n repoName: options?.repoName as string,\n language: options?.language as string,\n limit: options?.limit as number,\n includeContext: options?.includeContext as boolean,\n });\n return {\n success: true,\n message: `Found ${results.length} results`,\n data: results,\n };\n\n case 'stats':\n const stats = await this.repoIngestionSkill.getRepoStats(args[1]);\n return {\n success: true,\n message: 'Repository statistics',\n data: stats,\n };\n\n default:\n return {\n success: false,\n message: `Unknown repo command: ${repoCommand}. Use: ingest, update, search, or stats`,\n };\n }\n\n case 'dashboard':\n const dashboardCmd = args[0];\n if (!this.dashboardLauncher) {\n return {\n success: false,\n message: 'Dashboard launcher not yet initialized',\n };\n }\n switch (dashboardCmd) {\n case 'launch':\n await this.dashboardLauncher.launch();\n return {\n success: true,\n message: 'Dashboard launched',\n action: 'open-browser',\n };\n case 'stop':\n await this.dashboardLauncher.stop();\n return {\n success: true,\n message: 'Dashboard stopped',\n };\n default:\n await this.dashboardLauncher.launch();\n return {\n success: true,\n message: 'Dashboard launched',\n action: 'open-browser',\n };\n }\n\n case 'recursive':\n if (!this.rlmOrchestrator) {\n return {\n success: false,\n message:\n 'RLM Orchestrator not initialized. Please wait a moment and try again.',\n };\n }\n\n const task = args.join(' ') || 'Analyze and improve the current code';\n const rlmOptions = options as RLMOptions;\n\n try {\n logger.info('Starting RLM execution', { task });\n\n const result = await this.rlmOrchestrator.execute(\n task,\n {\n files: rlmOptions.files || [],\n query: task,\n },\n rlmOptions\n );\n\n return {\n success: result.success,\n message: `RLM execution ${result.success ? 'completed' : 'failed'}`,\n data: {\n duration: `${result.duration}ms`,\n totalTokens: result.totalTokens,\n totalCost: `$${result.totalCost.toFixed(2)}`,\n testsGenerated: result.testsGenerated,\n improvements: result.improvements.length,\n issuesFound: result.issuesFound,\n issuesFixed: result.issuesFixed,\n executionTree: result.rootNode,\n },\n };\n } catch (error) {\n logger.error('RLM execution error:', error);\n return {\n success: false,\n message: `RLM execution failed: ${error.message}`,\n };\n }\n\n default:\n return {\n success: false,\n message: `Unknown skill: ${skillName}`,\n };\n }\n }\n\n getAvailableSkills(): string[] {\n const skills = ['handoff', 'checkpoint', 'dig', 'dashboard'];\n if (this.repoIngestionSkill) {\n skills.push('repo');\n }\n if (this.rlmOrchestrator) {\n skills.push('rlm', 'lint');\n }\n return skills;\n }\n\n getSkillHelp(skillName: string): string {\n switch (skillName) {\n case 'handoff':\n return `\n/handoff @user \"message\" [--priority high] [--frames frame1,frame2]\nStreamline frame handoffs between team members\n`;\n\n case 'checkpoint':\n return `\n/checkpoint create \"description\" [--files file1,file2] [--auto-detect-risky]\n/checkpoint restore <id>\n/checkpoint list [--limit 10] [--since \"2024-01-01\"]\n/checkpoint diff <id1> <id2>\nCreate and manage recovery points\n`;\n\n case 'dig':\n return `\n/dig \"query\" [--depth 6months] [--patterns] [--decisions] [--timeline]\nDeep historical context retrieval across sessions\n`;\n\n case 'lint':\n return `\n/lint [path] [options]\nPerform comprehensive code linting and quality checks\n\nAutomatically checks for:\n- Syntax errors and type issues\n- Code formatting and style violations \n- Security vulnerabilities\n- Performance anti-patterns\n- Unused imports and dead code\n- Code smells and complexity issues\n\nUsage:\n stackmemory skills lint # Lint current directory\n stackmemory skills lint src/ # Lint specific directory\n stackmemory skills lint src/file.ts # Lint specific file\n\nOptions:\n --fix Automatically fix issues where possible\n --format Focus on formatting issues\n --security Focus on security vulnerabilities\n --performance Focus on performance issues\n --verbose Show detailed output\n\nExamples:\n stackmemory skills lint --fix\n stackmemory skills lint src/ --security --verbose\n`;\n\n case 'rlm':\n return `\n/rlm \"task description\" [options]\nExecute complex tasks with recursive agent orchestration\n\nOptions:\n --max-parallel <n> Max concurrent subagents (default: 5)\n --max-recursion <n> Max recursion depth (default: 4)\n --max-tokens-per-agent <n> Token budget per agent (default: 30000)\n --review-stages <n> Review iterations (default: 3)\n --quality-threshold <n> Target quality 0-1 (default: 0.85)\n --test-mode <mode> unit/integration/e2e/all (default: all)\n --verbose Show all operations\n --timeout-per-agent <s> Timeout in seconds (default: 300)\n\nExamples:\n stackmemory skills rlm \"Generate tests for API endpoints\"\n stackmemory skills rlm \"Refactor auth system\" --quality-threshold 0.95\n`;\n\n case 'dashboard':\n return `\n/dashboard [launch|stop]\nLaunch the StackMemory web dashboard for real-time monitoring\n- launch: Start the web dashboard and open in browser (default)\n- stop: Stop the dashboard server\nAuto-launches on new sessions when configured\n`;\n\n case 'repo':\n return `\n/repo ingest [path] [name] [--incremental] [--include-tests] [--include-docs]\n/repo update [path] [name] [--force-update]\n/repo search \"query\" [--repo-name name] [--language lang] [--limit n]\n/repo stats [repo-name]\n\nIngest and search code repositories in ChromaDB:\n- ingest: Index a new repository (defaults to current directory)\n- update: Update an existing repository with changes\n- search: Semantic search across ingested code\n- stats: View statistics about ingested repositories\n\nOptions:\n- --incremental: Only process changed files\n- --include-tests: Include test files in indexing\n- --include-docs: Include documentation files\n- --force-update: Force re-indexing of all files\n- --language: Filter search by programming language\n- --limit: Maximum search results (default: 20)\n`;\n\n case 'recursive':\n return `\n/rlm \"task description\" [options]\n\nRecursive Language Model orchestration using Claude Code's Task tool:\n- Decomposes complex tasks into parallel/sequential subtasks\n- Spawns specialized Claude subagents for each task type\n- Automatic test generation and multi-stage review\n- Handles large codebases through intelligent chunking\n\nSubagent Types:\n- Planning: Task decomposition and strategy\n- Code: Implementation and refactoring\n- Testing: Comprehensive test generation (unit/integration/E2E)\n- Linting: Code quality and formatting\n- Review: Multi-stage code review and quality scoring\n- Improve: Implement review suggestions\n- Context: Information retrieval\n- Publish: NPM/GitHub releases\n\nOptions:\n- --max-parallel N: Max concurrent subagents (default: 5)\n- --max-recursion N: Max recursion depth (default: 4)\n- --review-stages N: Number of review iterations (default: 3)\n- --quality-threshold N: Target quality score 0-1 (default: 0.85)\n- --test-mode [unit|integration|e2e|all]: Test generation mode (default: all)\n- --verbose: Show all recursive operations\n\nExamples:\n/rlm \"Refactor the authentication system with full test coverage\"\n/rlm \"Generate comprehensive tests for the API endpoints\" --test-mode integration\n/rlm \"Review and improve code quality\" --review-stages 5 --quality-threshold 0.95\n`;\n\n default:\n return `Unknown skill: ${skillName}`;\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Claude Skills for StackMemory\n * Custom skills that integrate with Claude Code to enhance workflow\n */\n\nimport {\n FrameHandoffManager,\n type HandoffMetadata,\n} from '../core/context/frame-handoff-manager.js';\nimport { DualStackManager } from '../core/context/dual-stack-manager.js';\nimport { SQLiteAdapter } from '../core/database/sqlite-adapter.js';\nimport { ContextRetriever } from '../core/retrieval/context-retriever.js';\nimport type { FrameManager } from '../core/context/frame-manager.js';\nimport { logger } from '../core/monitoring/logger.js';\nimport {\n RepoIngestionSkill,\n type RepoIngestionOptions,\n} from './repo-ingestion-skill.js';\nimport { DashboardLauncherSkill } from './dashboard-launcher.js';\nimport {\n RecursiveAgentOrchestrator,\n type RLMOptions,\n} from './recursive-agent-orchestrator.js';\nimport { getAPISkill, type APISkill } from './api-skill.js';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport type { Frame } from '../core/context/frame-manager.js';\n\n// Type definitions for Dig skill\ninterface Pattern {\n type: string;\n frequency: number;\n examples: string[];\n}\n\ninterface Decision {\n timestamp: string;\n decision: string;\n context: string;\n}\n\ninterface TimelineEntry {\n timestamp: string;\n event: string;\n description: string;\n}\n\nexport interface SkillContext {\n projectId: string;\n userId: string;\n dualStackManager: DualStackManager;\n handoffManager: FrameHandoffManager;\n contextRetriever: ContextRetriever;\n database: SQLiteAdapter;\n frameManager?: FrameManager;\n}\n\nexport interface SkillResult {\n success: boolean;\n message: string;\n data?: unknown;\n action?: string;\n}\n\n/**\n * Skill 1: Frame Handoff Orchestrator\n * Streamlines frame handoffs between team members\n */\nexport class HandoffSkill {\n constructor(private context: SkillContext) {}\n\n async execute(\n targetUser: string,\n message: string,\n options?: {\n frames?: string[];\n priority?: 'low' | 'medium' | 'high' | 'critical';\n autoDetect?: boolean;\n }\n ): Promise<SkillResult> {\n try {\n const activeStack = this.context.dualStackManager.getActiveStack();\n\n // Auto-detect frames if not specified\n let framesToHandoff = options?.frames || [];\n if (options?.autoDetect !== false && framesToHandoff.length === 0) {\n // Get recent frames that are completed or have errors\n const allFrames = await activeStack.getAllFrames();\n // Filter for completed frames OR frames with errors (not both conditions required)\n const relevantFrames = allFrames.filter(\n (f) =>\n f.state === 'completed' ||\n (f.outputs &&\n Array.isArray(f.outputs) &&\n f.outputs.some((o) => o.type === 'error'))\n );\n framesToHandoff = relevantFrames\n .slice(-5) // Last 5 relevant frames\n .map((f) => f.frameId);\n }\n\n if (framesToHandoff.length === 0) {\n return {\n success: false,\n message:\n 'No frames to handoff. Specify frames or complete some work first.',\n };\n }\n\n // Generate comprehensive handoff summary\n const frameDetails = await Promise.all(\n framesToHandoff.map((id) => activeStack.getFrame(id))\n );\n\n const summary = this.generateHandoffSummary(frameDetails, message);\n\n // Create handoff metadata\n const metadata: HandoffMetadata = {\n initiatedAt: new Date(),\n initiatorId: this.context.userId,\n targetUserId: targetUser,\n frameContext: {\n totalFrames: framesToHandoff.length,\n frameTypes: [\n ...new Set(frameDetails.map((f) => f?.type || 'unknown')),\n ],\n estimatedSize: JSON.stringify(frameDetails).length,\n dependencies: this.extractDependencies(frameDetails),\n },\n businessContext: {\n priority: options?.priority || 'medium',\n stakeholders: [targetUser],\n },\n };\n\n // Get target stack (shared or create new)\n const availableStacks =\n await this.context.dualStackManager.getAvailableStacks();\n let targetStackId = availableStacks.find(\n (s) => s.type === 'shared'\n )?.stackId;\n\n if (!targetStackId) {\n targetStackId = await this.context.dualStackManager.createSharedStack(\n 'team',\n `Handoff: ${message.slice(0, 50)}`,\n this.context.userId\n );\n }\n\n // Initiate handoff\n const handoffId = await this.context.handoffManager.initiateHandoff(\n targetStackId,\n framesToHandoff,\n metadata,\n targetUser,\n summary\n );\n\n // Create action items for recipient\n const actionItems = this.generateActionItems(frameDetails);\n\n return {\n success: true,\n message: `Handoff initiated to @${targetUser}`,\n data: {\n handoffId,\n frameCount: framesToHandoff.length,\n priority: options?.priority || 'medium',\n actionItems,\n targetStack: targetStackId,\n },\n action: `Notified ${targetUser}. Handoff ID: ${handoffId}`,\n };\n } catch (error: unknown) {\n logger.error('Handoff skill error:', error);\n return {\n success: false,\n message: `Failed to initiate handoff: ${error.message}`,\n };\n }\n }\n\n private generateHandoffSummary(frames: Frame[], message: string): string {\n const completed = frames.filter((f) => f?.state === 'completed').length;\n const blocked = frames.filter((f) =>\n f?.outputs?.some((o) => o.type === 'error')\n ).length;\n\n return `\n## Handoff Summary\n**Message**: ${message}\n**Frames**: ${frames.length} total (${completed} completed, ${blocked} blocked)\n\n### Work Completed:\n${frames\n .filter((f) => f?.state === 'completed')\n .map((f) => `- ${f.name}: ${f.digest_deterministic?.summary || 'No summary'}`)\n .join('\\n')}\n\n### Attention Required:\n${\n frames\n .filter((f) => f?.outputs?.some((o) => o.type === 'error'))\n .map(\n (f) =>\n `- ${f.name}: ${f.outputs.find((o) => o.type === 'error')?.content || 'Error'}`\n )\n .join('\\n') || 'None'\n}\n\n### Context:\n${frames\n .map((f) => f?.digest_ai?.context || '')\n .filter(Boolean)\n .join('\\n')}\n `.trim();\n }\n\n private extractDependencies(frames: Frame[]): string[] {\n const deps = new Set<string>();\n frames.forEach((frame) => {\n if (frame?.inputs?.dependencies) {\n if (Array.isArray(frame.inputs.dependencies)) {\n frame.inputs.dependencies.forEach((d) => deps.add(d));\n }\n }\n // Extract from outputs\n if (frame?.outputs) {\n frame.outputs.forEach((output) => {\n if (output.type === 'dependency') {\n deps.add(output.content);\n }\n });\n }\n });\n return Array.from(deps);\n }\n\n private generateActionItems(frames: Frame[]): string[] {\n const items: string[] = [];\n\n frames.forEach((frame) => {\n // Check for TODOs in outputs\n if (frame?.outputs) {\n frame.outputs.forEach((output) => {\n if (output.type === 'todo' || output.content?.includes('TODO')) {\n items.push(output.content);\n }\n });\n }\n\n // Check for errors that need resolution\n if (frame?.outputs?.some((o) => o.type === 'error')) {\n items.push(`Resolve error in ${frame.name}`);\n }\n\n // Check for pending tests - look in multiple places\n if (\n frame?.inputs?.tests === 'pending' ||\n frame?.type === 'implementation' ||\n (frame?.name && frame.name.toLowerCase().includes('implementation'))\n ) {\n items.push(`Write tests for ${frame.name}`);\n }\n });\n\n return items;\n }\n}\n\n/**\n * Skill 7: Recovery Checkpoint Manager\n * Create and manage recovery points\n */\nexport class CheckpointSkill {\n private checkpointDir: string;\n\n constructor(private context: SkillContext) {\n this.checkpointDir = path.join(\n os.homedir(),\n '.stackmemory',\n 'checkpoints',\n context.projectId\n );\n fs.mkdirSync(this.checkpointDir, { recursive: true });\n }\n\n async create(\n description: string,\n options?: {\n autoDetectRisky?: boolean;\n includeFiles?: string[];\n metadata?: Record<string, unknown>;\n }\n ): Promise<SkillResult> {\n try {\n const timestamp = Date.now();\n const checkpointId = `checkpoint-${timestamp}-${Math.random().toString(36).slice(2, 8)}`;\n\n // Get current context\n const activeStack = this.context.dualStackManager.getActiveStack();\n const currentContext = this.context.dualStackManager.getCurrentContext();\n const allFrames = await activeStack.getAllFrames();\n\n // Create checkpoint data\n const checkpoint = {\n id: checkpointId,\n timestamp,\n description,\n context: {\n stackId: currentContext.stackId,\n stackType: currentContext.type,\n userId: this.context.userId,\n projectId: this.context.projectId,\n },\n frames: allFrames,\n metadata: {\n ...options?.metadata,\n frameCount: allFrames.length,\n activeFrames: allFrames.filter((f) => f.state === 'active').length,\n completedFrames: allFrames.filter((f) => f.state === 'completed')\n .length,\n },\n files: options?.includeFiles || [],\n };\n\n // Save checkpoint\n const checkpointPath = path.join(\n this.checkpointDir,\n `${checkpointId}.json`\n );\n fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2));\n\n // Save file backups if specified\n if (options?.includeFiles && options.includeFiles.length > 0) {\n const filesDir = path.join(this.checkpointDir, checkpointId, 'files');\n fs.mkdirSync(filesDir, { recursive: true });\n\n for (const file of options.includeFiles) {\n if (fs.existsSync(file)) {\n const basename = path.basename(file);\n const backupPath = path.join(filesDir, basename);\n fs.copyFileSync(file, backupPath);\n }\n }\n }\n\n // Auto-detect risky operations\n if (options?.autoDetectRisky) {\n const riskyPatterns = [\n 'migration',\n 'database',\n 'deploy',\n 'production',\n 'delete',\n 'remove',\n 'drop',\n 'migrate', // Add more specific pattern\n ];\n\n const isRisky = allFrames.some((frame) => {\n const nameMatches =\n frame.name &&\n riskyPatterns.some((pattern) =>\n frame.name.toLowerCase().includes(pattern)\n );\n const commandMatches =\n frame.inputs?.command &&\n riskyPatterns.some((pattern) =>\n frame.inputs.command.toLowerCase().includes(pattern)\n );\n return nameMatches || commandMatches;\n });\n\n if (isRisky) {\n checkpoint.metadata.riskyOperation = true;\n checkpoint.metadata.autoCheckpoint = true;\n }\n }\n\n // Update the checkpoint data after risky operation detection\n fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2));\n\n logger.info(`Created checkpoint: ${checkpointId}`);\n\n return {\n success: true,\n message: `Checkpoint created: ${description}`,\n data: {\n checkpointId,\n timestamp: new Date(timestamp).toISOString(),\n frameCount: checkpoint.metadata.frameCount,\n location: checkpointPath,\n },\n action: `Saved checkpoint ${checkpointId}`,\n };\n } catch (error: unknown) {\n logger.error('Checkpoint creation error:', error);\n return {\n success: false,\n message: `Failed to create checkpoint: ${error.message}`,\n };\n }\n }\n\n async restore(checkpointId: string): Promise<SkillResult> {\n try {\n const checkpointPath = path.join(\n this.checkpointDir,\n `${checkpointId}.json`\n );\n\n if (!fs.existsSync(checkpointPath)) {\n // Try to find by partial ID\n const files = fs.readdirSync(this.checkpointDir);\n const match = files.find((f) => f.includes(checkpointId));\n if (match) {\n checkpointId = match.replace('.json', '');\n } else {\n return {\n success: false,\n message: `Checkpoint not found: ${checkpointId}`,\n };\n }\n }\n\n const checkpoint = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n\n // Switch to checkpoint's stack\n await this.context.dualStackManager.switchToStack(\n checkpoint.context.stackId\n );\n\n // Restore frames (this is a simplified version - real implementation would be more complex)\n // const activeStack = this.context.dualStackManager.getActiveStack();\n\n // Clear current frames and restore from checkpoint\n // Note: This is a conceptual implementation - actual frame restoration\n // would need more sophisticated state management\n\n // Restore files if they exist\n const filesDir = path.join(this.checkpointDir, checkpointId, 'files');\n if (fs.existsSync(filesDir)) {\n const files = fs.readdirSync(filesDir);\n for (const file of files) {\n const backupPath = path.join(filesDir, file);\n const originalPath = checkpoint.files.find(\n (f) => path.basename(f) === file\n );\n if (originalPath && fs.existsSync(backupPath)) {\n fs.copyFileSync(backupPath, originalPath);\n }\n }\n }\n\n logger.info(`Restored checkpoint: ${checkpointId}`);\n\n return {\n success: true,\n message: `Restored to checkpoint: ${checkpoint.description}`,\n data: {\n checkpointId,\n timestamp: new Date(checkpoint.timestamp).toISOString(),\n frameCount: checkpoint.metadata.frameCount,\n filesRestored: checkpoint.files.length,\n },\n action: `Restored checkpoint from ${new Date(checkpoint.timestamp).toLocaleString()}`,\n };\n } catch (error: unknown) {\n logger.error('Checkpoint restoration error:', error);\n return {\n success: false,\n message: `Failed to restore checkpoint: ${error.message}`,\n };\n }\n }\n\n async list(options?: { limit?: number; since?: Date }): Promise<SkillResult> {\n try {\n const files = fs\n .readdirSync(this.checkpointDir)\n .filter((f) => f.endsWith('.json'))\n .map((f) => {\n const checkpointPath = path.join(this.checkpointDir, f);\n const checkpoint = JSON.parse(\n fs.readFileSync(checkpointPath, 'utf-8')\n );\n return checkpoint;\n })\n .filter((c) => !options?.since || c.timestamp > options.since.getTime())\n .sort((a, b) => b.timestamp - a.timestamp)\n .slice(0, options?.limit || 10);\n\n return {\n success: true,\n message: `Found ${files.length} checkpoints`,\n data: files.map((c) => ({\n id: c.id,\n description: c.description,\n timestamp: new Date(c.timestamp).toISOString(),\n frameCount: c.metadata.frameCount,\n risky: c.metadata.riskyOperation || false,\n })),\n };\n } catch (error: unknown) {\n logger.error('Checkpoint list error:', error);\n return {\n success: false,\n message: `Failed to list checkpoints: ${error.message}`,\n };\n }\n }\n\n async diff(checkpoint1: string, checkpoint2: string): Promise<SkillResult> {\n try {\n const cp1 = await this.loadCheckpoint(checkpoint1);\n const cp2 = await this.loadCheckpoint(checkpoint2);\n\n if (!cp1 || !cp2) {\n return {\n success: false,\n message: 'One or both checkpoints not found',\n };\n }\n\n const diff = {\n timeDiff: Math.abs(cp2.timestamp - cp1.timestamp),\n framesDiff: cp2.frames.length - cp1.frames.length,\n newFrames: cp2.frames.filter(\n (f2) => !cp1.frames.some((f1) => f1.frameId === f2.frameId)\n ),\n removedFrames: cp1.frames.filter(\n (f1) => !cp2.frames.some((f2) => f2.frameId === f1.frameId)\n ),\n modifiedFrames: cp2.frames.filter((f2) => {\n const f1 = cp1.frames.find((f) => f.frameId === f2.frameId);\n return f1 && JSON.stringify(f1) !== JSON.stringify(f2);\n }),\n };\n\n return {\n success: true,\n message: `Diff between ${cp1.description} and ${cp2.description}`,\n data: {\n timeDiff: `${Math.round(diff.timeDiff / 1000 / 60)} minutes`,\n framesDiff:\n diff.framesDiff > 0 ? `+${diff.framesDiff}` : `${diff.framesDiff}`,\n newFrames: diff.newFrames.length,\n removedFrames: diff.removedFrames.length,\n modifiedFrames: diff.modifiedFrames.length,\n details: diff,\n },\n };\n } catch (error: unknown) {\n logger.error('Checkpoint diff error:', error);\n return {\n success: false,\n message: `Failed to diff checkpoints: ${error.message}`,\n };\n }\n }\n\n private async loadCheckpoint(checkpointId: string): Promise<unknown> {\n const checkpointPath = path.join(\n this.checkpointDir,\n `${checkpointId}.json`\n );\n if (fs.existsSync(checkpointPath)) {\n return JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));\n }\n\n // Try partial match\n const files = fs.readdirSync(this.checkpointDir);\n const match = files.find((f) => f.includes(checkpointId));\n if (match) {\n const path = path.join(this.checkpointDir, match);\n return JSON.parse(fs.readFileSync(path, 'utf-8'));\n }\n\n return null;\n }\n}\n\n/**\n * Skill 2: Context Archaeologist\n * Deep historical context retrieval across sessions\n */\nexport class ArchaeologistSkill {\n constructor(private context: SkillContext) {}\n\n async dig(\n query: string,\n options?: {\n depth?: string; // e.g., \"6months\", \"30days\", \"all\"\n patterns?: boolean;\n decisions?: boolean;\n timeline?: boolean;\n }\n ): Promise<SkillResult> {\n try {\n // Parse depth\n const depth = this.parseDepth(options?.depth || '30days');\n const since = new Date(Date.now() - depth);\n\n // Use context retriever for semantic search\n const results = await this.context.contextRetriever.retrieve({\n query,\n projectId: this.context.projectId,\n limit: 50,\n minScore: 0.3,\n });\n\n // Filter by date if specified\n const filtered = results.filter(\n (r) => !depth || new Date(r.timestamp) > since\n );\n\n // Extract patterns if requested\n let patterns: Pattern[] = [];\n if (options?.patterns) {\n patterns = this.extractPatterns(filtered);\n }\n\n // Extract decisions if requested\n let decisions: Decision[] = [];\n if (options?.decisions) {\n decisions = this.extractDecisions(filtered);\n }\n\n // Generate timeline if requested\n let timeline: TimelineEntry[] = [];\n if (options?.timeline) {\n timeline = this.generateTimeline(filtered);\n }\n\n // Find most relevant context\n const topResults = filtered.slice(0, 10);\n const summary = this.generateArchaeologySummary(\n topResults,\n patterns,\n decisions,\n timeline\n );\n\n return {\n success: true,\n message: `Found ${filtered.length} relevant results`,\n data: {\n totalResults: filtered.length,\n timeRange: {\n from: since.toISOString(),\n to: new Date().toISOString(),\n },\n topResults: topResults.map((r) => ({\n frameId: r.frameId,\n score: r.score,\n timestamp: r.timestamp,\n summary: r.content.slice(0, 100) + '...',\n })),\n patterns,\n decisions,\n timeline,\n summary,\n },\n action: `Analyzed ${filtered.length} frames from ${options?.depth || '30days'} of history`,\n };\n } catch (error: unknown) {\n logger.error('Archaeology skill error:', error);\n return {\n success: false,\n message: `Failed to dig through context: ${error.message}`,\n };\n }\n }\n\n private parseDepth(depth: string): number {\n const match = depth.match(/^(\\d+)(days?|weeks?|months?|years?|all)$/i);\n if (!match) {\n return 30 * 24 * 60 * 60 * 1000; // Default 30 days\n }\n\n const [, num, unit] = match;\n const value = parseInt(num);\n\n switch (unit.toLowerCase()) {\n case 'day':\n case 'days':\n return value * 24 * 60 * 60 * 1000;\n case 'week':\n case 'weeks':\n return value * 7 * 24 * 60 * 60 * 1000;\n case 'month':\n case 'months':\n return value * 30 * 24 * 60 * 60 * 1000;\n case 'year':\n case 'years':\n return value * 365 * 24 * 60 * 60 * 1000;\n case 'all':\n return Number.MAX_SAFE_INTEGER;\n default:\n return 30 * 24 * 60 * 60 * 1000;\n }\n }\n\n private extractPatterns(results: Frame[]): Pattern[] {\n const patterns: Map<string, number> = new Map();\n\n // Common patterns to look for\n const patternTypes = [\n { regex: /test.*then.*implement/i, name: 'TDD' },\n { regex: /refactor/i, name: 'Refactoring' },\n { regex: /debug|fix|error|bug/i, name: 'Debugging' },\n { regex: /implement.*feature/i, name: 'Feature Development' },\n { regex: /review|code review/i, name: 'Code Review' },\n { regex: /deploy|release/i, name: 'Deployment' },\n { regex: /optimize|performance/i, name: 'Optimization' },\n ];\n\n results.forEach((result) => {\n patternTypes.forEach((pattern) => {\n if (pattern.regex.test(result.content)) {\n patterns.set(pattern.name, (patterns.get(pattern.name) || 0) + 1);\n }\n });\n });\n\n return Array.from(patterns.entries())\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n }\n\n private extractDecisions(results: Frame[]): Decision[] {\n const decisions: Decision[] = [];\n\n // Keywords that indicate decisions\n const decisionKeywords = [\n 'decided',\n 'chose',\n 'selected',\n 'will use',\n 'going with',\n 'approach',\n 'strategy',\n 'solution',\n ];\n\n results.forEach((result) => {\n const content = result.content.toLowerCase();\n if (decisionKeywords.some((keyword) => content.includes(keyword))) {\n // Extract sentence containing the decision\n const sentences = result.content.split(/[.!?]+/);\n const decisionSentence = sentences.find((s) =>\n decisionKeywords.some((k) => s.toLowerCase().includes(k))\n );\n\n if (decisionSentence) {\n decisions.push({\n frameId: result.frameId,\n timestamp: result.timestamp,\n decision: decisionSentence.trim(),\n context: result.content.slice(0, 200),\n });\n }\n }\n });\n\n return decisions.slice(0, 10); // Top 10 decisions\n }\n\n private generateTimeline(results: Frame[]): TimelineEntry[] {\n // Group by day\n const timeline: Map<string, Frame[]> = new Map();\n\n results.forEach((result) => {\n const date = new Date(result.timestamp).toDateString();\n if (!timeline.has(date)) {\n timeline.set(date, []);\n }\n const dateItems = timeline.get(date);\n if (dateItems) {\n dateItems.push(result);\n }\n });\n\n return Array.from(timeline.entries())\n .map(([date, items]) => ({\n date,\n itemCount: items.length,\n highlights: items.slice(0, 3).map((item) => ({\n frameId: item.frameId,\n summary: item.content.slice(0, 50) + '...',\n })),\n }))\n .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());\n }\n\n private generateArchaeologySummary(\n results: Frame[],\n patterns: Pattern[],\n decisions: Decision[],\n timeline: TimelineEntry[]\n ): string {\n let summary = '## Context Archaeology Report\\n\\n';\n\n if (results.length > 0) {\n summary += `### Most Relevant Context (${results.length} results)\\n`;\n results.slice(0, 3).forEach((r) => {\n summary += `- **${new Date(r.timestamp).toLocaleDateString()}**: ${r.content.slice(0, 100)}...\\n`;\n });\n summary += '\\n';\n }\n\n if (patterns.length > 0) {\n summary += `### Detected Patterns\\n`;\n patterns.slice(0, 5).forEach((p) => {\n summary += `- ${p.name}: ${p.count} occurrences\\n`;\n });\n summary += '\\n';\n }\n\n if (decisions.length > 0) {\n summary += `### Key Decisions\\n`;\n decisions.slice(0, 5).forEach((d) => {\n summary += `- **${new Date(d.timestamp).toLocaleDateString()}**: ${d.decision}\\n`;\n });\n summary += '\\n';\n }\n\n if (timeline.length > 0) {\n summary += `### Activity Timeline\\n`;\n timeline.slice(0, 5).forEach((t) => {\n summary += `- **${t.date}**: ${t.itemCount} activities\\n`;\n });\n }\n\n return summary;\n }\n}\n\n/**\n * Main Claude Skills Manager\n */\nexport class ClaudeSkillsManager {\n private handoffSkill: HandoffSkill;\n private checkpointSkill: CheckpointSkill;\n private archaeologistSkill: ArchaeologistSkill;\n private dashboardLauncher: DashboardLauncherSkill;\n private repoIngestionSkill: RepoIngestionSkill | null = null;\n private rlmOrchestrator: RecursiveAgentOrchestrator | null = null;\n private apiSkill: APISkill;\n\n constructor(private context: SkillContext) {\n this.handoffSkill = new HandoffSkill(context);\n this.checkpointSkill = new CheckpointSkill(context);\n this.archaeologistSkill = new ArchaeologistSkill(context);\n this.apiSkill = getAPISkill();\n\n // Initialize dashboard launcher (lazy import to avoid circular deps)\n import('./dashboard-launcher.js').then((module) => {\n this.dashboardLauncher = new module.DashboardLauncherSkill();\n // Don't auto-launch dashboard to avoid startup errors\n // User can manually launch with 'stackmemory skills dashboard launch'\n logger.info('Dashboard launcher initialized (manual launch required)');\n });\n\n // Initialize repo ingestion skill if ChromaDB is configured\n const chromaConfig = {\n apiKey: process.env['CHROMADB_API_KEY'] || '',\n tenant: process.env['CHROMADB_TENANT'] || '',\n database: process.env['CHROMADB_DATABASE'] || 'stackmemory',\n collectionName: process.env['CHROMADB_COLLECTION'] || 'stackmemory_repos',\n };\n\n if (chromaConfig.apiKey && chromaConfig.tenant) {\n this.repoIngestionSkill = new RepoIngestionSkill(\n chromaConfig,\n context.userId,\n process.env['CHROMADB_TEAM_ID']\n );\n this.repoIngestionSkill.initialize().catch((error: unknown) => {\n logger.warn('Repo ingestion skill initialization failed:', error);\n });\n }\n\n // Initialize RLM Orchestrator\n // Import dynamically to avoid circular dependencies\n import('../features/tasks/linear-task-manager.js')\n .then((module) => {\n const taskStore = new module.LinearTaskManager();\n\n // Use frameManager from context if available\n const frameManager = context.frameManager;\n if (!frameManager) {\n throw new Error(\n 'FrameManager not provided in context - required for RLM orchestrator'\n );\n }\n\n this.rlmOrchestrator = new RecursiveAgentOrchestrator(\n frameManager,\n context.dualStackManager,\n context.contextRetriever,\n taskStore\n );\n\n logger.info('RLM Orchestrator initialized');\n })\n .catch((error: unknown) => {\n logger.warn('RLM Orchestrator initialization failed:', error);\n });\n }\n\n async executeSkill(\n skillName: string,\n args: string[],\n options?: Record<string, unknown>\n ): Promise<SkillResult> {\n switch (skillName) {\n case 'handoff':\n return this.handoffSkill.execute(args[0], args[1], options);\n\n case 'checkpoint':\n const subcommand = args[0];\n switch (subcommand) {\n case 'create':\n return this.checkpointSkill.create(args[1], options);\n case 'restore':\n return this.checkpointSkill.restore(args[1]);\n case 'list':\n return this.checkpointSkill.list(options);\n case 'diff':\n return this.checkpointSkill.diff(args[1], args[2]);\n default:\n return {\n success: false,\n message: `Unknown checkpoint subcommand: ${subcommand}`,\n };\n }\n\n case 'dig':\n return this.archaeologistSkill.dig(args[0], options);\n\n case 'lint':\n // Linting task using RLM orchestrator with linting agent\n if (!this.rlmOrchestrator) {\n return {\n success: false,\n message:\n 'RLM Orchestrator not initialized. Please wait a moment and try again.',\n };\n }\n\n const lintPath = args[0] || process.cwd();\n const lintOptions = {\n ...options,\n // Force use of linting agent\n agents: ['linting'],\n maxParallel: 1,\n reviewStages: 1,\n verboseLogging: true,\n } as RLMOptions;\n\n const lintTask = `Perform comprehensive linting on ${lintPath}: Check for syntax errors, type issues, formatting violations, security vulnerabilities, performance anti-patterns, and unused code. Provide actionable fixes.`;\n\n try {\n const result = await this.rlmOrchestrator.execute(\n lintTask,\n { path: lintPath, ...options },\n lintOptions\n );\n\n return {\n success: result.success,\n message: `Linting ${result.success ? 'completed' : 'failed'}`,\n data: {\n issuesFound: result.issuesFound,\n issuesFixed: result.issuesFixed,\n duration: `${result.duration}ms`,\n totalTokens: result.totalTokens,\n details: result.rootNode,\n },\n };\n } catch (error) {\n return {\n success: false,\n message: `Linting failed: ${error.message}`,\n };\n }\n\n case 'rlm':\n if (!this.rlmOrchestrator) {\n return {\n success: false,\n message:\n 'RLM Orchestrator not initialized. Please wait a moment and try again.',\n };\n }\n return this.rlmOrchestrator.execute(args[0], options as RLMOptions);\n\n case 'repo':\n case 'ingest':\n if (!this.repoIngestionSkill) {\n return {\n success: false,\n message:\n 'Repo ingestion skill not initialized. Please configure ChromaDB.',\n };\n }\n\n const repoCommand = args[0];\n switch (repoCommand) {\n case 'ingest':\n const repoPath = args[1] || process.cwd();\n const repoName = args[2] || path.basename(repoPath);\n return await this.repoIngestionSkill.ingestRepository(\n repoPath,\n repoName,\n options as RepoIngestionOptions\n );\n\n case 'update':\n const updatePath = args[1] || process.cwd();\n const updateName = args[2] || path.basename(updatePath);\n return await this.repoIngestionSkill.updateRepository(\n updatePath,\n updateName,\n options as RepoIngestionOptions\n );\n\n case 'search':\n const query = args[1];\n if (!query) {\n return {\n success: false,\n message: 'Search query required',\n };\n }\n const results = await this.repoIngestionSkill.searchCode(query, {\n repoName: options?.repoName as string,\n language: options?.language as string,\n limit: options?.limit as number,\n includeContext: options?.includeContext as boolean,\n });\n return {\n success: true,\n message: `Found ${results.length} results`,\n data: results,\n };\n\n case 'stats':\n const stats = await this.repoIngestionSkill.getRepoStats(args[1]);\n return {\n success: true,\n message: 'Repository statistics',\n data: stats,\n };\n\n default:\n return {\n success: false,\n message: `Unknown repo command: ${repoCommand}. Use: ingest, update, search, or stats`,\n };\n }\n\n case 'dashboard':\n const dashboardCmd = args[0];\n if (!this.dashboardLauncher) {\n return {\n success: false,\n message: 'Dashboard launcher not yet initialized',\n };\n }\n switch (dashboardCmd) {\n case 'launch':\n await this.dashboardLauncher.launch();\n return {\n success: true,\n message: 'Dashboard launched',\n action: 'open-browser',\n };\n case 'stop':\n await this.dashboardLauncher.stop();\n return {\n success: true,\n message: 'Dashboard stopped',\n };\n default:\n await this.dashboardLauncher.launch();\n return {\n success: true,\n message: 'Dashboard launched',\n action: 'open-browser',\n };\n }\n\n case 'recursive':\n if (!this.rlmOrchestrator) {\n return {\n success: false,\n message:\n 'RLM Orchestrator not initialized. Please wait a moment and try again.',\n };\n }\n\n const task = args.join(' ') || 'Analyze and improve the current code';\n const rlmOptions = options as RLMOptions;\n\n try {\n logger.info('Starting RLM execution', { task });\n\n const result = await this.rlmOrchestrator.execute(\n task,\n {\n files: rlmOptions.files || [],\n query: task,\n },\n rlmOptions\n );\n\n return {\n success: result.success,\n message: `RLM execution ${result.success ? 'completed' : 'failed'}`,\n data: {\n duration: `${result.duration}ms`,\n totalTokens: result.totalTokens,\n totalCost: `$${result.totalCost.toFixed(2)}`,\n testsGenerated: result.testsGenerated,\n improvements: result.improvements.length,\n issuesFound: result.issuesFound,\n issuesFixed: result.issuesFixed,\n executionTree: result.rootNode,\n },\n };\n } catch (error) {\n logger.error('RLM execution error:', error);\n return {\n success: false,\n message: `RLM execution failed: ${error.message}`,\n };\n }\n\n case 'api':\n const apiCmd = args[0];\n switch (apiCmd) {\n case 'add':\n return this.apiSkill.add(args[1], args[2], {\n spec: options?.spec as string,\n authType: options?.authType as\n | 'none'\n | 'api-key'\n | 'oauth2'\n | 'basic',\n headerName: options?.headerName as string,\n envVar: options?.envVar as string,\n });\n case 'list':\n return this.apiSkill.list();\n case 'describe':\n return this.apiSkill.describe(args[1], args[2]);\n case 'exec':\n const execParams: Record<string, unknown> = {};\n // Parse remaining args as params\n for (let i = 3; i < args.length; i += 2) {\n if (args[i] && args[i + 1]) {\n execParams[args[i].replace('--', '')] = args[i + 1];\n }\n }\n return this.apiSkill.exec(args[1], args[2], execParams, {\n raw: options?.raw as boolean,\n filter: options?.filter as string,\n });\n case 'auth':\n return this.apiSkill.auth(args[1], {\n token: options?.token as string,\n envVar: options?.envVar as string,\n oauth: options?.oauth as boolean,\n scopes: (options?.scopes as string)?.split(','),\n });\n case 'sync':\n return this.apiSkill.sync(args[1]);\n case 'remove':\n return this.apiSkill.remove(args[1]);\n case 'help':\n default:\n return {\n success: true,\n message: this.apiSkill.getHelp(),\n };\n }\n\n default:\n return {\n success: false,\n message: `Unknown skill: ${skillName}`,\n };\n }\n }\n\n getAvailableSkills(): string[] {\n const skills = ['handoff', 'checkpoint', 'dig', 'dashboard', 'api'];\n if (this.repoIngestionSkill) {\n skills.push('repo');\n }\n if (this.rlmOrchestrator) {\n skills.push('rlm', 'lint');\n }\n return skills;\n }\n\n getSkillHelp(skillName: string): string {\n switch (skillName) {\n case 'handoff':\n return `\n/handoff @user \"message\" [--priority high] [--frames frame1,frame2]\nStreamline frame handoffs between team members\n`;\n\n case 'checkpoint':\n return `\n/checkpoint create \"description\" [--files file1,file2] [--auto-detect-risky]\n/checkpoint restore <id>\n/checkpoint list [--limit 10] [--since \"2024-01-01\"]\n/checkpoint diff <id1> <id2>\nCreate and manage recovery points\n`;\n\n case 'dig':\n return `\n/dig \"query\" [--depth 6months] [--patterns] [--decisions] [--timeline]\nDeep historical context retrieval across sessions\n`;\n\n case 'lint':\n return `\n/lint [path] [options]\nPerform comprehensive code linting and quality checks\n\nAutomatically checks for:\n- Syntax errors and type issues\n- Code formatting and style violations \n- Security vulnerabilities\n- Performance anti-patterns\n- Unused imports and dead code\n- Code smells and complexity issues\n\nUsage:\n stackmemory skills lint # Lint current directory\n stackmemory skills lint src/ # Lint specific directory\n stackmemory skills lint src/file.ts # Lint specific file\n\nOptions:\n --fix Automatically fix issues where possible\n --format Focus on formatting issues\n --security Focus on security vulnerabilities\n --performance Focus on performance issues\n --verbose Show detailed output\n\nExamples:\n stackmemory skills lint --fix\n stackmemory skills lint src/ --security --verbose\n`;\n\n case 'rlm':\n return `\n/rlm \"task description\" [options]\nExecute complex tasks with recursive agent orchestration\n\nOptions:\n --max-parallel <n> Max concurrent subagents (default: 5)\n --max-recursion <n> Max recursion depth (default: 4)\n --max-tokens-per-agent <n> Token budget per agent (default: 30000)\n --review-stages <n> Review iterations (default: 3)\n --quality-threshold <n> Target quality 0-1 (default: 0.85)\n --test-mode <mode> unit/integration/e2e/all (default: all)\n --verbose Show all operations\n --timeout-per-agent <s> Timeout in seconds (default: 300)\n\nExamples:\n stackmemory skills rlm \"Generate tests for API endpoints\"\n stackmemory skills rlm \"Refactor auth system\" --quality-threshold 0.95\n`;\n\n case 'dashboard':\n return `\n/dashboard [launch|stop]\nLaunch the StackMemory web dashboard for real-time monitoring\n- launch: Start the web dashboard and open in browser (default)\n- stop: Stop the dashboard server\nAuto-launches on new sessions when configured\n`;\n\n case 'repo':\n return `\n/repo ingest [path] [name] [--incremental] [--include-tests] [--include-docs]\n/repo update [path] [name] [--force-update]\n/repo search \"query\" [--repo-name name] [--language lang] [--limit n]\n/repo stats [repo-name]\n\nIngest and search code repositories in ChromaDB:\n- ingest: Index a new repository (defaults to current directory)\n- update: Update an existing repository with changes\n- search: Semantic search across ingested code\n- stats: View statistics about ingested repositories\n\nOptions:\n- --incremental: Only process changed files\n- --include-tests: Include test files in indexing\n- --include-docs: Include documentation files\n- --force-update: Force re-indexing of all files\n- --language: Filter search by programming language\n- --limit: Maximum search results (default: 20)\n`;\n\n case 'recursive':\n return `\n/rlm \"task description\" [options]\n\nRecursive Language Model orchestration using Claude Code's Task tool:\n- Decomposes complex tasks into parallel/sequential subtasks\n- Spawns specialized Claude subagents for each task type\n- Automatic test generation and multi-stage review\n- Handles large codebases through intelligent chunking\n\nSubagent Types:\n- Planning: Task decomposition and strategy\n- Code: Implementation and refactoring\n- Testing: Comprehensive test generation (unit/integration/E2E)\n- Linting: Code quality and formatting\n- Review: Multi-stage code review and quality scoring\n- Improve: Implement review suggestions\n- Context: Information retrieval\n- Publish: NPM/GitHub releases\n\nOptions:\n- --max-parallel N: Max concurrent subagents (default: 5)\n- --max-recursion N: Max recursion depth (default: 4)\n- --review-stages N: Number of review iterations (default: 3)\n- --quality-threshold N: Target quality score 0-1 (default: 0.85)\n- --test-mode [unit|integration|e2e|all]: Test generation mode (default: all)\n- --verbose: Show all recursive operations\n\nExamples:\n/rlm \"Refactor the authentication system with full test coverage\"\n/rlm \"Generate comprehensive tests for the API endpoints\" --test-mode integration\n/rlm \"Review and improve code quality\" --review-stages 5 --quality-threshold 0.95\n`;\n\n case 'api':\n return this.apiSkill.getHelp();\n\n default:\n return `Unknown skill: ${skillName}`;\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path"]
7
7
  }
@@ -0,0 +1,132 @@
1
+ import { execSync } from "child_process";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import * as os from "os";
5
+ import { logger } from "../core/monitoring/logger.js";
6
+ const STACKMEMORY_PROCESS_PATTERNS = [
7
+ "stackmemory",
8
+ "ralph orchestrate",
9
+ "ralph swarm",
10
+ "ralph loop",
11
+ "hooks start"
12
+ ];
13
+ function getStackmemoryProcesses() {
14
+ const processes = [];
15
+ try {
16
+ const psOutput = execSync(
17
+ "ps -eo pid,lstart,command 2>/dev/null || ps -eo pid,start,args 2>/dev/null",
18
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
19
+ );
20
+ const lines = psOutput.trim().split("\n").slice(1);
21
+ for (const line of lines) {
22
+ const isStackmemory = STACKMEMORY_PROCESS_PATTERNS.some(
23
+ (pattern) => line.toLowerCase().includes(pattern.toLowerCase())
24
+ );
25
+ if (!isStackmemory) continue;
26
+ const match = line.match(
27
+ /^\s*(\d+)\s+(\w+\s+\w+\s+\d+\s+[\d:]+\s+\d+)\s+(.+)$/
28
+ );
29
+ if (match) {
30
+ const pid = parseInt(match[1], 10);
31
+ const startTimeStr = match[2];
32
+ const command = match[3];
33
+ if (pid === process.pid) continue;
34
+ const startTime = new Date(startTimeStr);
35
+ const ageMs = Date.now() - startTime.getTime();
36
+ const ageHours = ageMs / (1e3 * 60 * 60);
37
+ processes.push({
38
+ pid,
39
+ command: command.slice(0, 100),
40
+ // Truncate long commands
41
+ startTime,
42
+ ageHours
43
+ });
44
+ }
45
+ }
46
+ } catch (error) {
47
+ logger.warn("Failed to get process list:", error);
48
+ }
49
+ return processes;
50
+ }
51
+ function hasRecentLogActivity(proc, maxAgeHours) {
52
+ const logDir = path.join(os.homedir(), ".stackmemory", "logs");
53
+ if (!fs.existsSync(logDir)) return false;
54
+ try {
55
+ const logFiles = fs.readdirSync(logDir).filter((f) => f.endsWith(".log"));
56
+ for (const logFile of logFiles) {
57
+ const logPath = path.join(logDir, logFile);
58
+ const stats = fs.statSync(logPath);
59
+ const logAgeHours = (Date.now() - stats.mtimeMs) / (1e3 * 60 * 60);
60
+ if (logAgeHours < maxAgeHours) {
61
+ try {
62
+ const content = fs.readFileSync(logPath, "utf-8").slice(-1e4);
63
+ if (content.includes(`pid:${proc.pid}`) || content.includes(`PID ${proc.pid}`)) {
64
+ proc.logFile = logPath;
65
+ proc.lastLogActivity = stats.mtime;
66
+ return true;
67
+ }
68
+ } catch {
69
+ }
70
+ }
71
+ }
72
+ } catch (error) {
73
+ logger.warn("Failed to check log activity:", error);
74
+ }
75
+ return false;
76
+ }
77
+ function findStaleProcesses(maxAgeHours = 24) {
78
+ const allProcesses = getStackmemoryProcesses();
79
+ return allProcesses.filter((proc) => {
80
+ if (proc.ageHours < maxAgeHours) return false;
81
+ if (hasRecentLogActivity(proc, maxAgeHours)) return false;
82
+ return true;
83
+ });
84
+ }
85
+ function killStaleProcesses(processes, dryRun = false) {
86
+ const result = {
87
+ found: processes,
88
+ killed: [],
89
+ errors: []
90
+ };
91
+ for (const proc of processes) {
92
+ if (dryRun) {
93
+ logger.info(`[DRY RUN] Would kill PID ${proc.pid}: ${proc.command}`);
94
+ continue;
95
+ }
96
+ try {
97
+ process.kill(proc.pid, "SIGTERM");
98
+ result.killed.push(proc.pid);
99
+ logger.info(`Killed stale process ${proc.pid}: ${proc.command}`);
100
+ } catch (error) {
101
+ const err = error;
102
+ if (err.code === "ESRCH") {
103
+ result.killed.push(proc.pid);
104
+ } else {
105
+ result.errors.push({
106
+ pid: proc.pid,
107
+ error: err.message || "Unknown error"
108
+ });
109
+ logger.warn(`Failed to kill PID ${proc.pid}:`, err.message);
110
+ }
111
+ }
112
+ }
113
+ return result;
114
+ }
115
+ function cleanupStaleProcesses(options = {}) {
116
+ const { maxAgeHours = 24, dryRun = false } = options;
117
+ logger.info(`Looking for stale processes older than ${maxAgeHours}h...`);
118
+ const staleProcesses = findStaleProcesses(maxAgeHours);
119
+ if (staleProcesses.length === 0) {
120
+ logger.info("No stale processes found");
121
+ return { found: [], killed: [], errors: [] };
122
+ }
123
+ logger.info(`Found ${staleProcesses.length} stale process(es)`);
124
+ return killStaleProcesses(staleProcesses, dryRun);
125
+ }
126
+ export {
127
+ cleanupStaleProcesses,
128
+ findStaleProcesses,
129
+ getStackmemoryProcesses,
130
+ killStaleProcesses
131
+ };
132
+ //# sourceMappingURL=process-cleanup.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/process-cleanup.ts"],
4
+ "sourcesContent": ["/**\n * Process Cleanup Utility\n * Automatically cleans up stale stackmemory processes older than 24h\n * with no recent log activity.\n */\n\nimport { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { logger } from '../core/monitoring/logger.js';\n\nexport interface StaleProcess {\n pid: number;\n command: string;\n startTime: Date;\n ageHours: number;\n logFile?: string;\n lastLogActivity?: Date;\n}\n\nexport interface CleanupResult {\n found: StaleProcess[];\n killed: number[];\n errors: Array<{ pid: number; error: string }>;\n}\n\nconst STACKMEMORY_PROCESS_PATTERNS = [\n 'stackmemory',\n 'ralph orchestrate',\n 'ralph swarm',\n 'ralph loop',\n 'hooks start',\n];\n\n/**\n * Get all running stackmemory-related processes\n */\nexport function getStackmemoryProcesses(): StaleProcess[] {\n const processes: StaleProcess[] = [];\n\n try {\n // Get process list with start time (macOS/Linux compatible)\n const psOutput = execSync(\n 'ps -eo pid,lstart,command 2>/dev/null || ps -eo pid,start,args 2>/dev/null',\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }\n );\n\n const lines = psOutput.trim().split('\\n').slice(1); // Skip header\n\n for (const line of lines) {\n // Check if it's a stackmemory process\n const isStackmemory = STACKMEMORY_PROCESS_PATTERNS.some((pattern) =>\n line.toLowerCase().includes(pattern.toLowerCase())\n );\n\n if (!isStackmemory) continue;\n\n // Parse the line - format varies by OS\n // macOS: PID \"Day Mon DD HH:MM:SS YYYY\" COMMAND\n const match = line.match(\n /^\\s*(\\d+)\\s+(\\w+\\s+\\w+\\s+\\d+\\s+[\\d:]+\\s+\\d+)\\s+(.+)$/\n );\n\n if (match) {\n const pid = parseInt(match[1], 10);\n const startTimeStr = match[2];\n const command = match[3];\n\n // Skip current process\n if (pid === process.pid) continue;\n\n // Parse start time\n const startTime = new Date(startTimeStr);\n const ageMs = Date.now() - startTime.getTime();\n const ageHours = ageMs / (1000 * 60 * 60);\n\n processes.push({\n pid,\n command: command.slice(0, 100), // Truncate long commands\n startTime,\n ageHours,\n });\n }\n }\n } catch (error) {\n logger.warn('Failed to get process list:', error);\n }\n\n return processes;\n}\n\n/**\n * Check if a process has recent log activity\n */\nfunction hasRecentLogActivity(\n proc: StaleProcess,\n maxAgeHours: number\n): boolean {\n const logDir = path.join(os.homedir(), '.stackmemory', 'logs');\n\n if (!fs.existsSync(logDir)) return false;\n\n try {\n // Look for log files that might be related to this process\n const logFiles = fs.readdirSync(logDir).filter((f) => f.endsWith('.log'));\n\n for (const logFile of logFiles) {\n const logPath = path.join(logDir, logFile);\n const stats = fs.statSync(logPath);\n const logAgeHours = (Date.now() - stats.mtimeMs) / (1000 * 60 * 60);\n\n if (logAgeHours < maxAgeHours) {\n // Check if log contains this PID\n try {\n const content = fs.readFileSync(logPath, 'utf-8').slice(-10000); // Last 10KB\n if (\n content.includes(`pid:${proc.pid}`) ||\n content.includes(`PID ${proc.pid}`)\n ) {\n proc.logFile = logPath;\n proc.lastLogActivity = stats.mtime;\n return true;\n }\n } catch {\n // Ignore read errors\n }\n }\n }\n } catch (error) {\n logger.warn('Failed to check log activity:', error);\n }\n\n return false;\n}\n\n/**\n * Find stale processes older than specified hours with no recent log activity\n */\nexport function findStaleProcesses(maxAgeHours: number = 24): StaleProcess[] {\n const allProcesses = getStackmemoryProcesses();\n\n return allProcesses.filter((proc) => {\n // Must be older than threshold\n if (proc.ageHours < maxAgeHours) return false;\n\n // Check for recent log activity\n if (hasRecentLogActivity(proc, maxAgeHours)) return false;\n\n return true;\n });\n}\n\n/**\n * Kill stale processes\n */\nexport function killStaleProcesses(\n processes: StaleProcess[],\n dryRun: boolean = false\n): CleanupResult {\n const result: CleanupResult = {\n found: processes,\n killed: [],\n errors: [],\n };\n\n for (const proc of processes) {\n if (dryRun) {\n logger.info(`[DRY RUN] Would kill PID ${proc.pid}: ${proc.command}`);\n continue;\n }\n\n try {\n process.kill(proc.pid, 'SIGTERM');\n result.killed.push(proc.pid);\n logger.info(`Killed stale process ${proc.pid}: ${proc.command}`);\n } catch (error: unknown) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ESRCH') {\n // Process already dead\n result.killed.push(proc.pid);\n } else {\n result.errors.push({\n pid: proc.pid,\n error: err.message || 'Unknown error',\n });\n logger.warn(`Failed to kill PID ${proc.pid}:`, err.message);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Main cleanup function\n */\nexport function cleanupStaleProcesses(\n options: {\n maxAgeHours?: number;\n dryRun?: boolean;\n } = {}\n): CleanupResult {\n const { maxAgeHours = 24, dryRun = false } = options;\n\n logger.info(`Looking for stale processes older than ${maxAgeHours}h...`);\n\n const staleProcesses = findStaleProcesses(maxAgeHours);\n\n if (staleProcesses.length === 0) {\n logger.info('No stale processes found');\n return { found: [], killed: [], errors: [] };\n }\n\n logger.info(`Found ${staleProcesses.length} stale process(es)`);\n\n return killStaleProcesses(staleProcesses, dryRun);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackmemoryai/stackmemory",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention",
5
5
  "engines": {
6
6
  "node": ">=20.0.0",
@@ -10,7 +10,9 @@
10
10
  "main": "dist/index.js",
11
11
  "bin": {
12
12
  "stackmemory": "dist/cli/index.js",
13
- "codex-sm": "dist/cli/codex-sm.js"
13
+ "codex-sm": "dist/cli/codex-sm.js",
14
+ "claude-sm": "bin/claude-sm",
15
+ "claude-smd": "bin/claude-smd"
14
16
  },
15
17
  "types": "dist/src/index.d.ts",
16
18
  "files": [
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env zsh
2
+ # StackMemory Sweep Completion for ZSH
3
+ # Non-intrusive: shows context in RPROMPT, no input hijacking
4
+
5
+ # Configuration
6
+ SWEEP_COMPLETE_ENABLED=${SWEEP_COMPLETE_ENABLED:-true}
7
+ SWEEP_STATE_FILE="${HOME}/.stackmemory/sweep-state.json"
8
+ SWEEP_SUGGEST_SCRIPT="${HOME}/.stackmemory/shell/sweep-suggest.js"
9
+
10
+ # State
11
+ typeset -g _sweep_suggestion=""
12
+ typeset -g _sweep_last_check=0
13
+
14
+ # Get suggestion (called on-demand only)
15
+ _sweep_get_suggestion() {
16
+ [[ "$SWEEP_COMPLETE_ENABLED" != "true" ]] && return 1
17
+ [[ ${#BUFFER} -lt 3 ]] && return 1
18
+
19
+ if [[ -f "$SWEEP_SUGGEST_SCRIPT" ]]; then
20
+ _sweep_suggestion=$(echo "$BUFFER" | timeout 0.5 node "$SWEEP_SUGGEST_SCRIPT" 2>/dev/null)
21
+ [[ -n "$_sweep_suggestion" ]] && return 0
22
+ fi
23
+ return 1
24
+ }
25
+
26
+ # Accept current suggestion
27
+ _sweep_accept() {
28
+ if [[ -n "$_sweep_suggestion" ]]; then
29
+ BUFFER="${BUFFER}${_sweep_suggestion}"
30
+ CURSOR=${#BUFFER}
31
+ _sweep_suggestion=""
32
+ RPROMPT="$_sweep_saved_rprompt"
33
+ zle redisplay
34
+ else
35
+ # Fall through to normal tab completion
36
+ zle expand-or-complete
37
+ fi
38
+ }
39
+
40
+ # Request suggestion manually (Ctrl+])
41
+ _sweep_request() {
42
+ if _sweep_get_suggestion; then
43
+ _sweep_saved_rprompt="$RPROMPT"
44
+ RPROMPT="%F{240}[${_sweep_suggestion}]%f"
45
+ zle redisplay
46
+ else
47
+ zle -M "No suggestion available"
48
+ fi
49
+ }
50
+
51
+ # Clear suggestion
52
+ _sweep_clear() {
53
+ _sweep_suggestion=""
54
+ RPROMPT="$_sweep_saved_rprompt"
55
+ }
56
+
57
+ # Widget definitions
58
+ zle -N sweep-accept _sweep_accept
59
+ zle -N sweep-request _sweep_request
60
+ zle -N sweep-clear _sweep_clear
61
+
62
+ # Key bindings - ONLY these, no input hijacking
63
+ bindkey '^[[Z' sweep-request # Shift+Tab to request suggestion
64
+ bindkey '^I' sweep-accept # Tab to accept (falls through to normal completion if no suggestion)
65
+
66
+ # Show recent file context in RPROMPT (passive, after each command)
67
+ _sweep_show_context() {
68
+ [[ "$SWEEP_COMPLETE_ENABLED" != "true" ]] && return
69
+
70
+ if [[ -f "$SWEEP_STATE_FILE" ]]; then
71
+ local recent_file=$(grep -o '"file_path":"[^"]*"' "$SWEEP_STATE_FILE" 2>/dev/null | head -1 | cut -d'"' -f4)
72
+ if [[ -n "$recent_file" ]]; then
73
+ local filename=$(basename "$recent_file")
74
+ _sweep_saved_rprompt="%F{240}[${filename}]%f"
75
+ RPROMPT="$_sweep_saved_rprompt"
76
+ fi
77
+ fi
78
+ }
79
+
80
+ # Hook into prompt refresh (runs after each command, not during typing)
81
+ autoload -Uz add-zsh-hook
82
+ add-zsh-hook precmd _sweep_show_context
83
+
84
+ # Status
85
+ sweep_status() {
86
+ echo "Sweep Shell Integration"
87
+ echo " Enabled: $SWEEP_COMPLETE_ENABLED"
88
+ echo " Current suggestion: ${_sweep_suggestion:-none}"
89
+ echo ""
90
+ if [[ -f "$SWEEP_STATE_FILE" ]]; then
91
+ local count=$(grep -c '"file_path"' "$SWEEP_STATE_FILE" 2>/dev/null || echo 0)
92
+ echo " Recent edits tracked: $count"
93
+ fi
94
+ echo ""
95
+ echo "Usage:"
96
+ echo " Shift+Tab Request suggestion based on input"
97
+ echo " Tab Accept suggestion (or normal completion)"
98
+ echo ""
99
+ echo "The right prompt shows your most recently edited file."
100
+ }
101
+
102
+ # Toggle
103
+ sweep_toggle() {
104
+ if [[ "$SWEEP_COMPLETE_ENABLED" == "true" ]]; then
105
+ SWEEP_COMPLETE_ENABLED=false
106
+ RPROMPT=""
107
+ echo "Sweep disabled"
108
+ else
109
+ SWEEP_COMPLETE_ENABLED=true
110
+ _sweep_show_context
111
+ echo "Sweep enabled"
112
+ fi
113
+ }
114
+
115
+ alias sweep-on='SWEEP_COMPLETE_ENABLED=true; _sweep_show_context; echo "Sweep enabled"'
116
+ alias sweep-off='SWEEP_COMPLETE_ENABLED=false; RPROMPT=""; echo "Sweep disabled"'