@stackmemoryai/stackmemory 0.5.64 → 0.5.67

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 (66) hide show
  1. package/README.md +69 -346
  2. package/bin/claude-sm +1 -1
  3. package/bin/claude-smd +1 -1
  4. package/bin/codex-sm +6 -0
  5. package/bin/codex-smd +1 -1
  6. package/bin/opencode-sm +1 -1
  7. package/dist/src/cli/claude-sm.js +162 -25
  8. package/dist/src/cli/claude-sm.js.map +2 -2
  9. package/dist/src/cli/commands/ping.js +14 -0
  10. package/dist/src/cli/commands/ping.js.map +7 -0
  11. package/dist/src/cli/commands/ralph.js +103 -1
  12. package/dist/src/cli/commands/ralph.js.map +2 -2
  13. package/dist/src/cli/commands/retrieval.js +1 -1
  14. package/dist/src/cli/commands/retrieval.js.map +2 -2
  15. package/dist/src/cli/commands/skills.js +300 -1
  16. package/dist/src/cli/commands/skills.js.map +2 -2
  17. package/dist/src/cli/index.js +362 -20
  18. package/dist/src/cli/index.js.map +2 -2
  19. package/dist/src/core/digest/types.js +1 -1
  20. package/dist/src/core/digest/types.js.map +1 -1
  21. package/dist/src/core/extensions/provider-adapter.js +2 -5
  22. package/dist/src/core/extensions/provider-adapter.js.map +2 -2
  23. package/dist/src/core/retrieval/llm-provider.js +2 -2
  24. package/dist/src/core/retrieval/llm-provider.js.map +1 -1
  25. package/dist/src/core/retrieval/types.js +1 -1
  26. package/dist/src/core/retrieval/types.js.map +1 -1
  27. package/dist/src/features/sweep/pty-wrapper.js +15 -5
  28. package/dist/src/features/sweep/pty-wrapper.js.map +2 -2
  29. package/dist/src/features/workers/tmux-manager.js +71 -0
  30. package/dist/src/features/workers/tmux-manager.js.map +7 -0
  31. package/dist/src/features/workers/worker-registry.js +52 -0
  32. package/dist/src/features/workers/worker-registry.js.map +7 -0
  33. package/dist/src/integrations/linear/webhook-handler.js +82 -0
  34. package/dist/src/integrations/linear/webhook-handler.js.map +2 -2
  35. package/dist/src/integrations/mcp/pending-utils.js +33 -0
  36. package/dist/src/integrations/mcp/pending-utils.js.map +7 -0
  37. package/dist/src/integrations/mcp/server.js +571 -1
  38. package/dist/src/integrations/mcp/server.js.map +2 -2
  39. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +2 -2
  40. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js.map +2 -2
  41. package/dist/src/orchestrators/multimodal/constants.js +17 -0
  42. package/dist/src/orchestrators/multimodal/constants.js.map +7 -0
  43. package/dist/src/orchestrators/multimodal/harness.js +292 -0
  44. package/dist/src/orchestrators/multimodal/harness.js.map +7 -0
  45. package/dist/src/orchestrators/multimodal/providers.js +98 -0
  46. package/dist/src/orchestrators/multimodal/providers.js.map +7 -0
  47. package/dist/src/orchestrators/multimodal/types.js +5 -0
  48. package/dist/src/orchestrators/multimodal/types.js.map +7 -0
  49. package/dist/src/orchestrators/multimodal/utils.js +25 -0
  50. package/dist/src/orchestrators/multimodal/utils.js.map +7 -0
  51. package/dist/src/skills/claude-skills.js +116 -1
  52. package/dist/src/skills/claude-skills.js.map +2 -2
  53. package/dist/src/skills/linear-task-runner.js +262 -0
  54. package/dist/src/skills/linear-task-runner.js.map +7 -0
  55. package/dist/src/skills/recursive-agent-orchestrator.js +114 -85
  56. package/dist/src/skills/recursive-agent-orchestrator.js.map +2 -2
  57. package/dist/src/skills/spec-generator-skill.js +441 -0
  58. package/dist/src/skills/spec-generator-skill.js.map +7 -0
  59. package/package.json +14 -9
  60. package/scripts/claude-code-wrapper.sh +18 -30
  61. package/scripts/demos/ralph-integration-demo.ts +14 -13
  62. package/scripts/demos/trace-demo.ts +7 -21
  63. package/scripts/demos/trace-test.ts +20 -8
  64. package/scripts/install-claude-hooks.sh +2 -2
  65. package/scripts/verify-dist.cjs +83 -0
  66. package/templates/claude-hooks/post-edit-sweep.js +7 -10
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/skills/spec-generator-skill.ts"],
4
+ "sourcesContent": ["/**\n * Spec Generator Skill\n * Generates iterative spec documents: ONE_PAGER \u2192 DEV_SPEC \u2192 PROMPT_PLAN \u2192 AGENTS.md\n * Progressive context \u2014 later docs read earlier ones from disk.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { SkillContext, SkillResult } from './claude-skills.js';\nimport { logger } from '../core/monitoring/logger.js';\n\nexport type SpecType = 'one-pager' | 'dev-spec' | 'prompt-plan' | 'agents';\n\ninterface SpecConfig {\n filename: string;\n title: string;\n sections: string[];\n inputs: SpecType[]; // earlier docs this type reads\n}\n\nconst SPEC_DIR = 'docs/specs';\n\nconst SPEC_CONFIGS: Record<SpecType, SpecConfig> = {\n 'one-pager': {\n filename: 'ONE_PAGER.md',\n title: 'One-Pager',\n sections: [\n 'Problem',\n 'Audience',\n 'Platform',\n 'Core Flow',\n 'MVP Features',\n 'Non-Goals',\n 'Metrics',\n ],\n inputs: [],\n },\n 'dev-spec': {\n filename: 'DEV_SPEC.md',\n title: 'Development Specification',\n sections: [\n 'Architecture',\n 'Tech Stack',\n 'API Contracts',\n 'Data Models',\n 'Auth',\n 'Error Handling',\n 'Deployment',\n ],\n inputs: ['one-pager'],\n },\n 'prompt-plan': {\n filename: 'PROMPT_PLAN.md',\n title: 'Prompt Plan',\n sections: [\n 'Stage A: Project Setup',\n 'Stage B: Core Data Models',\n 'Stage C: API Layer',\n 'Stage D: Business Logic',\n 'Stage E: Frontend / UI',\n 'Stage F: Integration & Testing',\n 'Stage G: Deploy & Polish',\n ],\n inputs: ['one-pager', 'dev-spec'],\n },\n agents: {\n filename: 'AGENTS.md',\n title: 'AGENTS.md',\n sections: [\n 'Repo Files',\n 'Responsibilities',\n 'Guardrails',\n 'Testing',\n 'When to Ask',\n ],\n inputs: ['one-pager', 'dev-spec', 'prompt-plan'],\n },\n};\n\n// --- Templates ---\n\nfunction onePagerTemplate(title: string): string {\n return `# ${title} \u2014 One-Pager\n\n## Problem\n<!-- What problem does this solve? Who has this problem? -->\n\n## Audience\n<!-- Primary users and their context -->\n\n## Platform\n<!-- Web / Mobile / CLI / API \u2014 and why -->\n\n## Core Flow\n<!-- Happy-path user journey in 3-5 steps -->\n1.\n2.\n3.\n\n## MVP Features\n<!-- Minimum set of features for first release -->\n- [ ]\n- [ ]\n- [ ]\n\n## Non-Goals\n<!-- Explicitly out of scope for MVP -->\n-\n\n## Metrics\n<!-- How will you measure success? -->\n-\n`;\n}\n\nfunction devSpecTemplate(title: string, onePagerContent: string): string {\n return `# ${title} \u2014 Development Specification\n\n> Generated from ONE_PAGER.md\n\n<details><summary>Source: ONE_PAGER.md</summary>\n\n${onePagerContent}\n\n</details>\n\n## Architecture\n<!-- High-level system diagram / component breakdown -->\n\n## Tech Stack\n<!-- Languages, frameworks, databases, infra -->\n| Layer | Choice | Rationale |\n|-------|--------|-----------|\n| Frontend | | |\n| Backend | | |\n| Database | | |\n| Hosting | | |\n\n## API Contracts\n<!-- Key endpoints with request/response shapes -->\n\n## Data Models\n<!-- Core entities and relationships -->\n\n## Auth\n<!-- Authentication and authorization strategy -->\n\n## Error Handling\n<!-- Error codes, retry strategies, user-facing messages -->\n\n## Deployment\n<!-- CI/CD, environments, rollback strategy -->\n`;\n}\n\nfunction promptPlanTemplate(\n title: string,\n onePagerContent: string,\n devSpecContent: string\n): string {\n return `# ${title} \u2014 Prompt Plan\n\n> Generated from ONE_PAGER.md and DEV_SPEC.md\n> Each stage has TDD checkboxes \u2014 check off as tasks complete.\n\n<details><summary>Source: ONE_PAGER.md</summary>\n\n${onePagerContent}\n\n</details>\n\n<details><summary>Source: DEV_SPEC.md</summary>\n\n${devSpecContent}\n\n</details>\n\n## Stage A: Project Setup\n- [ ] Initialize repository and tooling\n- [ ] Configure CI/CD pipeline\n- [ ] Set up development environment\n\n## Stage B: Core Data Models\n- [ ] Define database schema\n- [ ] Create model layer\n- [ ] Write model tests\n\n## Stage C: API Layer\n- [ ] Implement API endpoints\n- [ ] Add input validation\n- [ ] Write API tests\n\n## Stage D: Business Logic\n- [ ] Implement core business rules\n- [ ] Add edge case handling\n- [ ] Write integration tests\n\n## Stage E: Frontend / UI\n- [ ] Build core UI components\n- [ ] Implement user flows\n- [ ] Write UI tests\n\n## Stage F: Integration & Testing\n- [ ] End-to-end test suite\n- [ ] Performance testing\n- [ ] Security audit\n\n## Stage G: Deploy & Polish\n- [ ] Production deployment\n- [ ] Monitoring and alerting\n- [ ] Documentation\n`;\n}\n\nfunction agentsTemplate(title: string, inputs: Record<string, string>): string {\n const sourceBlocks = Object.entries(inputs)\n .map(\n ([name, content]) =>\n `<details><summary>Source: ${name}</summary>\\n\\n${content}\\n\\n</details>`\n )\n .join('\\n\\n');\n\n return `# ${title} \u2014 AGENTS.md\n\n> Auto-generated agent configuration for Claude Code / Cursor / Windsurf.\n\n${sourceBlocks}\n\n## Repo Files\n<!-- Key files and their purpose -->\n| File | Purpose |\n|------|---------|\n| | |\n\n## Responsibilities\n<!-- What this agent should and shouldn't do -->\n### DO\n-\n\n### DON'T\n-\n\n## Guardrails\n<!-- Safety constraints and limits -->\n- Never commit secrets or credentials\n- Always run tests before committing\n- Keep changes focused and atomic\n\n## Testing\n<!-- How to validate changes -->\n\\`\\`\\`bash\nnpm test\nnpm run lint\nnpm run build\n\\`\\`\\`\n\n## When to Ask\n<!-- Situations where the agent should ask for human input -->\n- Architectural changes affecting multiple systems\n- Security-sensitive modifications\n- Breaking API changes\n- Ambiguous requirements\n`;\n}\n\n// --- Skill Class ---\n\nexport class SpecGeneratorSkill {\n private baseDir: string;\n\n constructor(private context: SkillContext) {\n this.baseDir = process.cwd();\n }\n\n /** Generate a spec document by type */\n async generate(\n type: SpecType,\n title: string,\n opts?: { force?: boolean }\n ): Promise<SkillResult> {\n const config = SPEC_CONFIGS[type];\n if (!config) {\n return { success: false, message: `Unknown spec type: ${type}` };\n }\n\n const specDir = path.join(this.baseDir, SPEC_DIR);\n const outputPath = path.join(specDir, config.filename);\n\n // Check if file already exists\n if (fs.existsSync(outputPath) && !opts?.force) {\n return {\n success: false,\n message: `${config.filename} already exists. Use --force to overwrite.`,\n data: { path: outputPath },\n };\n }\n\n // Load input documents (progressive context)\n const inputContents: Record<string, string> = {};\n for (const inputType of config.inputs) {\n const inputConfig = SPEC_CONFIGS[inputType];\n const inputPath = path.join(specDir, inputConfig.filename);\n if (fs.existsSync(inputPath)) {\n inputContents[inputConfig.filename] = fs.readFileSync(\n inputPath,\n 'utf-8'\n );\n }\n }\n\n // Generate content from template\n const content = this.renderTemplate(type, title, inputContents);\n\n // Write file\n fs.mkdirSync(specDir, { recursive: true });\n fs.writeFileSync(outputPath, content, 'utf-8');\n\n logger.info(`Generated spec: ${config.filename}`, { type, title });\n\n return {\n success: true,\n message: `Created ${config.filename}`,\n data: {\n path: outputPath,\n type,\n sections: config.sections,\n inputsUsed: Object.keys(inputContents),\n },\n action: `Generated ${SPEC_DIR}/${config.filename}`,\n };\n }\n\n /** List existing spec documents */\n async list(): Promise<SkillResult> {\n const specDir = path.join(this.baseDir, SPEC_DIR);\n const specs: Array<{\n type: SpecType;\n filename: string;\n exists: boolean;\n path: string;\n }> = [];\n\n for (const [type, config] of Object.entries(SPEC_CONFIGS)) {\n const filePath = path.join(specDir, config.filename);\n specs.push({\n type: type as SpecType,\n filename: config.filename,\n exists: fs.existsSync(filePath),\n path: filePath,\n });\n }\n\n const existing = specs.filter((s) => s.exists);\n const missing = specs.filter((s) => !s.exists);\n\n return {\n success: true,\n message: `${existing.length}/${specs.length} specs exist`,\n data: { specs, existing, missing },\n };\n }\n\n /** Update a spec \u2014 primarily for checking off PROMPT_PLAN items */\n async update(filePath: string, changes: string): Promise<SkillResult> {\n const resolvedPath = path.isAbsolute(filePath)\n ? filePath\n : path.join(this.baseDir, filePath);\n\n if (!fs.existsSync(resolvedPath)) {\n return { success: false, message: `File not found: ${resolvedPath}` };\n }\n\n let content = fs.readFileSync(resolvedPath, 'utf-8');\n\n // Parse checkbox updates: \"Stage A:1\" means check item 1 in Stage A\n const checkboxPattern = /^(Stage [A-G])(?::(\\d+))?$/;\n const match = changes.match(checkboxPattern);\n\n if (match) {\n const [, stageName, itemNum] = match;\n content = this.checkItem(\n content,\n stageName,\n itemNum ? parseInt(itemNum) : undefined\n );\n } else {\n // Treat as direct checkbox text match: find \"- [ ] <changes>\" and check it\n const escaped = changes.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = new RegExp(`- \\\\[ \\\\] ${escaped}`, 'i');\n if (re.test(content)) {\n content = content.replace(re, `- [x] ${changes}`);\n } else {\n return {\n success: false,\n message: `No unchecked item matching \"${changes}\" found`,\n };\n }\n }\n\n // Append changelog entry\n const timestamp = new Date().toISOString().slice(0, 19).replace('T', ' ');\n const changelog = `\\n<!-- Updated: ${timestamp} | ${changes} -->\\n`;\n content += changelog;\n\n fs.writeFileSync(resolvedPath, content, 'utf-8');\n\n logger.info('Updated spec', { path: resolvedPath, changes });\n\n return {\n success: true,\n message: `Updated: ${changes}`,\n data: { path: resolvedPath, changes },\n action: `Checked off item in ${path.basename(resolvedPath)}`,\n };\n }\n\n /** Validate completeness of a spec */\n async validate(filePath: string): Promise<SkillResult> {\n const resolvedPath = path.isAbsolute(filePath)\n ? filePath\n : path.join(this.baseDir, filePath);\n\n if (!fs.existsSync(resolvedPath)) {\n return { success: false, message: `File not found: ${resolvedPath}` };\n }\n\n const content = fs.readFileSync(resolvedPath, 'utf-8');\n\n // Count checkboxes\n const unchecked = (content.match(/- \\[ \\]/g) || []).length;\n const checked = (content.match(/- \\[x\\]/gi) || []).length;\n const total = checked + unchecked;\n\n // Check for empty sections (## header followed by only whitespace/comments)\n const emptySections: string[] = [];\n const sectionRegex = /^## (.+)$/gm;\n let sectionMatch;\n\n while ((sectionMatch = sectionRegex.exec(content)) !== null) {\n const sectionName = sectionMatch[1];\n const sectionStart = content.indexOf(sectionMatch[0]);\n const nextSection = content.indexOf('\\n## ', sectionStart + 1);\n const sectionContent =\n nextSection === -1\n ? content.slice(sectionStart + sectionMatch[0].length)\n : content.slice(sectionStart + sectionMatch[0].length, nextSection);\n\n // Strip comments and whitespace\n const stripped = sectionContent\n .replace(/<!--.*?-->/gs, '')\n .replace(/\\s+/g, '')\n .trim();\n\n if (stripped.length === 0 || stripped === '||') {\n emptySections.push(sectionName);\n }\n }\n\n const isComplete = unchecked === 0 && emptySections.length === 0;\n\n return {\n success: true,\n message: isComplete\n ? 'Spec is complete'\n : `Spec incomplete: ${unchecked} unchecked items, ${emptySections.length} empty sections`,\n data: {\n path: resolvedPath,\n checkboxes: { checked, unchecked, total },\n emptySections,\n isComplete,\n completionPercent:\n total > 0 ? Math.round((checked / total) * 100) : 100,\n },\n };\n }\n\n // --- Private helpers ---\n\n private renderTemplate(\n type: SpecType,\n title: string,\n inputs: Record<string, string>\n ): string {\n switch (type) {\n case 'one-pager':\n return onePagerTemplate(title);\n\n case 'dev-spec':\n return devSpecTemplate(\n title,\n inputs['ONE_PAGER.md'] ||\n '*ONE_PAGER.md not found \u2014 generate it first.*'\n );\n\n case 'prompt-plan':\n return promptPlanTemplate(\n title,\n inputs['ONE_PAGER.md'] || '*ONE_PAGER.md not found*',\n inputs['DEV_SPEC.md'] ||\n '*DEV_SPEC.md not found \u2014 generate it first.*'\n );\n\n case 'agents':\n return agentsTemplate(title, inputs);\n\n default:\n return `# ${title}\\n\\nUnknown spec type: ${type}\\n`;\n }\n }\n\n /** Check off a specific checkbox item in a stage */\n private checkItem(\n content: string,\n stageName: string,\n itemIndex?: number\n ): string {\n const lines = content.split('\\n');\n let inStage = false;\n let itemCount = 0;\n\n for (let i = 0; i < lines.length; i++) {\n // Detect stage header\n if (lines[i].startsWith('## ') && lines[i].includes(stageName)) {\n inStage = true;\n itemCount = 0;\n continue;\n }\n\n // Exit stage on next header\n if (inStage && lines[i].startsWith('## ')) {\n break;\n }\n\n // Process checkbox\n if (inStage && lines[i].match(/^- \\[ \\]/)) {\n itemCount++;\n if (itemIndex === undefined || itemCount === itemIndex) {\n lines[i] = lines[i].replace('- [ ]', '- [x]');\n if (itemIndex !== undefined) break;\n }\n }\n }\n\n return lines.join('\\n');\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stackmemoryai/stackmemory",
3
- "version": "0.5.64",
4
- "description": "Lossless memory runtime for AI coding tools - call stack context, predictive edits, AI code review, prompt optimization, model switching, and mobile sync",
3
+ "version": "0.5.67",
4
+ "description": "Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, and smart retrieval.",
5
5
  "engines": {
6
6
  "node": ">=20.0.0",
7
7
  "npm": ">=10.0.0"
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "types": "dist/src/index.d.ts",
20
20
  "files": [
21
+ "bin",
21
22
  "dist",
22
23
  "scripts",
23
24
  "templates",
@@ -49,8 +50,8 @@
49
50
  "model-routing"
50
51
  ],
51
52
  "scripts": {
52
- "start": "node dist/integrations/mcp/server.js",
53
- "start:full": "node dist/integrations/mcp/server.js",
53
+ "start": "node dist/src/integrations/mcp/server.js",
54
+ "start:full": "node dist/src/integrations/mcp/server.js",
54
55
  "setup": "npm install && npm run build && npm run init",
55
56
  "postinstall": "node scripts/install-claude-hooks-auto.js || true",
56
57
  "init": "node dist/scripts/initialize.js",
@@ -65,11 +66,11 @@
65
66
  "test:run": "vitest run",
66
67
  "test:pre-publish": "./scripts/test-pre-publish-quick.sh",
67
68
  "test:pre-commit": "vitest related --run --reporter=dot --silent --bail=1",
68
- "prepublishOnly": "npm run build && npm run test:pre-publish",
69
+ "prepublishOnly": "npm run build && npm run verify:dist && npm run test:pre-publish",
69
70
  "quality": "npm run lint && npm run test:run && npm run build",
70
- "dev": "tsx watch src/mcp/mcp-server.ts",
71
- "mcp:start": "node dist/integrations/mcp/server.js",
72
- "mcp:dev": "tsx src/mcp/mcp-server.ts",
71
+ "dev": "tsx watch src/integrations/mcp/server.ts",
72
+ "mcp:start": "node dist/src/integrations/mcp/server.js",
73
+ "mcp:dev": "tsx src/integrations/mcp/server.ts",
73
74
  "status": "node dist/scripts/status.js",
74
75
  "linear:sync": "node scripts/sync-linear-graphql.js",
75
76
  "linear:mirror": "node scripts/sync-linear-graphql.js --mirror",
@@ -86,7 +87,10 @@
86
87
  "daemon:status": "node dist/cli/index.js daemon status",
87
88
  "sync:start": "node scripts/background-sync-manager.js",
88
89
  "sync:setup": "./scripts/setup-background-sync.sh",
89
- "prepare": "echo 'Prepare step completed'"
90
+ "prepare": "echo 'Prepare step completed'",
91
+ "verify:dist": "node scripts/verify-dist.cjs",
92
+ "rebuild:native": "npm rebuild better-sqlite3 || true",
93
+ "deps:reset": "rm -rf node_modules package-lock.json && npm ci"
90
94
  },
91
95
  "dependencies": {
92
96
  "@anthropic-ai/sdk": "^0.71.2",
@@ -115,6 +119,7 @@
115
119
  "inquirer": "^9.3.8",
116
120
  "msgpackr": "^1.10.1",
117
121
  "ngrok": "^5.0.0-beta.2",
122
+ "node-pty": "^1.1.0",
118
123
  "open": "^11.0.0",
119
124
  "ora": "^9.0.0",
120
125
  "pg": "^8.17.1",
@@ -3,62 +3,50 @@
3
3
  # Claude Code wrapper with StackMemory integration
4
4
  # Usage: Add alias to ~/.zshrc: alias claude='~/Dev/stackmemory/scripts/claude-code-wrapper.sh'
5
5
 
6
- # Check for auto-sync flag
6
+ # Check for auto-sync flag and filter wrapper-specific args
7
7
  AUTO_SYNC=false
8
8
  SYNC_INTERVAL=5
9
+ CLAUDE_ARGS=()
10
+
9
11
  for arg in "$@"; do
10
12
  case $arg in
11
13
  --auto-sync)
12
14
  AUTO_SYNC=true
13
- shift
14
15
  ;;
15
16
  --sync-interval=*)
16
17
  SYNC_INTERVAL="${arg#*=}"
17
- shift
18
+ ;;
19
+ *)
20
+ CLAUDE_ARGS+=("$arg")
18
21
  ;;
19
22
  esac
20
23
  done
21
24
 
22
- # Start Linear auto-sync in background if requested
23
- SYNC_PID=""
25
+ # Start Linear auto-sync in background if requested (survives exec)
24
26
  if [ "$AUTO_SYNC" = true ] && [ -n "$LINEAR_API_KEY" ]; then
25
27
  echo "🔄 Starting Linear auto-sync (${SYNC_INTERVAL}min intervals)..."
26
- (
28
+ nohup bash -c "
27
29
  while true; do
28
30
  sleep $((SYNC_INTERVAL * 60))
29
- if [ -d ".stackmemory" ]; then
31
+ if [ -d \"$PWD/.stackmemory\" ]; then
30
32
  stackmemory linear sync --quiet 2>/dev/null || true
31
33
  fi
32
34
  done
33
- ) &
34
- SYNC_PID=$!
35
+ " > /dev/null 2>&1 &
36
+ disown
35
37
  fi
36
38
 
37
- cleanup() {
38
- echo "📝 Saving StackMemory context..."
39
-
40
- # Kill auto-sync if running
41
- if [ -n "$SYNC_PID" ] && kill -0 $SYNC_PID 2>/dev/null; then
42
- echo "🛑 Stopping auto-sync..."
43
- kill $SYNC_PID 2>/dev/null || true
44
- fi
45
-
46
- # Check if in a git repo with stackmemory
47
- if [ -d ".stackmemory" ] && [ -f "stackmemory.json" ]; then
48
- # Save current context (without sync)
49
- stackmemory status 2>/dev/null || true
50
- echo "✅ StackMemory context saved"
51
- fi
52
- }
39
+ # Note: Cleanup is now handled by Claude hooks instead of this wrapper
40
+ # See: stackmemory setup-hooks --cleanup
53
41
 
54
- # Set trap for exit signals
55
- trap cleanup EXIT INT TERM
42
+ # Run Claude Code with exec for full TTY control (interactive mode)
43
+ # This replaces the shell process, ensuring stdin works properly
44
+ # Note: cleanup trap won't run with exec - use Claude hooks for session cleanup instead
56
45
 
57
- # Run Claude Code (try multiple possible command names)
58
46
  if command -v claude-code &> /dev/null; then
59
- claude-code "$@"
47
+ exec claude-code "${CLAUDE_ARGS[@]}"
60
48
  elif command -v claude &> /dev/null; then
61
- claude "$@"
49
+ exec claude "${CLAUDE_ARGS[@]}"
62
50
  else
63
51
  echo "❌ Claude Code not found. Please install it first."
64
52
  echo " Visit: https://github.com/anthropics/claude-code"
@@ -5,7 +5,6 @@
5
5
  */
6
6
 
7
7
  import { RalphStackMemoryBridge } from './bridge/ralph-stackmemory-bridge.js';
8
- import { logger } from '../../core/monitoring/logger.js';
9
8
  import { RalphStackMemoryConfig } from './types.js';
10
9
 
11
10
  class RalphIntegrationDemo {
@@ -60,9 +59,12 @@ class RalphIntegrationDemo {
60
59
  await this.demonstrateMetrics();
61
60
 
62
61
  console.log('\n✅ Demo completed successfully!\n');
63
- } catch (error: any) {
64
- console.error('\n❌ Demo failed:', error.message);
65
- throw error;
62
+ } catch (err: unknown) {
63
+ console.error(
64
+ '\n❌ Demo failed:',
65
+ err instanceof Error ? err.message : err
66
+ );
67
+ throw err;
66
68
  } finally {
67
69
  await this.cleanup();
68
70
  }
@@ -158,9 +160,6 @@ class RalphIntegrationDemo {
158
160
  console.log('\n🚑 Phase 3: Crash Recovery');
159
161
  console.log('===========================');
160
162
 
161
- // Simulate getting session ID
162
- const sessionId = 'demo-session-123';
163
-
164
163
  try {
165
164
  console.log('🔄 Simulating session rehydration...');
166
165
 
@@ -177,8 +176,10 @@ class RalphIntegrationDemo {
177
176
  console.log(' - State reconciled: 0.3s');
178
177
  console.log(' - Memory usage: 45MB');
179
178
  console.log(' - Cache hit rate: 78%');
180
- } catch (error: any) {
181
- console.log(`⚠️ Recovery simulation: ${error.message}`);
179
+ } catch (err: unknown) {
180
+ console.log(
181
+ `⚠️ Recovery simulation: ${err instanceof Error ? err.message : err}`
182
+ );
182
183
  }
183
184
  }
184
185
 
@@ -227,10 +228,10 @@ async function main() {
227
228
 
228
229
  try {
229
230
  await demo.run();
230
- } catch (error: any) {
231
- console.error('Demo failed:', error.message);
232
- if (process.env.DEBUG) {
233
- console.error(error.stack);
231
+ } catch (err: unknown) {
232
+ console.error('Demo failed:', err instanceof Error ? err.message : err);
233
+ if (process.env.DEBUG && err instanceof Error) {
234
+ console.error(err.stack);
234
235
  }
235
236
  process.exit(1);
236
237
  }
@@ -6,33 +6,17 @@
6
6
 
7
7
  import {
8
8
  trace,
9
- Trace,
10
- TraceClass,
11
9
  enableVerboseTracing,
12
10
  createTracedDatabase,
13
11
  traceStep,
14
12
  } from './index.js';
15
- import { logger } from '../monitoring/logger.js';
16
- // Type-safe environment variable access
17
- function getEnv(key: string, defaultValue?: string): string {
18
- const value = process.env[key];
19
- if (value === undefined) {
20
- if (defaultValue !== undefined) return defaultValue;
21
- throw new Error(`Environment variable ${key} is required`);
22
- }
23
- return value;
24
- }
25
-
26
- function getOptionalEnv(key: string): string | undefined {
27
- return process.env[key];
28
- }
29
13
 
30
14
  // Example class with tracing
31
15
  // @TraceClass() - decorators not enabled in tsconfig
32
16
  class ExampleService {
33
- private data: Map<string, any> = new Map();
17
+ private data: Map<string, unknown> = new Map();
34
18
 
35
- async fetchData(id: string): Promise<any> {
19
+ async fetchData(id: string): Promise<Record<string, unknown>> {
36
20
  // Simulate API call
37
21
  await this.delay(50);
38
22
 
@@ -43,7 +27,9 @@ class ExampleService {
43
27
  return { id, value: Math.random() };
44
28
  }
45
29
 
46
- async processData(data: any): Promise<any> {
30
+ async processData(
31
+ data: Record<string, unknown>
32
+ ): Promise<Record<string, unknown>> {
47
33
  return traceStep('Data validation', async () => {
48
34
  await this.delay(20);
49
35
 
@@ -62,7 +48,7 @@ class ExampleService {
62
48
  });
63
49
  }
64
50
 
65
- cacheData(key: string, value: any): void {
51
+ cacheData(key: string, value: unknown): void {
66
52
  trace.traceSync('function', 'cacheData', { key, value }, () => {
67
53
  this.data.set(key, value);
68
54
  });
@@ -161,7 +147,7 @@ async function runDemo() {
161
147
 
162
148
  try {
163
149
  await service.fetchData('error');
164
- } catch (error: unknown) {
150
+ } catch {
165
151
  console.log('Error properly traced and handled\n');
166
152
  }
167
153
  });
@@ -3,19 +3,31 @@
3
3
  */
4
4
 
5
5
  import LocalStackMemoryMCP from './server';
6
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
+
7
+ // Type for accessing private members in tests
8
+ interface MCPTestInstance {
9
+ traceDetector: {
10
+ addToolCall: (call: {
11
+ id: string;
12
+ tool: string;
13
+ timestamp: number;
14
+ arguments: Record<string, unknown>;
15
+ }) => void;
16
+ flush: () => void;
17
+ };
18
+ handleGetTraceStatistics: (
19
+ args: Record<string, unknown>
20
+ ) => Promise<{ content: Array<{ text: string }> }>;
21
+ handleGetTraces: (args: {
22
+ limit: number;
23
+ }) => Promise<{ content: Array<{ text: string }> }>;
24
+ }
7
25
 
8
26
  async function testTraceIntegration() {
9
27
  console.log('🧪 Testing Trace Detection in MCP Server\n');
10
28
 
11
- // Mock minimal server setup
12
- const mockServer = {
13
- setRequestHandler: () => {},
14
- connect: () => Promise.resolve(),
15
- } as any;
16
-
17
29
  // Access the private methods through prototype
18
- const MCPClass = LocalStackMemoryMCP as any;
30
+ const MCPClass = LocalStackMemoryMCP as unknown as new () => MCPTestInstance;
19
31
  const mcp = new MCPClass();
20
32
 
21
33
  // Simulate tool calls directly on the trace detector
@@ -99,7 +99,7 @@ MAX_FILE_SIZE=100000 # Max size per file (100KB)
99
99
  MAX_TOTAL_SIZE=500000 # Max total size (500KB)
100
100
 
101
101
  # Claude CLI settings
102
- CLAUDE_MODEL=claude-3-opus # Model to use
102
+ CLAUDE_MODEL=claude-sonnet-4-20250514 # Model to use
103
103
  CLAUDE_MAX_TOKENS=4000 # Max tokens per request
104
104
 
105
105
  # File patterns to check (regex)
@@ -130,4 +130,4 @@ echo ""
130
130
  echo "Environment variables you can set:"
131
131
  echo " CLAUDE_AUTO_FIX=true # Auto-apply suggested fixes"
132
132
  echo " CLAUDE_REVIEW_ENABLED=false # Skip code review"
133
- echo " CLAUDE_TEST_ENABLED=false # Skip test generation"
133
+ echo " CLAUDE_TEST_ENABLED=false # Skip test generation"
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ // Verifies expected dist artifacts and bin launchers point to correct paths.
3
+ // Exits non-zero with actionable messages on mismatch.
4
+
5
+ const { readFileSync, existsSync } = require('fs');
6
+ const { join } = require('path');
7
+
8
+ function fail(msg) {
9
+ console.error(`ERROR: ${msg}`);
10
+ process.exitCode = 1;
11
+ }
12
+
13
+ function checkFile(path) {
14
+ if (!existsSync(path)) {
15
+ fail(`Missing built file: ${path}`);
16
+ return false;
17
+ }
18
+ return true;
19
+ }
20
+
21
+ function fileContains(path, substr) {
22
+ try {
23
+ const c = readFileSync(path, 'utf8');
24
+ if (!c.includes(substr)) {
25
+ fail(`Expected reference not found in ${path}: ${substr}`);
26
+ return false;
27
+ }
28
+ return true;
29
+ } catch (e) {
30
+ fail(`Unable to read ${path}: ${e.message}`);
31
+ return false;
32
+ }
33
+ }
34
+
35
+ function main() {
36
+ const dist = 'dist/src';
37
+
38
+ // 1) Core CLI and MCP server artifacts
39
+ const requiredFiles = [
40
+ join(dist, 'integrations/mcp/server.js'),
41
+ join(dist, 'cli/index.js'),
42
+ join(dist, 'cli/codex-sm.js'),
43
+ join(dist, 'cli/codex-sm-danger.js'),
44
+ join(dist, 'cli/claude-sm.js'),
45
+ join(dist, 'cli/claude-sm-danger.js'),
46
+ ];
47
+ requiredFiles.forEach(checkFile);
48
+
49
+ // 2) Bin launchers reference dist/src/* (ESM dynamic import)
50
+ fileContains('bin/codex-sm', "import('../dist/src/cli/codex-sm.js')");
51
+ fileContains('bin/codex-smd', "import('../dist/src/cli/codex-sm-danger.js')");
52
+ fileContains('bin/claude-sm', "import('../dist/src/cli/claude-sm.js')");
53
+ fileContains('bin/claude-smd', "import('../dist/src/cli/claude-sm-danger.js')");
54
+
55
+ // 3) package.json scripts point to correct paths
56
+ try {
57
+ const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
58
+ const scripts = pkg.scripts || {};
59
+ const expectations = [
60
+ ['start', 'dist/src/integrations/mcp/server.js'],
61
+ ['start:full', 'dist/src/integrations/mcp/server.js'],
62
+ ['mcp:start', 'dist/src/integrations/mcp/server.js'],
63
+ ];
64
+ for (const [key, needle] of expectations) {
65
+ const val = scripts[key] || '';
66
+ if (!val.includes(needle)) {
67
+ fail(`scripts.${key} should reference ${needle}, found: ${val}`);
68
+ }
69
+ }
70
+ } catch (e) {
71
+ fail(`Failed to validate package.json scripts: ${e.message}`);
72
+ }
73
+
74
+ if (process.exitCode) {
75
+ console.error('\nOne or more checks failed. Run: npm run build');
76
+ console.error('Then re-run: npm run verify:dist');
77
+ } else {
78
+ console.log('verify-dist: OK');
79
+ }
80
+ }
81
+
82
+ main();
83
+
@@ -15,6 +15,10 @@ import { fileURLToPath } from 'url';
15
15
  const __filename = fileURLToPath(import.meta.url);
16
16
  const __dirname = path.dirname(__filename);
17
17
 
18
+ const SWEEP_STATE_DIR =
19
+ process.env.SWEEP_STATE_DIR ||
20
+ path.join(process.env.HOME || '/tmp', '.stackmemory');
21
+
18
22
  const CONFIG = {
19
23
  enabled: process.env.SWEEP_ENABLED !== 'false',
20
24
  maxRecentDiffs: 5,
@@ -46,16 +50,9 @@ const CONFIG = {
46
50
  '.svelte',
47
51
  '.astro',
48
52
  ],
49
- stateFile: path.join(
50
- process.env.HOME || '/tmp',
51
- '.stackmemory',
52
- 'sweep-state.json'
53
- ),
54
- logFile: path.join(
55
- process.env.HOME || '/tmp',
56
- '.stackmemory',
57
- 'sweep-predictions.log'
58
- ),
53
+ stateFile: path.join(SWEEP_STATE_DIR, 'sweep-state.json'),
54
+ logFile: path.join(SWEEP_STATE_DIR, 'sweep-predictions.log'),
55
+ // Python script stays at shared location (shared server)
59
56
  pythonScript: path.join(
60
57
  process.env.HOME || '/tmp',
61
58
  '.stackmemory',