@stackmemoryai/stackmemory 0.3.9 → 0.3.10

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 (40) hide show
  1. package/README.md +53 -0
  2. package/dist/agents/core/agent-task-manager.js +12 -1
  3. package/dist/agents/core/agent-task-manager.js.map +3 -3
  4. package/dist/agents/testing-agent.js +610 -0
  5. package/dist/agents/testing-agent.js.map +7 -0
  6. package/dist/cli/claude-sm.js +2 -2
  7. package/dist/cli/claude-sm.js.map +2 -2
  8. package/dist/cli/codex-sm.js +2 -2
  9. package/dist/cli/codex-sm.js.map +2 -2
  10. package/dist/cli/commands/handoff.js +65 -18
  11. package/dist/cli/commands/handoff.js.map +3 -3
  12. package/dist/cli/commands/onboard.js +3 -3
  13. package/dist/cli/commands/onboard.js.map +2 -2
  14. package/dist/cli/commands/quality.js +2 -2
  15. package/dist/cli/commands/quality.js.map +2 -2
  16. package/dist/cli/commands/skills.js +113 -28
  17. package/dist/cli/commands/skills.js.map +2 -2
  18. package/dist/cli/commands/test.js +282 -0
  19. package/dist/cli/commands/test.js.map +7 -0
  20. package/dist/cli/commands/worktree.js +28 -10
  21. package/dist/cli/commands/worktree.js.map +2 -2
  22. package/dist/cli/index.js +2 -0
  23. package/dist/cli/index.js.map +2 -2
  24. package/dist/core/config/config-manager.js +26 -0
  25. package/dist/core/config/config-manager.js.map +3 -3
  26. package/dist/core/context/frame-manager.js +139 -0
  27. package/dist/core/context/frame-manager.js.map +2 -2
  28. package/dist/core/context/refactored-frame-manager.js +180 -1
  29. package/dist/core/context/refactored-frame-manager.js.map +2 -2
  30. package/dist/core/utils/update-checker.js +2 -2
  31. package/dist/core/utils/update-checker.js.map +2 -2
  32. package/dist/integrations/claude-code/subagent-client-stub.js +16 -0
  33. package/dist/integrations/claude-code/subagent-client-stub.js.map +7 -0
  34. package/dist/skills/claude-skills.js +97 -3
  35. package/dist/skills/claude-skills.js.map +2 -2
  36. package/dist/skills/security-secrets-scanner.js +21 -6
  37. package/dist/skills/security-secrets-scanner.js.map +2 -2
  38. package/dist/skills/unified-rlm-orchestrator.js +400 -0
  39. package/dist/skills/unified-rlm-orchestrator.js.map +7 -0
  40. package/package.json +3 -2
@@ -7,6 +7,8 @@ import {
7
7
  ErrorCode
8
8
  } from "../errors/index.js";
9
9
  import { FrameQueryMode } from "../session/index.js";
10
+ const MAX_FRAME_DEPTH = 100;
11
+ const DEFAULT_MAX_DEPTH = 100;
10
12
  import { FrameDatabase } from "./frame-database.js";
11
13
  import { FrameStack } from "./frame-stack.js";
12
14
  import { FrameDigestGenerator } from "./frame-digest.js";
@@ -19,6 +21,7 @@ class RefactoredFrameManager {
19
21
  projectId;
20
22
  queryMode = FrameQueryMode.PROJECT_ACTIVE;
21
23
  config;
24
+ maxFrameDepth = DEFAULT_MAX_DEPTH;
22
25
  constructor(db, projectId, config) {
23
26
  this.projectId = projectId;
24
27
  this.config = {
@@ -27,6 +30,7 @@ class RefactoredFrameManager {
27
30
  sessionId: config?.sessionId || uuidv4(),
28
31
  maxStackDepth: config?.maxStackDepth || 50
29
32
  };
33
+ this.maxFrameDepth = config?.maxStackDepth || DEFAULT_MAX_DEPTH;
30
34
  this.currentRunId = this.config.runId;
31
35
  this.sessionId = this.config.sessionId;
32
36
  this.frameDb = new FrameDatabase(db);
@@ -96,7 +100,37 @@ class RefactoredFrameManager {
96
100
  );
97
101
  }
98
102
  const resolvedParentId = frameOptions.parentFrameId || this.frameStack.getCurrentFrameId();
99
- const depth = resolvedParentId ? this.frameStack.getFrameStackDepth(resolvedParentId) + 1 : 0;
103
+ let depth = 0;
104
+ if (resolvedParentId) {
105
+ const parentFrame = this.frameDb.getFrame(resolvedParentId);
106
+ depth = parentFrame ? parentFrame.depth + 1 : 0;
107
+ }
108
+ if (depth > this.maxFrameDepth) {
109
+ throw new FrameError(
110
+ `Maximum frame depth exceeded: ${depth} > ${this.maxFrameDepth}`,
111
+ ErrorCode.FRAME_STACK_OVERFLOW,
112
+ {
113
+ currentDepth: depth,
114
+ maxDepth: this.maxFrameDepth,
115
+ frameName: frameOptions.name,
116
+ parentFrameId: resolvedParentId
117
+ }
118
+ );
119
+ }
120
+ if (resolvedParentId) {
121
+ const cycle = this.detectCycle(uuidv4(), resolvedParentId);
122
+ if (cycle) {
123
+ throw new FrameError(
124
+ `Circular reference detected in frame hierarchy`,
125
+ ErrorCode.FRAME_CYCLE_DETECTED,
126
+ {
127
+ parentFrameId: resolvedParentId,
128
+ cycle,
129
+ frameName: frameOptions.name
130
+ }
131
+ );
132
+ }
133
+ }
100
134
  const frameId = uuidv4();
101
135
  const frame = {
102
136
  frame_id: frameId,
@@ -375,6 +409,151 @@ class RefactoredFrameManager {
375
409
  }
376
410
  return constraints;
377
411
  }
412
+ /**
413
+ * Detect if setting a parent frame would create a cycle in the frame hierarchy.
414
+ * Returns the cycle path if detected, or null if no cycle.
415
+ * @param childFrameId - The frame that would be the child
416
+ * @param parentFrameId - The proposed parent frame
417
+ * @returns Array of frame IDs forming the cycle, or null if no cycle
418
+ */
419
+ detectCycle(childFrameId, parentFrameId) {
420
+ const visited = /* @__PURE__ */ new Set();
421
+ const path = [];
422
+ let currentId = parentFrameId;
423
+ while (currentId) {
424
+ if (visited.has(currentId)) {
425
+ const cycleStart = path.indexOf(currentId);
426
+ return path.slice(cycleStart).concat(currentId);
427
+ }
428
+ if (currentId === childFrameId) {
429
+ return path.concat([currentId, childFrameId]);
430
+ }
431
+ visited.add(currentId);
432
+ path.push(currentId);
433
+ const frame = this.frameDb.getFrame(currentId);
434
+ if (!frame) {
435
+ break;
436
+ }
437
+ currentId = frame.parent_frame_id;
438
+ if (path.length > this.maxFrameDepth) {
439
+ throw new FrameError(
440
+ `Frame hierarchy traversal exceeded maximum depth during cycle detection`,
441
+ ErrorCode.FRAME_STACK_OVERFLOW,
442
+ {
443
+ depth: path.length,
444
+ maxDepth: this.maxFrameDepth,
445
+ path
446
+ }
447
+ );
448
+ }
449
+ }
450
+ return null;
451
+ }
452
+ /**
453
+ * Update parent frame of an existing frame (with cycle detection)
454
+ * @param frameId - The frame to update
455
+ * @param newParentFrameId - The new parent frame ID (null to make it a root frame)
456
+ */
457
+ updateParentFrame(frameId, newParentFrameId) {
458
+ const frame = this.frameDb.getFrame(frameId);
459
+ if (!frame) {
460
+ throw new FrameError(
461
+ `Frame not found: ${frameId}`,
462
+ ErrorCode.FRAME_NOT_FOUND,
463
+ { frameId }
464
+ );
465
+ }
466
+ if (newParentFrameId) {
467
+ const cycle = this.detectCycle(frameId, newParentFrameId);
468
+ if (cycle) {
469
+ throw new FrameError(
470
+ `Cannot set parent: would create circular reference`,
471
+ ErrorCode.FRAME_CYCLE_DETECTED,
472
+ {
473
+ frameId,
474
+ newParentFrameId,
475
+ cycle,
476
+ currentParentId: frame.parent_frame_id
477
+ }
478
+ );
479
+ }
480
+ const newParentFrame = this.frameDb.getFrame(newParentFrameId);
481
+ if (newParentFrame) {
482
+ const newDepth = newParentFrame.depth + 1;
483
+ if (newDepth > this.maxFrameDepth) {
484
+ throw new FrameError(
485
+ `Cannot set parent: would exceed maximum frame depth`,
486
+ ErrorCode.FRAME_STACK_OVERFLOW,
487
+ {
488
+ frameId,
489
+ newParentFrameId,
490
+ newDepth,
491
+ maxDepth: this.maxFrameDepth
492
+ }
493
+ );
494
+ }
495
+ }
496
+ }
497
+ this.frameDb.updateFrame(frameId, {
498
+ parent_frame_id: newParentFrameId
499
+ });
500
+ logger.info("Updated parent frame", {
501
+ frameId,
502
+ oldParentId: frame.parent_frame_id,
503
+ newParentId: newParentFrameId
504
+ });
505
+ }
506
+ /**
507
+ * Validate the entire frame hierarchy for cycles and depth violations
508
+ * @returns Validation result with any detected issues
509
+ */
510
+ validateFrameHierarchy() {
511
+ const errors = [];
512
+ const warnings = [];
513
+ const allFrames = this.frameDb.getFramesByProject(this.projectId);
514
+ for (const frame of allFrames) {
515
+ if (frame.depth > this.maxFrameDepth) {
516
+ errors.push(
517
+ `Frame ${frame.frame_id} exceeds max depth: ${frame.depth} > ${this.maxFrameDepth}`
518
+ );
519
+ }
520
+ if (frame.depth > this.maxFrameDepth * 0.8) {
521
+ warnings.push(
522
+ `Frame ${frame.frame_id} is deep in hierarchy: ${frame.depth}/${this.maxFrameDepth}`
523
+ );
524
+ }
525
+ }
526
+ const rootFrames = allFrames.filter((f) => !f.parent_frame_id);
527
+ const visited = /* @__PURE__ */ new Set();
528
+ const visiting = /* @__PURE__ */ new Set();
529
+ const checkForCycle = (frameId) => {
530
+ if (visiting.has(frameId)) {
531
+ errors.push(`Cycle detected involving frame ${frameId}`);
532
+ return true;
533
+ }
534
+ if (visited.has(frameId)) {
535
+ return false;
536
+ }
537
+ visiting.add(frameId);
538
+ const children = allFrames.filter((f) => f.parent_frame_id === frameId);
539
+ for (const child of children) {
540
+ if (checkForCycle(child.frame_id)) {
541
+ return true;
542
+ }
543
+ }
544
+ visiting.delete(frameId);
545
+ visited.add(frameId);
546
+ return false;
547
+ };
548
+ for (const root of rootFrames) {
549
+ checkForCycle(root.frame_id);
550
+ }
551
+ return {
552
+ isValid: errors.length === 0,
553
+ errors,
554
+ warnings
555
+ };
556
+ }
378
557
  }
379
558
  import {
380
559
  Frame as Frame2,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/context/refactored-frame-manager.ts"],
4
- "sourcesContent": ["/**\n * Refactored Frame Manager - Modular Implementation\n * Main orchestrator that uses focused modules for frame management\n */\n\nimport Database from 'better-sqlite3';\nimport { v4 as uuidv4 } from 'uuid';\nimport { logger } from '../monitoring/logger.js';\nimport { trace } from '../trace/index.js';\nimport {\n FrameError,\n SystemError,\n ErrorCode,\n wrapError,\n createErrorHandler,\n} from '../errors/index.js';\nimport { retry, withTimeout } from '../errors/recovery.js';\nimport { sessionManager, FrameQueryMode } from '../session/index.js';\n\n// Import refactored modules\nimport {\n Frame,\n FrameContext,\n Anchor,\n Event,\n FrameType,\n FrameState,\n FrameCreationOptions,\n FrameManagerConfig,\n DigestResult,\n} from './frame-types.js';\nimport { FrameDatabase } from './frame-database.js';\nimport { FrameStack } from './frame-stack.js';\nimport { FrameDigestGenerator } from './frame-digest.js';\n\nexport class RefactoredFrameManager {\n private frameDb: FrameDatabase;\n private frameStack: FrameStack;\n private digestGenerator: FrameDigestGenerator;\n\n private currentRunId: string;\n private sessionId: string;\n private projectId: string;\n private queryMode: FrameQueryMode = FrameQueryMode.PROJECT_ACTIVE;\n private config: FrameManagerConfig;\n\n constructor(\n db: Database.Database,\n projectId: string,\n config?: Partial<FrameManagerConfig>\n ) {\n this.projectId = projectId;\n this.config = {\n projectId,\n runId: config?.runId || uuidv4(),\n sessionId: config?.sessionId || uuidv4(),\n maxStackDepth: config?.maxStackDepth || 50,\n };\n\n this.currentRunId = this.config.runId!;\n this.sessionId = this.config.sessionId!;\n\n // Initialize modules\n this.frameDb = new FrameDatabase(db);\n this.frameStack = new FrameStack(\n this.frameDb,\n projectId,\n this.currentRunId\n );\n this.digestGenerator = new FrameDigestGenerator(this.frameDb);\n\n // Initialize database schema\n this.frameDb.initSchema();\n\n logger.info('RefactoredFrameManager initialized', {\n projectId: this.projectId,\n runId: this.currentRunId,\n sessionId: this.sessionId,\n });\n }\n\n /**\n * Initialize the frame manager\n */\n async initialize(): Promise<void> {\n try {\n await this.frameStack.initialize();\n\n logger.info('Frame manager initialization completed', {\n stackDepth: this.frameStack.getDepth(),\n });\n } catch (error: unknown) {\n throw new SystemError(\n 'Failed to initialize frame manager',\n ErrorCode.SYSTEM_INIT_FAILED,\n { projectId: this.projectId },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new frame\n */\n createFrame(options: FrameCreationOptions): string;\n createFrame(\n type: FrameType,\n name: string,\n inputs?: Record<string, any>,\n parentFrameId?: string\n ): string;\n createFrame(\n typeOrOptions: FrameType | FrameCreationOptions,\n name?: string,\n inputs?: Record<string, any>,\n parentFrameId?: string\n ): string {\n return trace.traceSync(\n 'function',\n 'FrameManager.createFrame',\n { typeOrOptions, name },\n () => this._createFrame(typeOrOptions, name, inputs, parentFrameId)\n );\n }\n\n private _createFrame(\n typeOrOptions: FrameType | FrameCreationOptions,\n name?: string,\n inputs?: Record<string, any>,\n parentFrameId?: string\n ): string {\n let frameOptions: FrameCreationOptions;\n\n // Handle both function signatures\n if (typeof typeOrOptions === 'string') {\n frameOptions = {\n type: typeOrOptions,\n name: name!,\n inputs: inputs || {},\n parentFrameId,\n };\n } else {\n frameOptions = typeOrOptions;\n }\n\n // Validate inputs\n if (!frameOptions.name || frameOptions.name.trim().length === 0) {\n throw new FrameError(\n 'Frame name is required',\n ErrorCode.FRAME_INVALID_INPUT,\n { frameOptions }\n );\n }\n\n // Check stack depth limit\n if (this.frameStack.getDepth() >= this.config.maxStackDepth!) {\n throw new FrameError(\n `Maximum stack depth reached: ${this.config.maxStackDepth}`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n { currentDepth: this.frameStack.getDepth() }\n );\n }\n\n // Determine parent frame\n const resolvedParentId =\n frameOptions.parentFrameId || this.frameStack.getCurrentFrameId();\n const depth = resolvedParentId\n ? this.frameStack.getFrameStackDepth(resolvedParentId) + 1\n : 0;\n\n // Create frame data\n const frameId = uuidv4();\n const frame: Omit<Frame, 'created_at' | 'closed_at'> = {\n frame_id: frameId,\n run_id: this.currentRunId,\n project_id: this.projectId,\n parent_frame_id: resolvedParentId,\n depth,\n type: frameOptions.type,\n name: frameOptions.name,\n state: 'active',\n inputs: frameOptions.inputs || {},\n outputs: {},\n digest_json: {},\n };\n\n // Insert into database\n const createdFrame = this.frameDb.insertFrame(frame);\n\n // Add to stack\n this.frameStack.pushFrame(frameId);\n\n logger.info('Created frame', {\n frameId,\n name: frameOptions.name,\n type: frameOptions.type,\n parentFrameId: resolvedParentId,\n stackDepth: this.frameStack.getDepth(),\n });\n\n return frameId;\n }\n\n /**\n * Close a frame and generate digest\n */\n closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n trace.traceSync(\n 'function',\n 'FrameManager.closeFrame',\n { frameId, outputs },\n () => this._closeFrame(frameId, outputs)\n );\n }\n\n private _closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n const targetFrameId = frameId || this.frameStack.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame to close',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'closeFrame',\n stackDepth: this.frameStack.getDepth(),\n }\n );\n }\n\n // Get frame details\n const frame = this.frameDb.getFrame(targetFrameId);\n if (!frame) {\n throw new FrameError(\n `Frame not found: ${targetFrameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n {\n frameId: targetFrameId,\n operation: 'closeFrame',\n runId: this.currentRunId,\n }\n );\n }\n\n if (frame.state === 'closed') {\n logger.warn('Attempted to close already closed frame', {\n frameId: targetFrameId,\n });\n return;\n }\n\n // Generate digest before closing\n const digest = this.digestGenerator.generateDigest(targetFrameId);\n const finalOutputs = { ...outputs, ...digest.structured };\n\n // Update frame to closed state\n this.frameDb.updateFrame(targetFrameId, {\n state: 'closed',\n outputs: finalOutputs,\n digest_text: digest.text,\n digest_json: digest.structured,\n closed_at: Math.floor(Date.now() / 1000),\n });\n\n // Remove from stack (this will also remove any child frames)\n this.frameStack.popFrame(targetFrameId);\n\n // Close all child frames recursively\n this.closeChildFrames(targetFrameId);\n\n logger.info('Closed frame', {\n frameId: targetFrameId,\n name: frame.name,\n duration: Math.floor(Date.now() / 1000) - frame.created_at,\n digestLength: digest.text.length,\n stackDepth: this.frameStack.getDepth(),\n });\n }\n\n /**\n * Add an event to the current frame\n */\n addEvent(\n eventType: Event['event_type'],\n payload: Record<string, any>,\n frameId?: string\n ): string {\n return trace.traceSync(\n 'function',\n 'FrameManager.addEvent',\n { eventType, frameId },\n () => this._addEvent(eventType, payload, frameId)\n );\n }\n\n private _addEvent(\n eventType: Event['event_type'],\n payload: Record<string, any>,\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.frameStack.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for event',\n ErrorCode.FRAME_INVALID_STATE,\n {\n eventType,\n operation: 'addEvent',\n }\n );\n }\n\n const eventId = uuidv4();\n const sequence = this.frameDb.getNextEventSequence(targetFrameId);\n\n const event: Omit<Event, 'ts'> = {\n event_id: eventId,\n frame_id: targetFrameId,\n run_id: this.currentRunId,\n seq: sequence,\n event_type: eventType,\n payload,\n };\n\n const createdEvent = this.frameDb.insertEvent(event);\n\n logger.debug('Added event', {\n eventId,\n frameId: targetFrameId,\n eventType,\n sequence,\n });\n\n return eventId;\n }\n\n /**\n * Add an anchor (important fact) to current frame\n */\n addAnchor(\n type: Anchor['type'],\n text: string,\n priority: number = 5,\n metadata: Record<string, any> = {},\n frameId?: string\n ): string {\n return trace.traceSync(\n 'function',\n 'FrameManager.addAnchor',\n { type, frameId },\n () => this._addAnchor(type, text, priority, metadata, frameId)\n );\n }\n\n private _addAnchor(\n type: Anchor['type'],\n text: string,\n priority: number,\n metadata: Record<string, any>,\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.frameStack.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for anchor',\n ErrorCode.FRAME_INVALID_STATE,\n {\n anchorType: type,\n operation: 'addAnchor',\n }\n );\n }\n\n const anchorId = uuidv4();\n const anchor: Omit<Anchor, 'created_at'> = {\n anchor_id: anchorId,\n frame_id: targetFrameId,\n type,\n text,\n priority,\n metadata,\n };\n\n const createdAnchor = this.frameDb.insertAnchor(anchor);\n\n logger.debug('Added anchor', {\n anchorId,\n frameId: targetFrameId,\n type,\n priority,\n });\n\n return anchorId;\n }\n\n /**\n * Get hot stack context\n */\n getHotStackContext(maxEvents: number = 20): FrameContext[] {\n return this.frameStack.getHotStackContext(maxEvents);\n }\n\n /**\n * Get active frame path (root to current)\n */\n getActiveFramePath(): Frame[] {\n return this.frameStack.getStackFrames();\n }\n\n /**\n * Get current frame ID\n */\n getCurrentFrameId(): string | undefined {\n return this.frameStack.getCurrentFrameId();\n }\n\n /**\n * Get stack depth\n */\n getStackDepth(): number {\n return this.frameStack.getDepth();\n }\n\n /**\n * Get frame by ID\n */\n getFrame(frameId: string): Frame | undefined {\n return this.frameDb.getFrame(frameId);\n }\n\n /**\n * Get frame events\n */\n getFrameEvents(frameId: string, limit?: number): Event[] {\n return this.frameDb.getFrameEvents(frameId, limit);\n }\n\n /**\n * Get frame anchors\n */\n getFrameAnchors(frameId: string): Anchor[] {\n return this.frameDb.getFrameAnchors(frameId);\n }\n\n /**\n * Generate digest for a frame\n */\n generateDigest(frameId: string): DigestResult {\n return this.digestGenerator.generateDigest(frameId);\n }\n\n /**\n * Validate stack consistency\n */\n validateStack(): { isValid: boolean; errors: string[] } {\n return this.frameStack.validateStack();\n }\n\n /**\n * Get database statistics\n */\n getStatistics(): Record<string, number> {\n return this.frameDb.getStatistics();\n }\n\n /**\n * Close all child frames recursively\n */\n private closeChildFrames(parentFrameId: string): void {\n try {\n const activeFrames = this.frameDb.getFramesByProject(\n this.projectId,\n 'active'\n );\n const childFrames = activeFrames.filter(\n (f: any) => f.parent_frame_id === parentFrameId\n );\n\n for (const childFrame of childFrames) {\n if (this.frameStack.isFrameActive(childFrame.frame_id)) {\n this.closeFrame(childFrame.frame_id);\n }\n }\n } catch (error: unknown) {\n logger.warn('Failed to close child frames', { parentFrameId, error });\n }\n }\n\n /**\n * Extract active artifacts from frame events\n */\n getActiveArtifacts(frameId: string): string[] {\n const events = this.frameDb.getFrameEvents(frameId);\n const artifacts: string[] = [];\n\n for (const event of events) {\n if (event.event_type === 'artifact' && event.payload.path) {\n artifacts.push(event.payload.path);\n }\n }\n\n return [...new Set(artifacts)];\n }\n\n /**\n * Extract constraints from frame inputs\n */\n extractConstraints(inputs: Record<string, any>): string[] {\n const constraints: string[] = [];\n\n if (inputs.constraints && Array.isArray(inputs.constraints)) {\n constraints.push(...inputs.constraints);\n }\n\n if (inputs.requirements && Array.isArray(inputs.requirements)) {\n constraints.push(...inputs.requirements);\n }\n\n if (inputs.limitations && Array.isArray(inputs.limitations)) {\n constraints.push(...inputs.limitations);\n }\n\n return constraints;\n }\n}\n\n// Re-export types for compatibility\nexport {\n Frame,\n FrameContext,\n Anchor,\n Event,\n FrameType,\n FrameState,\n FrameCreationOptions,\n FrameManagerConfig,\n DigestResult,\n} from './frame-types.js';\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Refactored Frame Manager - Modular Implementation\n * Main orchestrator that uses focused modules for frame management\n */\n\nimport Database from 'better-sqlite3';\nimport { v4 as uuidv4 } from 'uuid';\nimport { logger } from '../monitoring/logger.js';\nimport { trace } from '../trace/index.js';\nimport {\n FrameError,\n SystemError,\n ErrorCode,\n wrapError,\n createErrorHandler,\n} from '../errors/index.js';\nimport { retry, withTimeout } from '../errors/recovery.js';\nimport { sessionManager, FrameQueryMode } from '../session/index.js';\n\n// Constants for frame validation\nconst MAX_FRAME_DEPTH = 100; // Maximum allowed frame depth\nconst DEFAULT_MAX_DEPTH = 100; // Default if not configured\n\n// Import refactored modules\nimport {\n Frame,\n FrameContext,\n Anchor,\n Event,\n FrameType,\n FrameState,\n FrameCreationOptions,\n FrameManagerConfig,\n DigestResult,\n} from './frame-types.js';\nimport { FrameDatabase } from './frame-database.js';\nimport { FrameStack } from './frame-stack.js';\nimport { FrameDigestGenerator } from './frame-digest.js';\n\nexport class RefactoredFrameManager {\n private frameDb: FrameDatabase;\n private frameStack: FrameStack;\n private digestGenerator: FrameDigestGenerator;\n\n private currentRunId: string;\n private sessionId: string;\n private projectId: string;\n private queryMode: FrameQueryMode = FrameQueryMode.PROJECT_ACTIVE;\n private config: FrameManagerConfig;\n private maxFrameDepth: number = DEFAULT_MAX_DEPTH;\n\n constructor(\n db: Database.Database,\n projectId: string,\n config?: Partial<FrameManagerConfig>\n ) {\n this.projectId = projectId;\n this.config = {\n projectId,\n runId: config?.runId || uuidv4(),\n sessionId: config?.sessionId || uuidv4(),\n maxStackDepth: config?.maxStackDepth || 50,\n };\n \n // Set max frame depth from config if provided\n this.maxFrameDepth = config?.maxStackDepth || DEFAULT_MAX_DEPTH;\n\n this.currentRunId = this.config.runId!;\n this.sessionId = this.config.sessionId!;\n\n // Initialize modules\n this.frameDb = new FrameDatabase(db);\n this.frameStack = new FrameStack(\n this.frameDb,\n projectId,\n this.currentRunId\n );\n this.digestGenerator = new FrameDigestGenerator(this.frameDb);\n\n // Initialize database schema\n this.frameDb.initSchema();\n\n logger.info('RefactoredFrameManager initialized', {\n projectId: this.projectId,\n runId: this.currentRunId,\n sessionId: this.sessionId,\n });\n }\n\n /**\n * Initialize the frame manager\n */\n async initialize(): Promise<void> {\n try {\n await this.frameStack.initialize();\n\n logger.info('Frame manager initialization completed', {\n stackDepth: this.frameStack.getDepth(),\n });\n } catch (error: unknown) {\n throw new SystemError(\n 'Failed to initialize frame manager',\n ErrorCode.SYSTEM_INIT_FAILED,\n { projectId: this.projectId },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new frame\n */\n createFrame(options: FrameCreationOptions): string;\n createFrame(\n type: FrameType,\n name: string,\n inputs?: Record<string, any>,\n parentFrameId?: string\n ): string;\n createFrame(\n typeOrOptions: FrameType | FrameCreationOptions,\n name?: string,\n inputs?: Record<string, any>,\n parentFrameId?: string\n ): string {\n return trace.traceSync(\n 'function',\n 'FrameManager.createFrame',\n { typeOrOptions, name },\n () => this._createFrame(typeOrOptions, name, inputs, parentFrameId)\n );\n }\n\n private _createFrame(\n typeOrOptions: FrameType | FrameCreationOptions,\n name?: string,\n inputs?: Record<string, any>,\n parentFrameId?: string\n ): string {\n let frameOptions: FrameCreationOptions;\n\n // Handle both function signatures\n if (typeof typeOrOptions === 'string') {\n frameOptions = {\n type: typeOrOptions,\n name: name!,\n inputs: inputs || {},\n parentFrameId,\n };\n } else {\n frameOptions = typeOrOptions;\n }\n\n // Validate inputs\n if (!frameOptions.name || frameOptions.name.trim().length === 0) {\n throw new FrameError(\n 'Frame name is required',\n ErrorCode.FRAME_INVALID_INPUT,\n { frameOptions }\n );\n }\n\n // Check stack depth limit\n if (this.frameStack.getDepth() >= this.config.maxStackDepth!) {\n throw new FrameError(\n `Maximum stack depth reached: ${this.config.maxStackDepth}`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n { currentDepth: this.frameStack.getDepth() }\n );\n }\n\n // Determine parent frame\n const resolvedParentId =\n frameOptions.parentFrameId || this.frameStack.getCurrentFrameId();\n \n // Get depth from parent frame, not from stack position\n let depth = 0;\n if (resolvedParentId) {\n const parentFrame = this.frameDb.getFrame(resolvedParentId);\n depth = parentFrame ? parentFrame.depth + 1 : 0;\n }\n\n // Check for depth limit\n if (depth > this.maxFrameDepth) {\n throw new FrameError(\n `Maximum frame depth exceeded: ${depth} > ${this.maxFrameDepth}`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n currentDepth: depth,\n maxDepth: this.maxFrameDepth,\n frameName: frameOptions.name,\n parentFrameId: resolvedParentId,\n }\n );\n }\n\n // Check for circular reference before creating frame\n if (resolvedParentId) {\n const cycle = this.detectCycle(uuidv4(), resolvedParentId);\n if (cycle) {\n throw new FrameError(\n `Circular reference detected in frame hierarchy`,\n ErrorCode.FRAME_CYCLE_DETECTED,\n {\n parentFrameId: resolvedParentId,\n cycle,\n frameName: frameOptions.name,\n }\n );\n }\n }\n\n // Create frame data\n const frameId = uuidv4();\n const frame: Omit<Frame, 'created_at' | 'closed_at'> = {\n frame_id: frameId,\n run_id: this.currentRunId,\n project_id: this.projectId,\n parent_frame_id: resolvedParentId,\n depth,\n type: frameOptions.type,\n name: frameOptions.name,\n state: 'active',\n inputs: frameOptions.inputs || {},\n outputs: {},\n digest_json: {},\n };\n\n // Insert into database\n const createdFrame = this.frameDb.insertFrame(frame);\n\n // Add to stack\n this.frameStack.pushFrame(frameId);\n\n logger.info('Created frame', {\n frameId,\n name: frameOptions.name,\n type: frameOptions.type,\n parentFrameId: resolvedParentId,\n stackDepth: this.frameStack.getDepth(),\n });\n\n return frameId;\n }\n\n /**\n * Close a frame and generate digest\n */\n closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n trace.traceSync(\n 'function',\n 'FrameManager.closeFrame',\n { frameId, outputs },\n () => this._closeFrame(frameId, outputs)\n );\n }\n\n private _closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n const targetFrameId = frameId || this.frameStack.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame to close',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'closeFrame',\n stackDepth: this.frameStack.getDepth(),\n }\n );\n }\n\n // Get frame details\n const frame = this.frameDb.getFrame(targetFrameId);\n if (!frame) {\n throw new FrameError(\n `Frame not found: ${targetFrameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n {\n frameId: targetFrameId,\n operation: 'closeFrame',\n runId: this.currentRunId,\n }\n );\n }\n\n if (frame.state === 'closed') {\n logger.warn('Attempted to close already closed frame', {\n frameId: targetFrameId,\n });\n return;\n }\n\n // Generate digest before closing\n const digest = this.digestGenerator.generateDigest(targetFrameId);\n const finalOutputs = { ...outputs, ...digest.structured };\n\n // Update frame to closed state\n this.frameDb.updateFrame(targetFrameId, {\n state: 'closed',\n outputs: finalOutputs,\n digest_text: digest.text,\n digest_json: digest.structured,\n closed_at: Math.floor(Date.now() / 1000),\n });\n\n // Remove from stack (this will also remove any child frames)\n this.frameStack.popFrame(targetFrameId);\n\n // Close all child frames recursively\n this.closeChildFrames(targetFrameId);\n\n logger.info('Closed frame', {\n frameId: targetFrameId,\n name: frame.name,\n duration: Math.floor(Date.now() / 1000) - frame.created_at,\n digestLength: digest.text.length,\n stackDepth: this.frameStack.getDepth(),\n });\n }\n\n /**\n * Add an event to the current frame\n */\n addEvent(\n eventType: Event['event_type'],\n payload: Record<string, any>,\n frameId?: string\n ): string {\n return trace.traceSync(\n 'function',\n 'FrameManager.addEvent',\n { eventType, frameId },\n () => this._addEvent(eventType, payload, frameId)\n );\n }\n\n private _addEvent(\n eventType: Event['event_type'],\n payload: Record<string, any>,\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.frameStack.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for event',\n ErrorCode.FRAME_INVALID_STATE,\n {\n eventType,\n operation: 'addEvent',\n }\n );\n }\n\n const eventId = uuidv4();\n const sequence = this.frameDb.getNextEventSequence(targetFrameId);\n\n const event: Omit<Event, 'ts'> = {\n event_id: eventId,\n frame_id: targetFrameId,\n run_id: this.currentRunId,\n seq: sequence,\n event_type: eventType,\n payload,\n };\n\n const createdEvent = this.frameDb.insertEvent(event);\n\n logger.debug('Added event', {\n eventId,\n frameId: targetFrameId,\n eventType,\n sequence,\n });\n\n return eventId;\n }\n\n /**\n * Add an anchor (important fact) to current frame\n */\n addAnchor(\n type: Anchor['type'],\n text: string,\n priority: number = 5,\n metadata: Record<string, any> = {},\n frameId?: string\n ): string {\n return trace.traceSync(\n 'function',\n 'FrameManager.addAnchor',\n { type, frameId },\n () => this._addAnchor(type, text, priority, metadata, frameId)\n );\n }\n\n private _addAnchor(\n type: Anchor['type'],\n text: string,\n priority: number,\n metadata: Record<string, any>,\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.frameStack.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for anchor',\n ErrorCode.FRAME_INVALID_STATE,\n {\n anchorType: type,\n operation: 'addAnchor',\n }\n );\n }\n\n const anchorId = uuidv4();\n const anchor: Omit<Anchor, 'created_at'> = {\n anchor_id: anchorId,\n frame_id: targetFrameId,\n type,\n text,\n priority,\n metadata,\n };\n\n const createdAnchor = this.frameDb.insertAnchor(anchor);\n\n logger.debug('Added anchor', {\n anchorId,\n frameId: targetFrameId,\n type,\n priority,\n });\n\n return anchorId;\n }\n\n /**\n * Get hot stack context\n */\n getHotStackContext(maxEvents: number = 20): FrameContext[] {\n return this.frameStack.getHotStackContext(maxEvents);\n }\n\n /**\n * Get active frame path (root to current)\n */\n getActiveFramePath(): Frame[] {\n return this.frameStack.getStackFrames();\n }\n\n /**\n * Get current frame ID\n */\n getCurrentFrameId(): string | undefined {\n return this.frameStack.getCurrentFrameId();\n }\n\n /**\n * Get stack depth\n */\n getStackDepth(): number {\n return this.frameStack.getDepth();\n }\n\n /**\n * Get frame by ID\n */\n getFrame(frameId: string): Frame | undefined {\n return this.frameDb.getFrame(frameId);\n }\n\n /**\n * Get frame events\n */\n getFrameEvents(frameId: string, limit?: number): Event[] {\n return this.frameDb.getFrameEvents(frameId, limit);\n }\n\n /**\n * Get frame anchors\n */\n getFrameAnchors(frameId: string): Anchor[] {\n return this.frameDb.getFrameAnchors(frameId);\n }\n\n /**\n * Generate digest for a frame\n */\n generateDigest(frameId: string): DigestResult {\n return this.digestGenerator.generateDigest(frameId);\n }\n\n /**\n * Validate stack consistency\n */\n validateStack(): { isValid: boolean; errors: string[] } {\n return this.frameStack.validateStack();\n }\n\n /**\n * Get database statistics\n */\n getStatistics(): Record<string, number> {\n return this.frameDb.getStatistics();\n }\n\n /**\n * Close all child frames recursively\n */\n private closeChildFrames(parentFrameId: string): void {\n try {\n const activeFrames = this.frameDb.getFramesByProject(\n this.projectId,\n 'active'\n );\n const childFrames = activeFrames.filter(\n (f: any) => f.parent_frame_id === parentFrameId\n );\n\n for (const childFrame of childFrames) {\n if (this.frameStack.isFrameActive(childFrame.frame_id)) {\n this.closeFrame(childFrame.frame_id);\n }\n }\n } catch (error: unknown) {\n logger.warn('Failed to close child frames', { parentFrameId, error });\n }\n }\n\n /**\n * Extract active artifacts from frame events\n */\n getActiveArtifacts(frameId: string): string[] {\n const events = this.frameDb.getFrameEvents(frameId);\n const artifacts: string[] = [];\n\n for (const event of events) {\n if (event.event_type === 'artifact' && event.payload.path) {\n artifacts.push(event.payload.path);\n }\n }\n\n return [...new Set(artifacts)];\n }\n\n /**\n * Extract constraints from frame inputs\n */\n extractConstraints(inputs: Record<string, any>): string[] {\n const constraints: string[] = [];\n\n if (inputs.constraints && Array.isArray(inputs.constraints)) {\n constraints.push(...inputs.constraints);\n }\n\n if (inputs.requirements && Array.isArray(inputs.requirements)) {\n constraints.push(...inputs.requirements);\n }\n\n if (inputs.limitations && Array.isArray(inputs.limitations)) {\n constraints.push(...inputs.limitations);\n }\n\n return constraints;\n }\n\n /**\n * Detect if setting a parent frame would create a cycle in the frame hierarchy.\n * Returns the cycle path if detected, or null if no cycle.\n * @param childFrameId - The frame that would be the child\n * @param parentFrameId - The proposed parent frame\n * @returns Array of frame IDs forming the cycle, or null if no cycle\n */\n private detectCycle(\n childFrameId: string,\n parentFrameId: string\n ): string[] | null {\n const visited = new Set<string>();\n const path: string[] = [];\n\n // Start from the proposed parent and traverse up the hierarchy\n let currentId: string | undefined = parentFrameId;\n \n while (currentId) {\n // If we've seen this frame before, we have a cycle\n if (visited.has(currentId)) {\n // Build the cycle path\n const cycleStart = path.indexOf(currentId);\n return path.slice(cycleStart).concat(currentId);\n }\n\n // If the current frame is the child we're trying to add, it's a cycle\n if (currentId === childFrameId) {\n return path.concat([currentId, childFrameId]);\n }\n\n visited.add(currentId);\n path.push(currentId);\n\n // Move to the parent of current frame\n const frame = this.frameDb.getFrame(currentId);\n if (!frame) {\n // Frame not found, no cycle possible through this path\n break;\n }\n currentId = frame.parent_frame_id;\n\n // Safety check: if we've traversed too many levels, something is wrong\n if (path.length > this.maxFrameDepth) {\n throw new FrameError(\n `Frame hierarchy traversal exceeded maximum depth during cycle detection`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n depth: path.length,\n maxDepth: this.maxFrameDepth,\n path,\n }\n );\n }\n }\n\n return null; // No cycle detected\n }\n\n /**\n * Update parent frame of an existing frame (with cycle detection)\n * @param frameId - The frame to update\n * @param newParentFrameId - The new parent frame ID (null to make it a root frame)\n */\n public updateParentFrame(frameId: string, newParentFrameId: string | null): void {\n // Check if frame exists\n const frame = this.frameDb.getFrame(frameId);\n if (!frame) {\n throw new FrameError(\n `Frame not found: ${frameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n { frameId }\n );\n }\n\n // If setting a parent, check for cycles\n if (newParentFrameId) {\n const cycle = this.detectCycle(frameId, newParentFrameId);\n if (cycle) {\n throw new FrameError(\n `Cannot set parent: would create circular reference`,\n ErrorCode.FRAME_CYCLE_DETECTED,\n {\n frameId,\n newParentFrameId,\n cycle,\n currentParentId: frame.parent_frame_id,\n }\n );\n }\n\n // Check depth after parent change\n const newParentFrame = this.frameDb.getFrame(newParentFrameId);\n if (newParentFrame) {\n const newDepth = newParentFrame.depth + 1;\n if (newDepth > this.maxFrameDepth) {\n throw new FrameError(\n `Cannot set parent: would exceed maximum frame depth`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n frameId,\n newParentFrameId,\n newDepth,\n maxDepth: this.maxFrameDepth,\n }\n );\n }\n }\n }\n\n // Update the frame's parent (this would need to be implemented in FrameDatabase)\n this.frameDb.updateFrame(frameId, {\n parent_frame_id: newParentFrameId,\n });\n\n logger.info('Updated parent frame', {\n frameId,\n oldParentId: frame.parent_frame_id,\n newParentId: newParentFrameId,\n });\n }\n\n /**\n * Validate the entire frame hierarchy for cycles and depth violations\n * @returns Validation result with any detected issues\n */\n public validateFrameHierarchy(): {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n } {\n const errors: string[] = [];\n const warnings: string[] = [];\n const allFrames = this.frameDb.getFramesByProject(this.projectId);\n \n // Check each frame for depth violations\n for (const frame of allFrames) {\n if (frame.depth > this.maxFrameDepth) {\n errors.push(\n `Frame ${frame.frame_id} exceeds max depth: ${frame.depth} > ${this.maxFrameDepth}`\n );\n }\n \n // Warn about deep frames approaching the limit\n if (frame.depth > this.maxFrameDepth * 0.8) {\n warnings.push(\n `Frame ${frame.frame_id} is deep in hierarchy: ${frame.depth}/${this.maxFrameDepth}`\n );\n }\n }\n \n // Check for cycles by traversing from each root\n const rootFrames = allFrames.filter(f => !f.parent_frame_id);\n const visited = new Set<string>();\n const visiting = new Set<string>();\n \n const checkForCycle = (frameId: string): boolean => {\n if (visiting.has(frameId)) {\n errors.push(`Cycle detected involving frame ${frameId}`);\n return true;\n }\n \n if (visited.has(frameId)) {\n return false;\n }\n \n visiting.add(frameId);\n \n // Check all children\n const children = allFrames.filter(f => f.parent_frame_id === frameId);\n for (const child of children) {\n if (checkForCycle(child.frame_id)) {\n return true;\n }\n }\n \n visiting.delete(frameId);\n visited.add(frameId);\n return false;\n };\n \n // Check from each root\n for (const root of rootFrames) {\n checkForCycle(root.frame_id);\n }\n \n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n }\n}\n\n// Re-export types for compatibility\nexport {\n Frame,\n FrameContext,\n Anchor,\n Event,\n FrameType,\n FrameState,\n FrameCreationOptions,\n FrameManagerConfig,\n DigestResult,\n} from './frame-types.js';\n"],
5
+ "mappings": "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",
6
6
  "names": ["Frame", "FrameContext", "Anchor", "Event", "FrameType", "FrameState", "FrameCreationOptions", "FrameManagerConfig", "DigestResult"]
7
7
  }
@@ -1,4 +1,4 @@
1
- import { execSync } from "child_process";
1
+ import { execFileSync } from "child_process";
2
2
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
3
3
  import { join } from "path";
4
4
  import { homedir } from "os";
@@ -59,7 +59,7 @@ class UpdateChecker {
59
59
  static async fetchLatestVersion() {
60
60
  try {
61
61
  const fetchVersion = async () => {
62
- const output = execSync(`npm view ${this.PACKAGE_NAME} version`, {
62
+ const output = execFileSync("npm", ["view", this.PACKAGE_NAME, "version"], {
63
63
  encoding: "utf-8",
64
64
  stdio: ["pipe", "pipe", "ignore"],
65
65
  timeout: 5e3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/utils/update-checker.ts"],
4
- "sourcesContent": ["/**\n * Update checker for StackMemory\n * Checks npm registry for newer versions\n */\n\nimport { execSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { logger } from '../monitoring/logger.js';\nimport {\n SystemError,\n ErrorCode,\n getErrorMessage,\n wrapError,\n} from '../errors/index.js';\nimport { withTimeout, gracefulDegrade } from '../errors/recovery.js';\n\ninterface UpdateCache {\n lastChecked: number;\n latestVersion: string;\n currentVersion: string;\n}\n\nexport class UpdateChecker {\n private static CACHE_FILE = join(\n homedir(),\n '.stackmemory',\n 'update-check.json'\n );\n private static CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours\n private static PACKAGE_NAME = '@stackmemoryai/stackmemory';\n\n /**\n * Check for updates and display notification if needed\n */\n static async checkForUpdates(\n currentVersion: string,\n silent = false\n ): Promise<void> {\n try {\n // Check cache first\n const cache = this.loadCache();\n const now = Date.now();\n\n // Skip check if we checked recently\n if (cache && now - cache.lastChecked < this.CHECK_INTERVAL) {\n if (\n !silent &&\n cache.latestVersion &&\n cache.latestVersion !== currentVersion\n ) {\n this.displayUpdateNotification(currentVersion, cache.latestVersion);\n }\n return;\n }\n\n // Fetch latest version from npm\n const latestVersion = await this.fetchLatestVersion();\n\n // Update cache\n this.saveCache({\n lastChecked: now,\n latestVersion,\n currentVersion,\n });\n\n // Display notification if update available\n if (\n !silent &&\n latestVersion &&\n this.isNewerVersion(currentVersion, latestVersion)\n ) {\n this.displayUpdateNotification(currentVersion, latestVersion);\n }\n } catch (error: unknown) {\n // Log the error with proper context but don't interrupt user workflow\n const wrappedError = wrapError(\n error,\n 'Update check failed',\n ErrorCode.INTERNAL_ERROR,\n { currentVersion, silent }\n );\n logger.debug('Update check failed:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n }\n }\n\n /**\n * Fetch latest version from npm registry\n */\n private static async fetchLatestVersion(): Promise<string> {\n try {\n // Use timeout to prevent hanging on slow network\n const fetchVersion = async () => {\n const output = execSync(`npm view ${this.PACKAGE_NAME} version`, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'ignore'],\n timeout: 5000, // 5 second timeout\n }).trim();\n return output;\n };\n\n // Wrap with timeout and graceful degradation\n return await gracefulDegrade(\n () => withTimeout(fetchVersion, 5000, 'npm registry timeout'),\n '',\n { operation: 'fetchLatestVersion', package: this.PACKAGE_NAME }\n );\n } catch (error: unknown) {\n const wrappedError = wrapError(\n error,\n 'Failed to fetch latest version from npm',\n ErrorCode.SERVICE_UNAVAILABLE,\n { package: this.PACKAGE_NAME }\n );\n logger.debug('Failed to fetch latest version:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n return '';\n }\n }\n\n /**\n * Compare version strings\n */\n private static isNewerVersion(current: string, latest: string): boolean {\n try {\n const currentParts = current.split('.').map(Number);\n const latestParts = latest.split('.').map(Number);\n\n // Handle malformed version strings\n if (currentParts.some(isNaN) || latestParts.some(isNaN)) {\n logger.debug('Invalid version format:', { current, latest });\n return false;\n }\n\n for (let i = 0; i < 3; i++) {\n const latestPart = latestParts[i] ?? 0;\n const currentPart = currentParts[i] ?? 0;\n if (latestPart > currentPart) return true;\n if (latestPart < currentPart) return false;\n }\n return false;\n } catch (error: unknown) {\n logger.debug('Version comparison failed:', {\n error: getErrorMessage(error),\n current,\n latest,\n });\n return false;\n }\n }\n\n /**\n * Display update notification\n */\n private static displayUpdateNotification(\n current: string,\n latest: string\n ): void {\n console.log('\\n' + '\u2500'.repeat(60));\n console.log('\uD83D\uDCE6 StackMemory Update Available!');\n console.log(` Current: v${current}`);\n console.log(` Latest: v${latest}`);\n console.log('\\n Update with:');\n console.log(' npm install -g @stackmemoryai/stackmemory@latest');\n console.log('\u2500'.repeat(60) + '\\n');\n }\n\n /**\n * Load update cache\n */\n private static loadCache(): UpdateCache | null {\n try {\n if (!existsSync(this.CACHE_FILE)) {\n return null;\n }\n\n const data = readFileSync(this.CACHE_FILE, 'utf-8');\n const cache = JSON.parse(data) as UpdateCache;\n\n // Validate cache structure\n if (\n typeof cache.lastChecked !== 'number' ||\n typeof cache.latestVersion !== 'string' ||\n typeof cache.currentVersion !== 'string'\n ) {\n logger.debug('Invalid cache format, ignoring');\n return null;\n }\n\n return cache;\n } catch (error: unknown) {\n // Cache errors should not interrupt operation\n const wrappedError = wrapError(\n error,\n 'Failed to load update cache',\n ErrorCode.INTERNAL_ERROR,\n { cacheFile: this.CACHE_FILE }\n );\n logger.debug('Failed to load update cache:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n return null;\n }\n }\n\n /**\n * Save update cache\n */\n private static saveCache(cache: UpdateCache): void {\n try {\n const dir = join(homedir(), '.stackmemory');\n\n // Create directory if it doesn't exist (safer than execSync)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o755 });\n }\n\n // Write cache with atomic operation (write to temp, then rename)\n const tempFile = `${this.CACHE_FILE}.tmp`;\n writeFileSync(tempFile, JSON.stringify(cache, null, 2), {\n mode: 0o644,\n });\n\n // Atomic rename\n if (existsSync(this.CACHE_FILE)) {\n writeFileSync(this.CACHE_FILE, JSON.stringify(cache, null, 2));\n } else {\n writeFileSync(this.CACHE_FILE, JSON.stringify(cache, null, 2));\n }\n } catch (error: unknown) {\n // Cache save errors should not interrupt operation\n const wrappedError = wrapError(\n error,\n 'Failed to save update cache',\n ErrorCode.INTERNAL_ERROR,\n { cacheFile: this.CACHE_FILE, cache }\n );\n logger.debug('Failed to save update cache:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n }\n }\n\n /**\n * Force check for updates (ignores cache)\n */\n static async forceCheck(currentVersion: string): Promise<void> {\n try {\n const latestVersion = await this.fetchLatestVersion();\n\n // Update cache\n this.saveCache({\n lastChecked: Date.now(),\n latestVersion,\n currentVersion,\n });\n\n if (latestVersion) {\n if (this.isNewerVersion(currentVersion, latestVersion)) {\n this.displayUpdateNotification(currentVersion, latestVersion);\n } else {\n console.log(`\u2705 StackMemory is up to date (v${currentVersion})`);\n }\n }\n } catch (error: unknown) {\n console.error('\u274C Update check failed:', (error as Error).message);\n }\n }\n}\n"],
5
- "mappings": "AAKA,SAAS,gBAAgB;AACzB,SAAS,YAAY,cAAc,eAAe,iBAAiB;AACnE,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,aAAa,uBAAuB;AAQtC,MAAM,cAAc;AAAA,EACzB,OAAe,aAAa;AAAA,IAC1B,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAe,iBAAiB,KAAK,KAAK,KAAK;AAAA;AAAA,EAC/C,OAAe,eAAe;AAAA;AAAA;AAAA;AAAA,EAK9B,aAAa,gBACX,gBACA,SAAS,OACM;AACf,QAAI;AAEF,YAAM,QAAQ,KAAK,UAAU;AAC7B,YAAM,MAAM,KAAK,IAAI;AAGrB,UAAI,SAAS,MAAM,MAAM,cAAc,KAAK,gBAAgB;AAC1D,YACE,CAAC,UACD,MAAM,iBACN,MAAM,kBAAkB,gBACxB;AACA,eAAK,0BAA0B,gBAAgB,MAAM,aAAa;AAAA,QACpE;AACA;AAAA,MACF;AAGA,YAAM,gBAAgB,MAAM,KAAK,mBAAmB;AAGpD,WAAK,UAAU;AAAA,QACb,aAAa;AAAA,QACb;AAAA,QACA;AAAA,MACF,CAAC;AAGD,UACE,CAAC,UACD,iBACA,KAAK,eAAe,gBAAgB,aAAa,GACjD;AACA,aAAK,0BAA0B,gBAAgB,aAAa;AAAA,MAC9D;AAAA,IACF,SAAS,OAAgB;AAEvB,YAAM,eAAe;AAAA,QACnB;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,EAAE,gBAAgB,OAAO;AAAA,MAC3B;AACA,aAAO,MAAM,wBAAwB;AAAA,QACnC,OAAO,gBAAgB,KAAK;AAAA,QAC5B,SAAS,aAAa;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAqB,qBAAsC;AACzD,QAAI;AAEF,YAAM,eAAe,YAAY;AAC/B,cAAM,SAAS,SAAS,YAAY,KAAK,YAAY,YAAY;AAAA,UAC/D,UAAU;AAAA,UACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ;AAAA,UAChC,SAAS;AAAA;AAAA,QACX,CAAC,EAAE,KAAK;AACR,eAAO;AAAA,MACT;AAGA,aAAO,MAAM;AAAA,QACX,MAAM,YAAY,cAAc,KAAM,sBAAsB;AAAA,QAC5D;AAAA,QACA,EAAE,WAAW,sBAAsB,SAAS,KAAK,aAAa;AAAA,MAChE;AAAA,IACF,SAAS,OAAgB;AACvB,YAAM,eAAe;AAAA,QACnB;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,EAAE,SAAS,KAAK,aAAa;AAAA,MAC/B;AACA,aAAO,MAAM,mCAAmC;AAAA,QAC9C,OAAO,gBAAgB,KAAK;AAAA,QAC5B,SAAS,aAAa;AAAA,MACxB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,eAAe,SAAiB,QAAyB;AACtE,QAAI;AACF,YAAM,eAAe,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM;AAClD,YAAM,cAAc,OAAO,MAAM,GAAG,EAAE,IAAI,MAAM;AAGhD,UAAI,aAAa,KAAK,KAAK,KAAK,YAAY,KAAK,KAAK,GAAG;AACvD,eAAO,MAAM,2BAA2B,EAAE,SAAS,OAAO,CAAC;AAC3D,eAAO;AAAA,MACT;AAEA,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,cAAM,aAAa,YAAY,CAAC,KAAK;AACrC,cAAM,cAAc,aAAa,CAAC,KAAK;AACvC,YAAI,aAAa,YAAa,QAAO;AACrC,YAAI,aAAa,YAAa,QAAO;AAAA,MACvC;AACA,aAAO;AAAA,IACT,SAAS,OAAgB;AACvB,aAAO,MAAM,8BAA8B;AAAA,QACzC,OAAO,gBAAgB,KAAK;AAAA,QAC5B;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,0BACb,SACA,QACM;AACN,YAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AACjC,YAAQ,IAAI,yCAAkC;AAC9C,YAAQ,IAAI,gBAAgB,OAAO,EAAE;AACrC,YAAQ,IAAI,gBAAgB,MAAM,EAAE;AACpC,YAAQ,IAAI,mBAAmB;AAC/B,YAAQ,IAAI,qDAAqD;AACjE,YAAQ,IAAI,SAAI,OAAO,EAAE,IAAI,IAAI;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,YAAgC;AAC7C,QAAI;AACF,UAAI,CAAC,WAAW,KAAK,UAAU,GAAG;AAChC,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,aAAa,KAAK,YAAY,OAAO;AAClD,YAAM,QAAQ,KAAK,MAAM,IAAI;AAG7B,UACE,OAAO,MAAM,gBAAgB,YAC7B,OAAO,MAAM,kBAAkB,YAC/B,OAAO,MAAM,mBAAmB,UAChC;AACA,eAAO,MAAM,gCAAgC;AAC7C,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,SAAS,OAAgB;AAEvB,YAAM,eAAe;AAAA,QACnB;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,EAAE,WAAW,KAAK,WAAW;AAAA,MAC/B;AACA,aAAO,MAAM,gCAAgC;AAAA,QAC3C,OAAO,gBAAgB,KAAK;AAAA,QAC5B,SAAS,aAAa;AAAA,MACxB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,UAAU,OAA0B;AACjD,QAAI;AACF,YAAM,MAAM,KAAK,QAAQ,GAAG,cAAc;AAG1C,UAAI,CAAC,WAAW,GAAG,GAAG;AACpB,kBAAU,KAAK,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAAA,MACjD;AAGA,YAAM,WAAW,GAAG,KAAK,UAAU;AACnC,oBAAc,UAAU,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG;AAAA,QACtD,MAAM;AAAA,MACR,CAAC;AAGD,UAAI,WAAW,KAAK,UAAU,GAAG;AAC/B,sBAAc,KAAK,YAAY,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,MAC/D,OAAO;AACL,sBAAc,KAAK,YAAY,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,MAC/D;AAAA,IACF,SAAS,OAAgB;AAEvB,YAAM,eAAe;AAAA,QACnB;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,EAAE,WAAW,KAAK,YAAY,MAAM;AAAA,MACtC;AACA,aAAO,MAAM,gCAAgC;AAAA,QAC3C,OAAO,gBAAgB,KAAK;AAAA,QAC5B,SAAS,aAAa;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAAW,gBAAuC;AAC7D,QAAI;AACF,YAAM,gBAAgB,MAAM,KAAK,mBAAmB;AAGpD,WAAK,UAAU;AAAA,QACb,aAAa,KAAK,IAAI;AAAA,QACtB;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,eAAe;AACjB,YAAI,KAAK,eAAe,gBAAgB,aAAa,GAAG;AACtD,eAAK,0BAA0B,gBAAgB,aAAa;AAAA,QAC9D,OAAO;AACL,kBAAQ,IAAI,sCAAiC,cAAc,GAAG;AAAA,QAChE;AAAA,MACF;AAAA,IACF,SAAS,OAAgB;AACvB,cAAQ,MAAM,+BAA2B,MAAgB,OAAO;AAAA,IAClE;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["/**\n * Update checker for StackMemory\n * Checks npm registry for newer versions\n */\n\nimport { execSync, execFileSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { logger } from '../monitoring/logger.js';\nimport {\n SystemError,\n ErrorCode,\n getErrorMessage,\n wrapError,\n} from '../errors/index.js';\nimport { withTimeout, gracefulDegrade } from '../errors/recovery.js';\n\ninterface UpdateCache {\n lastChecked: number;\n latestVersion: string;\n currentVersion: string;\n}\n\nexport class UpdateChecker {\n private static CACHE_FILE = join(\n homedir(),\n '.stackmemory',\n 'update-check.json'\n );\n private static CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours\n private static PACKAGE_NAME = '@stackmemoryai/stackmemory';\n\n /**\n * Check for updates and display notification if needed\n */\n static async checkForUpdates(\n currentVersion: string,\n silent = false\n ): Promise<void> {\n try {\n // Check cache first\n const cache = this.loadCache();\n const now = Date.now();\n\n // Skip check if we checked recently\n if (cache && now - cache.lastChecked < this.CHECK_INTERVAL) {\n if (\n !silent &&\n cache.latestVersion &&\n cache.latestVersion !== currentVersion\n ) {\n this.displayUpdateNotification(currentVersion, cache.latestVersion);\n }\n return;\n }\n\n // Fetch latest version from npm\n const latestVersion = await this.fetchLatestVersion();\n\n // Update cache\n this.saveCache({\n lastChecked: now,\n latestVersion,\n currentVersion,\n });\n\n // Display notification if update available\n if (\n !silent &&\n latestVersion &&\n this.isNewerVersion(currentVersion, latestVersion)\n ) {\n this.displayUpdateNotification(currentVersion, latestVersion);\n }\n } catch (error: unknown) {\n // Log the error with proper context but don't interrupt user workflow\n const wrappedError = wrapError(\n error,\n 'Update check failed',\n ErrorCode.INTERNAL_ERROR,\n { currentVersion, silent }\n );\n logger.debug('Update check failed:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n }\n }\n\n /**\n * Fetch latest version from npm registry\n */\n private static async fetchLatestVersion(): Promise<string> {\n try {\n // Use timeout to prevent hanging on slow network\n const fetchVersion = async () => {\n const output = execFileSync('npm', ['view', this.PACKAGE_NAME, 'version'], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'ignore'],\n timeout: 5000, // 5 second timeout\n }).trim();\n return output;\n };\n\n // Wrap with timeout and graceful degradation\n return await gracefulDegrade(\n () => withTimeout(fetchVersion, 5000, 'npm registry timeout'),\n '',\n { operation: 'fetchLatestVersion', package: this.PACKAGE_NAME }\n );\n } catch (error: unknown) {\n const wrappedError = wrapError(\n error,\n 'Failed to fetch latest version from npm',\n ErrorCode.SERVICE_UNAVAILABLE,\n { package: this.PACKAGE_NAME }\n );\n logger.debug('Failed to fetch latest version:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n return '';\n }\n }\n\n /**\n * Compare version strings\n */\n private static isNewerVersion(current: string, latest: string): boolean {\n try {\n const currentParts = current.split('.').map(Number);\n const latestParts = latest.split('.').map(Number);\n\n // Handle malformed version strings\n if (currentParts.some(isNaN) || latestParts.some(isNaN)) {\n logger.debug('Invalid version format:', { current, latest });\n return false;\n }\n\n for (let i = 0; i < 3; i++) {\n const latestPart = latestParts[i] ?? 0;\n const currentPart = currentParts[i] ?? 0;\n if (latestPart > currentPart) return true;\n if (latestPart < currentPart) return false;\n }\n return false;\n } catch (error: unknown) {\n logger.debug('Version comparison failed:', {\n error: getErrorMessage(error),\n current,\n latest,\n });\n return false;\n }\n }\n\n /**\n * Display update notification\n */\n private static displayUpdateNotification(\n current: string,\n latest: string\n ): void {\n console.log('\\n' + '\u2500'.repeat(60));\n console.log('\uD83D\uDCE6 StackMemory Update Available!');\n console.log(` Current: v${current}`);\n console.log(` Latest: v${latest}`);\n console.log('\\n Update with:');\n console.log(' npm install -g @stackmemoryai/stackmemory@latest');\n console.log('\u2500'.repeat(60) + '\\n');\n }\n\n /**\n * Load update cache\n */\n private static loadCache(): UpdateCache | null {\n try {\n if (!existsSync(this.CACHE_FILE)) {\n return null;\n }\n\n const data = readFileSync(this.CACHE_FILE, 'utf-8');\n const cache = JSON.parse(data) as UpdateCache;\n\n // Validate cache structure\n if (\n typeof cache.lastChecked !== 'number' ||\n typeof cache.latestVersion !== 'string' ||\n typeof cache.currentVersion !== 'string'\n ) {\n logger.debug('Invalid cache format, ignoring');\n return null;\n }\n\n return cache;\n } catch (error: unknown) {\n // Cache errors should not interrupt operation\n const wrappedError = wrapError(\n error,\n 'Failed to load update cache',\n ErrorCode.INTERNAL_ERROR,\n { cacheFile: this.CACHE_FILE }\n );\n logger.debug('Failed to load update cache:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n return null;\n }\n }\n\n /**\n * Save update cache\n */\n private static saveCache(cache: UpdateCache): void {\n try {\n const dir = join(homedir(), '.stackmemory');\n\n // Create directory if it doesn't exist (safer than execSync)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o755 });\n }\n\n // Write cache with atomic operation (write to temp, then rename)\n const tempFile = `${this.CACHE_FILE}.tmp`;\n writeFileSync(tempFile, JSON.stringify(cache, null, 2), {\n mode: 0o644,\n });\n\n // Atomic rename\n if (existsSync(this.CACHE_FILE)) {\n writeFileSync(this.CACHE_FILE, JSON.stringify(cache, null, 2));\n } else {\n writeFileSync(this.CACHE_FILE, JSON.stringify(cache, null, 2));\n }\n } catch (error: unknown) {\n // Cache save errors should not interrupt operation\n const wrappedError = wrapError(\n error,\n 'Failed to save update cache',\n ErrorCode.INTERNAL_ERROR,\n { cacheFile: this.CACHE_FILE, cache }\n );\n logger.debug('Failed to save update cache:', {\n error: getErrorMessage(error),\n context: wrappedError.context,\n });\n }\n }\n\n /**\n * Force check for updates (ignores cache)\n */\n static async forceCheck(currentVersion: string): Promise<void> {\n try {\n const latestVersion = await this.fetchLatestVersion();\n\n // Update cache\n this.saveCache({\n lastChecked: Date.now(),\n latestVersion,\n currentVersion,\n });\n\n if (latestVersion) {\n if (this.isNewerVersion(currentVersion, latestVersion)) {\n this.displayUpdateNotification(currentVersion, latestVersion);\n } else {\n console.log(`\u2705 StackMemory is up to date (v${currentVersion})`);\n }\n }\n } catch (error: unknown) {\n console.error('\u274C Update check failed:', (error as Error).message);\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,16 @@
1
+ class ClaudeCodeSubagentClient {
2
+ async executeSubagent(request) {
3
+ return {
4
+ success: true,
5
+ result: {
6
+ message: `Stub execution of ${request.type} agent`,
7
+ task: request.task
8
+ },
9
+ tokens: 100
10
+ };
11
+ }
12
+ }
13
+ export {
14
+ ClaudeCodeSubagentClient
15
+ };
16
+ //# sourceMappingURL=subagent-client-stub.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/integrations/claude-code/subagent-client-stub.ts"],
4
+ "sourcesContent": ["/**\n * Stub implementation of ClaudeCodeSubagentClient for testing\n * Used when child_process is not available (e.g., in tests)\n */\n\nexport interface SubagentRequest {\n type: string;\n task: string;\n context: Record<string, any>;\n}\n\nexport interface SubagentResponse {\n success: boolean;\n result: any;\n error?: string;\n tokens?: number;\n}\n\nexport class ClaudeCodeSubagentClient {\n async executeSubagent(request: SubagentRequest): Promise<SubagentResponse> {\n // Stub implementation for testing\n return {\n success: true,\n result: {\n message: `Stub execution of ${request.type} agent`,\n task: request.task,\n },\n tokens: 100,\n };\n }\n}"],
5
+ "mappings": "AAkBO,MAAM,yBAAyB;AAAA,EACpC,MAAM,gBAAgB,SAAqD;AAEzE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,SAAS,qBAAqB,QAAQ,IAAI;AAAA,QAC1C,MAAM,QAAQ;AAAA,MAChB;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -671,6 +671,54 @@ class ClaudeSkillsManager {
671
671
  }
672
672
  case "dig":
673
673
  return this.archaeologistSkill.dig(args[0], options);
674
+ case "lint":
675
+ if (!this.rlmOrchestrator) {
676
+ return {
677
+ success: false,
678
+ message: "RLM Orchestrator not initialized. Please wait a moment and try again."
679
+ };
680
+ }
681
+ const lintPath = args[0] || process.cwd();
682
+ const lintOptions = {
683
+ ...options,
684
+ // Force use of linting agent
685
+ agents: ["linting"],
686
+ maxParallel: 1,
687
+ reviewStages: 1,
688
+ verboseLogging: true
689
+ };
690
+ 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.`;
691
+ try {
692
+ const result = await this.rlmOrchestrator.execute(
693
+ lintTask,
694
+ { path: lintPath, ...options },
695
+ lintOptions
696
+ );
697
+ return {
698
+ success: result.success,
699
+ message: `Linting ${result.success ? "completed" : "failed"}`,
700
+ data: {
701
+ issuesFound: result.issuesFound,
702
+ issuesFixed: result.issuesFixed,
703
+ duration: `${result.duration}ms`,
704
+ totalTokens: result.totalTokens,
705
+ details: result.rootNode
706
+ }
707
+ };
708
+ } catch (error) {
709
+ return {
710
+ success: false,
711
+ message: `Linting failed: ${error.message}`
712
+ };
713
+ }
714
+ case "rlm":
715
+ if (!this.rlmOrchestrator) {
716
+ return {
717
+ success: false,
718
+ message: "RLM Orchestrator not initialized. Please wait a moment and try again."
719
+ };
720
+ }
721
+ return this.rlmOrchestrator.execute(args[0], options);
674
722
  case "repo":
675
723
  case "ingest":
676
724
  if (!this.repoIngestionSkill) {
@@ -759,7 +807,6 @@ class ClaudeSkillsManager {
759
807
  action: "open-browser"
760
808
  };
761
809
  }
762
- case "rlm":
763
810
  case "recursive":
764
811
  if (!this.rlmOrchestrator) {
765
812
  return {
@@ -813,7 +860,7 @@ class ClaudeSkillsManager {
813
860
  skills.push("repo");
814
861
  }
815
862
  if (this.rlmOrchestrator) {
816
- skills.push("rlm");
863
+ skills.push("rlm", "lint");
817
864
  }
818
865
  return skills;
819
866
  }
@@ -836,6 +883,54 @@ Create and manage recovery points
836
883
  return `
837
884
  /dig "query" [--depth 6months] [--patterns] [--decisions] [--timeline]
838
885
  Deep historical context retrieval across sessions
886
+ `;
887
+ case "lint":
888
+ return `
889
+ /lint [path] [options]
890
+ Perform comprehensive code linting and quality checks
891
+
892
+ Automatically checks for:
893
+ - Syntax errors and type issues
894
+ - Code formatting and style violations
895
+ - Security vulnerabilities
896
+ - Performance anti-patterns
897
+ - Unused imports and dead code
898
+ - Code smells and complexity issues
899
+
900
+ Usage:
901
+ stackmemory skills lint # Lint current directory
902
+ stackmemory skills lint src/ # Lint specific directory
903
+ stackmemory skills lint src/file.ts # Lint specific file
904
+
905
+ Options:
906
+ --fix Automatically fix issues where possible
907
+ --format Focus on formatting issues
908
+ --security Focus on security vulnerabilities
909
+ --performance Focus on performance issues
910
+ --verbose Show detailed output
911
+
912
+ Examples:
913
+ stackmemory skills lint --fix
914
+ stackmemory skills lint src/ --security --verbose
915
+ `;
916
+ case "rlm":
917
+ return `
918
+ /rlm "task description" [options]
919
+ Execute complex tasks with recursive agent orchestration
920
+
921
+ Options:
922
+ --max-parallel <n> Max concurrent subagents (default: 5)
923
+ --max-recursion <n> Max recursion depth (default: 4)
924
+ --max-tokens-per-agent <n> Token budget per agent (default: 30000)
925
+ --review-stages <n> Review iterations (default: 3)
926
+ --quality-threshold <n> Target quality 0-1 (default: 0.85)
927
+ --test-mode <mode> unit/integration/e2e/all (default: all)
928
+ --verbose Show all operations
929
+ --timeout-per-agent <s> Timeout in seconds (default: 300)
930
+
931
+ Examples:
932
+ stackmemory skills rlm "Generate tests for API endpoints"
933
+ stackmemory skills rlm "Refactor auth system" --quality-threshold 0.95
839
934
  `;
840
935
  case "dashboard":
841
936
  return `
@@ -866,7 +961,6 @@ Options:
866
961
  - --language: Filter search by programming language
867
962
  - --limit: Maximum search results (default: 20)
868
963
  `;
869
- case "rlm":
870
964
  case "recursive":
871
965
  return `
872
966
  /rlm "task description" [options]