@stackmemoryai/stackmemory 0.5.57 → 0.5.59

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 (611) hide show
  1. package/bin/codex-smd +6 -0
  2. package/dist/cli/codex-sm-danger.js +21 -0
  3. package/dist/cli/codex-sm-danger.js.map +7 -0
  4. package/dist/cli/commands/handoff.js +33 -3
  5. package/dist/cli/commands/handoff.js.map +2 -2
  6. package/dist/cli/commands/search.js +20 -3
  7. package/dist/cli/commands/search.js.map +2 -2
  8. package/dist/core/database/sqlite-adapter.js +13 -3
  9. package/dist/core/database/sqlite-adapter.js.map +2 -2
  10. package/dist/core/errors/error-utils.js +208 -0
  11. package/dist/core/errors/error-utils.js.map +7 -0
  12. package/dist/core/errors/index.js +13 -4
  13. package/dist/core/errors/index.js.map +2 -2
  14. package/dist/core/merge/unified-merge-resolver.js +303 -0
  15. package/dist/core/merge/unified-merge-resolver.js.map +7 -0
  16. package/dist/core/monitoring/logger.js +61 -9
  17. package/dist/core/monitoring/logger.js.map +2 -2
  18. package/dist/core/security/index.js +35 -0
  19. package/dist/core/security/index.js.map +7 -0
  20. package/dist/core/security/input-sanitizer.js +321 -0
  21. package/dist/core/security/input-sanitizer.js.map +7 -0
  22. package/dist/core/session/enhanced-handoff.js +136 -2
  23. package/dist/core/session/enhanced-handoff.js.map +3 -3
  24. package/dist/integrations/linear/client.js +5 -1
  25. package/dist/integrations/linear/client.js.map +2 -2
  26. package/dist/integrations/mcp/remote-server.js +27 -36
  27. package/dist/integrations/mcp/remote-server.js.map +2 -2
  28. package/dist/integrations/mcp/server.js +44 -29
  29. package/dist/integrations/mcp/server.js.map +3 -3
  30. package/dist/scripts/benchmark-performance.js +48 -0
  31. package/dist/scripts/benchmark-performance.js.map +7 -0
  32. package/dist/scripts/check-redis.js +42 -0
  33. package/dist/scripts/check-redis.js.map +7 -0
  34. package/dist/scripts/initialize.js +116 -0
  35. package/dist/scripts/initialize.js.map +7 -0
  36. package/dist/scripts/list-linear-tasks.js +124 -0
  37. package/dist/scripts/list-linear-tasks.js.map +7 -0
  38. package/dist/scripts/measure-handoff-impact.js +340 -0
  39. package/dist/scripts/measure-handoff-impact.js.map +7 -0
  40. package/dist/scripts/query-chromadb.js +160 -0
  41. package/dist/scripts/query-chromadb.js.map +7 -0
  42. package/dist/scripts/show-linear-summary.js +119 -0
  43. package/dist/scripts/show-linear-summary.js.map +7 -0
  44. package/dist/scripts/simple-swarm-demo.js +90 -0
  45. package/dist/scripts/simple-swarm-demo.js.map +7 -0
  46. package/dist/scripts/status.js +155 -0
  47. package/dist/scripts/status.js.map +7 -0
  48. package/dist/scripts/test-chromadb-sync.js +192 -0
  49. package/dist/scripts/test-chromadb-sync.js.map +7 -0
  50. package/dist/scripts/test-ralph-iteration-fix.js +86 -0
  51. package/dist/scripts/test-ralph-iteration-fix.js.map +7 -0
  52. package/dist/scripts/test-ralph-iterations.js +121 -0
  53. package/dist/scripts/test-ralph-iterations.js.map +7 -0
  54. package/dist/scripts/test-redis-storage.js +389 -0
  55. package/dist/scripts/test-redis-storage.js.map +7 -0
  56. package/dist/scripts/test-simple-ralph-state-sync.js +115 -0
  57. package/dist/scripts/test-simple-ralph-state-sync.js.map +7 -0
  58. package/dist/scripts/test-swarm-fixes.js +125 -0
  59. package/dist/scripts/test-swarm-fixes.js.map +7 -0
  60. package/dist/scripts/test-swarm-tui.js +23 -0
  61. package/dist/scripts/test-swarm-tui.js.map +7 -0
  62. package/dist/scripts/test-tui-shortcuts.js +52 -0
  63. package/dist/scripts/test-tui-shortcuts.js.map +7 -0
  64. package/dist/scripts/validate-tui-shortcuts.js +60 -0
  65. package/dist/scripts/validate-tui-shortcuts.js.map +7 -0
  66. package/dist/src/agents/core/agent-task-manager.js +527 -0
  67. package/dist/src/agents/core/agent-task-manager.js.map +7 -0
  68. package/dist/src/agents/verifiers/base-verifier.js +133 -0
  69. package/dist/src/agents/verifiers/base-verifier.js.map +7 -0
  70. package/dist/src/agents/verifiers/formatter-verifier.js +130 -0
  71. package/dist/src/agents/verifiers/formatter-verifier.js.map +7 -0
  72. package/dist/src/agents/verifiers/llm-judge.js +252 -0
  73. package/dist/src/agents/verifiers/llm-judge.js.map +7 -0
  74. package/dist/src/cli/auto-detect.js +321 -0
  75. package/dist/src/cli/auto-detect.js.map +7 -0
  76. package/dist/src/cli/claude-sm-danger.js +21 -0
  77. package/dist/src/cli/claude-sm-danger.js.map +7 -0
  78. package/dist/src/cli/claude-sm.js +1156 -0
  79. package/dist/src/cli/claude-sm.js.map +7 -0
  80. package/dist/src/cli/codex-sm-danger.js +21 -0
  81. package/dist/src/cli/codex-sm-danger.js.map +7 -0
  82. package/dist/src/cli/codex-sm.js +349 -0
  83. package/dist/src/cli/codex-sm.js.map +7 -0
  84. package/dist/src/cli/commands/api.js +232 -0
  85. package/dist/src/cli/commands/api.js.map +7 -0
  86. package/dist/src/cli/commands/auto-background.js +180 -0
  87. package/dist/src/cli/commands/auto-background.js.map +7 -0
  88. package/dist/src/cli/commands/cleanup-processes.js +68 -0
  89. package/dist/src/cli/commands/cleanup-processes.js.map +7 -0
  90. package/dist/src/cli/commands/clear.js +202 -0
  91. package/dist/src/cli/commands/clear.js.map +7 -0
  92. package/dist/src/cli/commands/config.js +445 -0
  93. package/dist/src/cli/commands/config.js.map +7 -0
  94. package/dist/src/cli/commands/context-rehydrate.js +751 -0
  95. package/dist/src/cli/commands/context-rehydrate.js.map +7 -0
  96. package/dist/src/cli/commands/context.js +343 -0
  97. package/dist/src/cli/commands/context.js.map +7 -0
  98. package/dist/src/cli/commands/daemon.js +392 -0
  99. package/dist/src/cli/commands/daemon.js.map +7 -0
  100. package/dist/src/cli/commands/dashboard.js +210 -0
  101. package/dist/src/cli/commands/dashboard.js.map +7 -0
  102. package/dist/src/cli/commands/db.js +147 -0
  103. package/dist/src/cli/commands/db.js.map +7 -0
  104. package/dist/src/cli/commands/decision.js +266 -0
  105. package/dist/src/cli/commands/decision.js.map +7 -0
  106. package/dist/src/cli/commands/discovery.js +279 -0
  107. package/dist/src/cli/commands/discovery.js.map +7 -0
  108. package/dist/src/cli/commands/handoff.js +624 -0
  109. package/dist/src/cli/commands/handoff.js.map +7 -0
  110. package/dist/src/cli/commands/hooks.js +298 -0
  111. package/dist/src/cli/commands/hooks.js.map +7 -0
  112. package/dist/src/cli/commands/linear.js +529 -0
  113. package/dist/src/cli/commands/linear.js.map +7 -0
  114. package/dist/src/cli/commands/log.js +169 -0
  115. package/dist/src/cli/commands/log.js.map +7 -0
  116. package/dist/src/cli/commands/login.js +172 -0
  117. package/dist/src/cli/commands/login.js.map +7 -0
  118. package/dist/src/cli/commands/migrate.js +240 -0
  119. package/dist/src/cli/commands/migrate.js.map +7 -0
  120. package/dist/src/cli/commands/model.js +533 -0
  121. package/dist/src/cli/commands/model.js.map +7 -0
  122. package/dist/src/cli/commands/onboard.js +536 -0
  123. package/dist/src/cli/commands/onboard.js.map +7 -0
  124. package/dist/src/cli/commands/projects.js +199 -0
  125. package/dist/src/cli/commands/projects.js.map +7 -0
  126. package/dist/src/cli/commands/ralph.js +909 -0
  127. package/dist/src/cli/commands/ralph.js.map +7 -0
  128. package/dist/src/cli/commands/retrieval.js +248 -0
  129. package/dist/src/cli/commands/retrieval.js.map +7 -0
  130. package/dist/src/cli/commands/search.js +173 -0
  131. package/dist/src/cli/commands/search.js.map +7 -0
  132. package/dist/src/cli/commands/service.js +749 -0
  133. package/dist/src/cli/commands/service.js.map +7 -0
  134. package/dist/src/cli/commands/session.js +200 -0
  135. package/dist/src/cli/commands/session.js.map +7 -0
  136. package/dist/src/cli/commands/settings.js +306 -0
  137. package/dist/src/cli/commands/settings.js.map +7 -0
  138. package/dist/src/cli/commands/setup.js +701 -0
  139. package/dist/src/cli/commands/setup.js.map +7 -0
  140. package/dist/src/cli/commands/shell.js +249 -0
  141. package/dist/src/cli/commands/shell.js.map +7 -0
  142. package/dist/src/cli/commands/signup.js +50 -0
  143. package/dist/src/cli/commands/signup.js.map +7 -0
  144. package/dist/src/cli/commands/skills.js +470 -0
  145. package/dist/src/cli/commands/skills.js.map +7 -0
  146. package/dist/src/cli/commands/sms-notify.js +795 -0
  147. package/dist/src/cli/commands/sms-notify.js.map +7 -0
  148. package/dist/src/cli/commands/storage-tier.js +183 -0
  149. package/dist/src/cli/commands/storage-tier.js.map +7 -0
  150. package/dist/src/cli/commands/sweep.js +249 -0
  151. package/dist/src/cli/commands/sweep.js.map +7 -0
  152. package/dist/src/cli/commands/tasks.js +213 -0
  153. package/dist/src/cli/commands/tasks.js.map +7 -0
  154. package/dist/src/cli/commands/worktree.js +319 -0
  155. package/dist/src/cli/commands/worktree.js.map +7 -0
  156. package/dist/src/cli/index.js +594 -0
  157. package/dist/src/cli/index.js.map +7 -0
  158. package/dist/src/cli/opencode-sm.js +448 -0
  159. package/dist/src/cli/opencode-sm.js.map +7 -0
  160. package/dist/src/cli/utils/viewer.js +96 -0
  161. package/dist/src/cli/utils/viewer.js.map +7 -0
  162. package/dist/src/core/config/config-manager.js +398 -0
  163. package/dist/src/core/config/config-manager.js.map +7 -0
  164. package/dist/src/core/config/feature-flags.js +76 -0
  165. package/dist/src/core/config/feature-flags.js.map +7 -0
  166. package/dist/src/core/config/storage-config.js +115 -0
  167. package/dist/src/core/config/storage-config.js.map +7 -0
  168. package/dist/src/core/config/types.js +144 -0
  169. package/dist/src/core/config/types.js.map +7 -0
  170. package/dist/src/core/context/auto-context.js +80 -0
  171. package/dist/src/core/context/auto-context.js.map +7 -0
  172. package/dist/src/core/context/dual-stack-manager.js +870 -0
  173. package/dist/src/core/context/dual-stack-manager.js.map +7 -0
  174. package/dist/src/core/context/enhanced-rehydration.js +994 -0
  175. package/dist/src/core/context/enhanced-rehydration.js.map +7 -0
  176. package/dist/src/core/context/frame-database.js +479 -0
  177. package/dist/src/core/context/frame-database.js.map +7 -0
  178. package/dist/src/core/context/frame-digest.js +250 -0
  179. package/dist/src/core/context/frame-digest.js.map +7 -0
  180. package/dist/src/core/context/frame-handoff-manager.js +778 -0
  181. package/dist/src/core/context/frame-handoff-manager.js.map +7 -0
  182. package/dist/src/core/context/frame-lifecycle-hooks.js +119 -0
  183. package/dist/src/core/context/frame-lifecycle-hooks.js.map +7 -0
  184. package/dist/src/core/context/frame-recovery.js +302 -0
  185. package/dist/src/core/context/frame-recovery.js.map +7 -0
  186. package/dist/src/core/context/frame-stack.js +314 -0
  187. package/dist/src/core/context/frame-stack.js.map +7 -0
  188. package/dist/src/core/context/frame-types.js +5 -0
  189. package/dist/src/core/context/frame-types.js.map +7 -0
  190. package/dist/src/core/context/index.js +25 -0
  191. package/dist/src/core/context/index.js.map +7 -0
  192. package/dist/src/core/context/permission-manager.js +185 -0
  193. package/dist/src/core/context/permission-manager.js.map +7 -0
  194. package/dist/src/core/context/recursive-context-manager.js +592 -0
  195. package/dist/src/core/context/recursive-context-manager.js.map +7 -0
  196. package/dist/src/core/context/refactored-frame-manager.js +754 -0
  197. package/dist/src/core/context/refactored-frame-manager.js.map +7 -0
  198. package/dist/src/core/context/shared-context-layer.js +621 -0
  199. package/dist/src/core/context/shared-context-layer.js.map +7 -0
  200. package/dist/src/core/context/stack-merge-resolver.js +749 -0
  201. package/dist/src/core/context/stack-merge-resolver.js.map +7 -0
  202. package/dist/src/core/context/validation.js +130 -0
  203. package/dist/src/core/context/validation.js.map +7 -0
  204. package/dist/src/core/database/batch-operations.js +384 -0
  205. package/dist/src/core/database/batch-operations.js.map +7 -0
  206. package/dist/src/core/database/connection-pool.js +330 -0
  207. package/dist/src/core/database/connection-pool.js.map +7 -0
  208. package/dist/src/core/database/database-adapter.js +60 -0
  209. package/dist/src/core/database/database-adapter.js.map +7 -0
  210. package/dist/src/core/database/migration-manager.js +614 -0
  211. package/dist/src/core/database/migration-manager.js.map +7 -0
  212. package/dist/src/core/database/query-cache.js +298 -0
  213. package/dist/src/core/database/query-cache.js.map +7 -0
  214. package/dist/src/core/database/query-router.js +430 -0
  215. package/dist/src/core/database/query-router.js.map +7 -0
  216. package/dist/src/core/database/sqlite-adapter.js +738 -0
  217. package/dist/src/core/database/sqlite-adapter.js.map +7 -0
  218. package/dist/src/core/digest/enhanced-hybrid-digest.js +277 -0
  219. package/dist/src/core/digest/enhanced-hybrid-digest.js.map +7 -0
  220. package/dist/src/core/digest/frame-digest-integration.js +176 -0
  221. package/dist/src/core/digest/frame-digest-integration.js.map +7 -0
  222. package/dist/src/core/digest/hybrid-digest-generator.js +553 -0
  223. package/dist/src/core/digest/hybrid-digest-generator.js.map +7 -0
  224. package/dist/src/core/digest/index.js +9 -0
  225. package/dist/src/core/digest/index.js.map +7 -0
  226. package/dist/src/core/digest/types.js +25 -0
  227. package/dist/src/core/digest/types.js.map +7 -0
  228. package/dist/src/core/errors/error-utils.js +208 -0
  229. package/dist/src/core/errors/error-utils.js.map +7 -0
  230. package/dist/src/core/errors/index.js +521 -0
  231. package/dist/src/core/errors/index.js.map +7 -0
  232. package/dist/src/core/errors/recovery.js +269 -0
  233. package/dist/src/core/errors/recovery.js.map +7 -0
  234. package/dist/src/core/execution/parallel-executor.js +258 -0
  235. package/dist/src/core/execution/parallel-executor.js.map +7 -0
  236. package/dist/src/core/frame/workflow-templates.js +319 -0
  237. package/dist/src/core/frame/workflow-templates.js.map +7 -0
  238. package/dist/src/core/merge/conflict-detector.js +431 -0
  239. package/dist/src/core/merge/conflict-detector.js.map +7 -0
  240. package/dist/src/core/merge/index.js +9 -0
  241. package/dist/src/core/merge/index.js.map +7 -0
  242. package/dist/src/core/merge/resolution-engine.js +558 -0
  243. package/dist/src/core/merge/resolution-engine.js.map +7 -0
  244. package/dist/src/core/merge/stack-diff.js +532 -0
  245. package/dist/src/core/merge/stack-diff.js.map +7 -0
  246. package/dist/src/core/merge/types.js +5 -0
  247. package/dist/src/core/merge/types.js.map +7 -0
  248. package/dist/src/core/merge/unified-merge-resolver.js +303 -0
  249. package/dist/src/core/merge/unified-merge-resolver.js.map +7 -0
  250. package/dist/src/core/models/fallback-monitor.js +232 -0
  251. package/dist/src/core/models/fallback-monitor.js.map +7 -0
  252. package/dist/src/core/models/model-router.js +340 -0
  253. package/dist/src/core/models/model-router.js.map +7 -0
  254. package/dist/src/core/monitoring/error-handler.js +49 -0
  255. package/dist/src/core/monitoring/error-handler.js.map +7 -0
  256. package/dist/src/core/monitoring/logger.js +202 -0
  257. package/dist/src/core/monitoring/logger.js.map +7 -0
  258. package/dist/src/core/monitoring/metrics.js +172 -0
  259. package/dist/src/core/monitoring/metrics.js.map +7 -0
  260. package/dist/src/core/monitoring/progress-tracker.js +189 -0
  261. package/dist/src/core/monitoring/progress-tracker.js.map +7 -0
  262. package/dist/src/core/monitoring/session-monitor.js +300 -0
  263. package/dist/src/core/monitoring/session-monitor.js.map +7 -0
  264. package/dist/src/core/performance/context-cache.js +273 -0
  265. package/dist/src/core/performance/context-cache.js.map +7 -0
  266. package/dist/src/core/performance/index.js +11 -0
  267. package/dist/src/core/performance/index.js.map +7 -0
  268. package/dist/src/core/performance/lazy-context-loader.js +327 -0
  269. package/dist/src/core/performance/lazy-context-loader.js.map +7 -0
  270. package/dist/src/core/performance/monitor.js +221 -0
  271. package/dist/src/core/performance/monitor.js.map +7 -0
  272. package/dist/src/core/performance/optimized-frame-context.js +345 -0
  273. package/dist/src/core/performance/optimized-frame-context.js.map +7 -0
  274. package/dist/src/core/performance/performance-benchmark.js +277 -0
  275. package/dist/src/core/performance/performance-benchmark.js.map +7 -0
  276. package/dist/src/core/performance/performance-profiler.js +370 -0
  277. package/dist/src/core/performance/performance-profiler.js.map +7 -0
  278. package/dist/src/core/performance/streaming-jsonl-parser.js +195 -0
  279. package/dist/src/core/performance/streaming-jsonl-parser.js.map +7 -0
  280. package/dist/src/core/persistence/postgres-adapter.js +349 -0
  281. package/dist/src/core/persistence/postgres-adapter.js.map +7 -0
  282. package/dist/src/core/projects/project-isolation.js +201 -0
  283. package/dist/src/core/projects/project-isolation.js.map +7 -0
  284. package/dist/src/core/projects/project-manager.js +697 -0
  285. package/dist/src/core/projects/project-manager.js.map +7 -0
  286. package/dist/src/core/query/query-parser.js +370 -0
  287. package/dist/src/core/query/query-parser.js.map +7 -0
  288. package/dist/src/core/query/query-templates.js +321 -0
  289. package/dist/src/core/query/query-templates.js.map +7 -0
  290. package/dist/src/core/retrieval/context-retriever.js +479 -0
  291. package/dist/src/core/retrieval/context-retriever.js.map +7 -0
  292. package/dist/src/core/retrieval/index.js +8 -0
  293. package/dist/src/core/retrieval/index.js.map +7 -0
  294. package/dist/src/core/retrieval/llm-context-retrieval.js +613 -0
  295. package/dist/src/core/retrieval/llm-context-retrieval.js.map +7 -0
  296. package/dist/src/core/retrieval/llm-provider.js +151 -0
  297. package/dist/src/core/retrieval/llm-provider.js.map +7 -0
  298. package/dist/src/core/retrieval/retrieval-audit.js +236 -0
  299. package/dist/src/core/retrieval/retrieval-audit.js.map +7 -0
  300. package/dist/src/core/retrieval/summary-generator.js +589 -0
  301. package/dist/src/core/retrieval/summary-generator.js.map +7 -0
  302. package/dist/src/core/retrieval/types.js +21 -0
  303. package/dist/src/core/retrieval/types.js.map +7 -0
  304. package/dist/src/core/security/index.js +35 -0
  305. package/dist/src/core/security/index.js.map +7 -0
  306. package/dist/src/core/security/input-sanitizer.js +321 -0
  307. package/dist/src/core/security/input-sanitizer.js.map +7 -0
  308. package/dist/src/core/session/clear-survival.js +465 -0
  309. package/dist/src/core/session/clear-survival.js.map +7 -0
  310. package/dist/src/core/session/enhanced-handoff.js +792 -0
  311. package/dist/src/core/session/enhanced-handoff.js.map +7 -0
  312. package/dist/src/core/session/handoff-generator.js +343 -0
  313. package/dist/src/core/session/handoff-generator.js.map +7 -0
  314. package/dist/src/core/session/index.js +15 -0
  315. package/dist/src/core/session/index.js.map +7 -0
  316. package/dist/src/core/session/session-manager.js +347 -0
  317. package/dist/src/core/session/session-manager.js.map +7 -0
  318. package/dist/src/core/skills/index.js +7 -0
  319. package/dist/src/core/skills/index.js.map +7 -0
  320. package/dist/src/core/skills/skill-storage.js +764 -0
  321. package/dist/src/core/skills/skill-storage.js.map +7 -0
  322. package/dist/src/core/skills/types.js +193 -0
  323. package/dist/src/core/skills/types.js.map +7 -0
  324. package/dist/src/core/storage/chromadb-adapter.js +354 -0
  325. package/dist/src/core/storage/chromadb-adapter.js.map +7 -0
  326. package/dist/src/core/storage/infinite-storage.js +510 -0
  327. package/dist/src/core/storage/infinite-storage.js.map +7 -0
  328. package/dist/src/core/storage/remote-storage.js +489 -0
  329. package/dist/src/core/storage/remote-storage.js.map +7 -0
  330. package/dist/src/core/storage/two-tier-storage.js +766 -0
  331. package/dist/src/core/storage/two-tier-storage.js.map +7 -0
  332. package/dist/src/core/trace/cli-trace-wrapper.js +132 -0
  333. package/dist/src/core/trace/cli-trace-wrapper.js.map +7 -0
  334. package/dist/src/core/trace/db-trace-wrapper.js +247 -0
  335. package/dist/src/core/trace/db-trace-wrapper.js.map +7 -0
  336. package/dist/src/core/trace/debug-trace.js +417 -0
  337. package/dist/src/core/trace/debug-trace.js.map +7 -0
  338. package/dist/src/core/trace/index.js +109 -0
  339. package/dist/src/core/trace/index.js.map +7 -0
  340. package/dist/src/core/trace/linear-api-wrapper.js +178 -0
  341. package/dist/src/core/trace/linear-api-wrapper.js.map +7 -0
  342. package/dist/src/core/trace/trace-detector.js +528 -0
  343. package/dist/src/core/trace/trace-detector.js.map +7 -0
  344. package/dist/src/core/trace/trace-store.js +345 -0
  345. package/dist/src/core/trace/trace-store.js.map +7 -0
  346. package/dist/src/core/trace/types.js +77 -0
  347. package/dist/src/core/trace/types.js.map +7 -0
  348. package/dist/src/core/types.js +5 -0
  349. package/dist/src/core/types.js.map +7 -0
  350. package/dist/src/core/utils/async-mutex.js +114 -0
  351. package/dist/src/core/utils/async-mutex.js.map +7 -0
  352. package/dist/src/core/utils/compression.js +83 -0
  353. package/dist/src/core/utils/compression.js.map +7 -0
  354. package/dist/src/core/utils/update-checker.js +218 -0
  355. package/dist/src/core/utils/update-checker.js.map +7 -0
  356. package/dist/src/core/worktree/worktree-manager.js +465 -0
  357. package/dist/src/core/worktree/worktree-manager.js.map +7 -0
  358. package/dist/src/daemon/daemon-config.js +149 -0
  359. package/dist/src/daemon/daemon-config.js.map +7 -0
  360. package/dist/src/daemon/services/context-service.js +122 -0
  361. package/dist/src/daemon/services/context-service.js.map +7 -0
  362. package/dist/src/daemon/services/linear-service.js +136 -0
  363. package/dist/src/daemon/services/linear-service.js.map +7 -0
  364. package/dist/src/daemon/session-daemon.js +312 -0
  365. package/dist/src/daemon/session-daemon.js.map +7 -0
  366. package/dist/src/daemon/unified-daemon.js +276 -0
  367. package/dist/src/daemon/unified-daemon.js.map +7 -0
  368. package/dist/src/features/analytics/api/analytics-api.js +287 -0
  369. package/dist/src/features/analytics/api/analytics-api.js.map +7 -0
  370. package/dist/src/features/analytics/core/analytics-service.js +282 -0
  371. package/dist/src/features/analytics/core/analytics-service.js.map +7 -0
  372. package/dist/src/features/analytics/index.js +18 -0
  373. package/dist/src/features/analytics/index.js.map +7 -0
  374. package/dist/src/features/analytics/queries/metrics-queries.js +277 -0
  375. package/dist/src/features/analytics/queries/metrics-queries.js.map +7 -0
  376. package/dist/src/features/analytics/types/metrics.js +5 -0
  377. package/dist/src/features/analytics/types/metrics.js.map +7 -0
  378. package/dist/src/features/browser/browser-mcp.js +492 -0
  379. package/dist/src/features/browser/browser-mcp.js.map +7 -0
  380. package/dist/src/features/sweep/index.js +20 -0
  381. package/dist/src/features/sweep/index.js.map +7 -0
  382. package/dist/src/features/sweep/prediction-client.js +155 -0
  383. package/dist/src/features/sweep/prediction-client.js.map +7 -0
  384. package/dist/src/features/sweep/prompt-builder.js +85 -0
  385. package/dist/src/features/sweep/prompt-builder.js.map +7 -0
  386. package/dist/src/features/sweep/pty-wrapper.js +171 -0
  387. package/dist/src/features/sweep/pty-wrapper.js.map +7 -0
  388. package/dist/src/features/sweep/state-watcher.js +87 -0
  389. package/dist/src/features/sweep/state-watcher.js.map +7 -0
  390. package/dist/src/features/sweep/status-bar.js +88 -0
  391. package/dist/src/features/sweep/status-bar.js.map +7 -0
  392. package/dist/src/features/sweep/sweep-server-manager.js +226 -0
  393. package/dist/src/features/sweep/sweep-server-manager.js.map +7 -0
  394. package/dist/src/features/sweep/tab-interceptor.js +38 -0
  395. package/dist/src/features/sweep/tab-interceptor.js.map +7 -0
  396. package/dist/src/features/sweep/types.js +18 -0
  397. package/dist/src/features/sweep/types.js.map +7 -0
  398. package/dist/src/features/tasks/linear-task-manager.js +487 -0
  399. package/dist/src/features/tasks/linear-task-manager.js.map +7 -0
  400. package/dist/src/features/tasks/task-aware-context.js +410 -0
  401. package/dist/src/features/tasks/task-aware-context.js.map +7 -0
  402. package/dist/src/features/tui/simple-monitor.js +116 -0
  403. package/dist/src/features/tui/simple-monitor.js.map +7 -0
  404. package/dist/src/features/tui/swarm-monitor.js +648 -0
  405. package/dist/src/features/tui/swarm-monitor.js.map +7 -0
  406. package/dist/src/features/web/client/stores/task-store.js +26 -0
  407. package/dist/src/features/web/client/stores/task-store.js.map +7 -0
  408. package/dist/src/features/web/server/index.js +194 -0
  409. package/dist/src/features/web/server/index.js.map +7 -0
  410. package/dist/src/hooks/auto-background.js +151 -0
  411. package/dist/src/hooks/auto-background.js.map +7 -0
  412. package/dist/src/hooks/claude-code-whatsapp-hook.js +197 -0
  413. package/dist/src/hooks/claude-code-whatsapp-hook.js.map +7 -0
  414. package/dist/src/hooks/config.js +150 -0
  415. package/dist/src/hooks/config.js.map +7 -0
  416. package/dist/src/hooks/daemon.js +364 -0
  417. package/dist/src/hooks/daemon.js.map +7 -0
  418. package/dist/src/hooks/events.js +58 -0
  419. package/dist/src/hooks/events.js.map +7 -0
  420. package/dist/src/hooks/index.js +12 -0
  421. package/dist/src/hooks/index.js.map +7 -0
  422. package/dist/src/hooks/linear-task-picker.js +186 -0
  423. package/dist/src/hooks/linear-task-picker.js.map +7 -0
  424. package/dist/src/hooks/schemas.js +197 -0
  425. package/dist/src/hooks/schemas.js.map +7 -0
  426. package/dist/src/hooks/secure-fs.js +49 -0
  427. package/dist/src/hooks/secure-fs.js.map +7 -0
  428. package/dist/src/hooks/security-logger.js +155 -0
  429. package/dist/src/hooks/security-logger.js.map +7 -0
  430. package/dist/src/hooks/session-summary.js +222 -0
  431. package/dist/src/hooks/session-summary.js.map +7 -0
  432. package/dist/src/hooks/sms-action-runner.js +371 -0
  433. package/dist/src/hooks/sms-action-runner.js.map +7 -0
  434. package/dist/src/hooks/sms-notify.js +506 -0
  435. package/dist/src/hooks/sms-notify.js.map +7 -0
  436. package/dist/src/hooks/sms-watcher.js +93 -0
  437. package/dist/src/hooks/sms-watcher.js.map +7 -0
  438. package/dist/src/hooks/sms-webhook.js +555 -0
  439. package/dist/src/hooks/sms-webhook.js.map +7 -0
  440. package/dist/src/hooks/whatsapp-commands.js +479 -0
  441. package/dist/src/hooks/whatsapp-commands.js.map +7 -0
  442. package/dist/src/hooks/whatsapp-scheduler.js +317 -0
  443. package/dist/src/hooks/whatsapp-scheduler.js.map +7 -0
  444. package/dist/src/hooks/whatsapp-sync.js +409 -0
  445. package/dist/src/hooks/whatsapp-sync.js.map +7 -0
  446. package/dist/src/index.js +25 -0
  447. package/dist/src/index.js.map +7 -0
  448. package/dist/src/integrations/anthropic/client.js +263 -0
  449. package/dist/src/integrations/anthropic/client.js.map +7 -0
  450. package/dist/src/integrations/claude-code/agent-bridge.js +768 -0
  451. package/dist/src/integrations/claude-code/agent-bridge.js.map +7 -0
  452. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +459 -0
  453. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js.map +7 -0
  454. package/dist/src/integrations/claude-code/lifecycle-hooks.js +254 -0
  455. package/dist/src/integrations/claude-code/lifecycle-hooks.js.map +7 -0
  456. package/dist/src/integrations/claude-code/post-task-hooks.js +545 -0
  457. package/dist/src/integrations/claude-code/post-task-hooks.js.map +7 -0
  458. package/dist/src/integrations/claude-code/subagent-client-stub.js +20 -0
  459. package/dist/src/integrations/claude-code/subagent-client-stub.js.map +7 -0
  460. package/dist/src/integrations/claude-code/subagent-client.js +511 -0
  461. package/dist/src/integrations/claude-code/subagent-client.js.map +7 -0
  462. package/dist/src/integrations/claude-code/task-coordinator.js +360 -0
  463. package/dist/src/integrations/claude-code/task-coordinator.js.map +7 -0
  464. package/dist/src/integrations/linear/auth.js +337 -0
  465. package/dist/src/integrations/linear/auth.js.map +7 -0
  466. package/dist/src/integrations/linear/auto-sync.js +258 -0
  467. package/dist/src/integrations/linear/auto-sync.js.map +7 -0
  468. package/dist/src/integrations/linear/client.js +634 -0
  469. package/dist/src/integrations/linear/client.js.map +7 -0
  470. package/dist/src/integrations/linear/config.js +130 -0
  471. package/dist/src/integrations/linear/config.js.map +7 -0
  472. package/dist/src/integrations/linear/migration.js +361 -0
  473. package/dist/src/integrations/linear/migration.js.map +7 -0
  474. package/dist/src/integrations/linear/oauth-server.js +454 -0
  475. package/dist/src/integrations/linear/oauth-server.js.map +7 -0
  476. package/dist/src/integrations/linear/rest-client.js +213 -0
  477. package/dist/src/integrations/linear/rest-client.js.map +7 -0
  478. package/dist/src/integrations/linear/sync-manager.js +236 -0
  479. package/dist/src/integrations/linear/sync-manager.js.map +7 -0
  480. package/dist/src/integrations/linear/sync-service.js +231 -0
  481. package/dist/src/integrations/linear/sync-service.js.map +7 -0
  482. package/dist/src/integrations/linear/sync.js +782 -0
  483. package/dist/src/integrations/linear/sync.js.map +7 -0
  484. package/dist/src/integrations/linear/types.js +5 -0
  485. package/dist/src/integrations/linear/types.js.map +7 -0
  486. package/dist/src/integrations/linear/unified-sync.js +589 -0
  487. package/dist/src/integrations/linear/unified-sync.js.map +7 -0
  488. package/dist/src/integrations/linear/webhook-handler.js +219 -0
  489. package/dist/src/integrations/linear/webhook-handler.js.map +7 -0
  490. package/dist/src/integrations/linear/webhook-server.js +218 -0
  491. package/dist/src/integrations/linear/webhook-server.js.map +7 -0
  492. package/dist/src/integrations/linear/webhook.js +291 -0
  493. package/dist/src/integrations/linear/webhook.js.map +7 -0
  494. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +266 -0
  495. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js.map +7 -0
  496. package/dist/src/integrations/mcp/handlers/context-handlers.js +257 -0
  497. package/dist/src/integrations/mcp/handlers/context-handlers.js.map +7 -0
  498. package/dist/src/integrations/mcp/handlers/discovery-handlers.js +497 -0
  499. package/dist/src/integrations/mcp/handlers/discovery-handlers.js.map +7 -0
  500. package/dist/src/integrations/mcp/handlers/index.js +166 -0
  501. package/dist/src/integrations/mcp/handlers/index.js.map +7 -0
  502. package/dist/src/integrations/mcp/handlers/linear-handlers.js +247 -0
  503. package/dist/src/integrations/mcp/handlers/linear-handlers.js.map +7 -0
  504. package/dist/src/integrations/mcp/handlers/skill-handlers.js +529 -0
  505. package/dist/src/integrations/mcp/handlers/skill-handlers.js.map +7 -0
  506. package/dist/src/integrations/mcp/handlers/task-handlers.js +239 -0
  507. package/dist/src/integrations/mcp/handlers/task-handlers.js.map +7 -0
  508. package/dist/src/integrations/mcp/handlers/trace-handlers.js +308 -0
  509. package/dist/src/integrations/mcp/handlers/trace-handlers.js.map +7 -0
  510. package/dist/src/integrations/mcp/index.js +23 -0
  511. package/dist/src/integrations/mcp/index.js.map +7 -0
  512. package/dist/src/integrations/mcp/middleware/tool-scoring.js +356 -0
  513. package/dist/src/integrations/mcp/middleware/tool-scoring.js.map +7 -0
  514. package/dist/src/integrations/mcp/refactored-server.js +374 -0
  515. package/dist/src/integrations/mcp/refactored-server.js.map +7 -0
  516. package/dist/src/integrations/mcp/remote-server.js +682 -0
  517. package/dist/src/integrations/mcp/remote-server.js.map +7 -0
  518. package/dist/src/integrations/mcp/schemas.js +147 -0
  519. package/dist/src/integrations/mcp/schemas.js.map +7 -0
  520. package/dist/src/integrations/mcp/server.js +1975 -0
  521. package/dist/src/integrations/mcp/server.js.map +7 -0
  522. package/dist/src/integrations/mcp/tool-definitions-code.js +125 -0
  523. package/dist/src/integrations/mcp/tool-definitions-code.js.map +7 -0
  524. package/dist/src/integrations/mcp/tool-definitions.js +702 -0
  525. package/dist/src/integrations/mcp/tool-definitions.js.map +7 -0
  526. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +860 -0
  527. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js.map +7 -0
  528. package/dist/src/integrations/ralph/context/context-budget-manager.js +301 -0
  529. package/dist/src/integrations/ralph/context/context-budget-manager.js.map +7 -0
  530. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +360 -0
  531. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js.map +7 -0
  532. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +410 -0
  533. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js.map +7 -0
  534. package/dist/src/integrations/ralph/index.js +18 -0
  535. package/dist/src/integrations/ralph/index.js.map +7 -0
  536. package/dist/src/integrations/ralph/learning/pattern-learner.js +401 -0
  537. package/dist/src/integrations/ralph/learning/pattern-learner.js.map +7 -0
  538. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +448 -0
  539. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js.map +7 -0
  540. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +294 -0
  541. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js.map +7 -0
  542. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +108 -0
  543. package/dist/src/integrations/ralph/monitoring/swarm-registry.js.map +7 -0
  544. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +463 -0
  545. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js.map +7 -0
  546. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +400 -0
  547. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js.map +7 -0
  548. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +473 -0
  549. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js.map +7 -0
  550. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +388 -0
  551. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js.map +7 -0
  552. package/dist/src/integrations/ralph/performance/performance-optimizer.js +358 -0
  553. package/dist/src/integrations/ralph/performance/performance-optimizer.js.map +7 -0
  554. package/dist/src/integrations/ralph/recovery/crash-recovery.js +462 -0
  555. package/dist/src/integrations/ralph/recovery/crash-recovery.js.map +7 -0
  556. package/dist/src/integrations/ralph/state/state-reconciler.js +404 -0
  557. package/dist/src/integrations/ralph/state/state-reconciler.js.map +7 -0
  558. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +428 -0
  559. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js.map +7 -0
  560. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +996 -0
  561. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js.map +7 -0
  562. package/dist/src/integrations/ralph/types.js +5 -0
  563. package/dist/src/integrations/ralph/types.js.map +7 -0
  564. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +585 -0
  565. package/dist/src/integrations/ralph/visualization/ralph-debugger.js.map +7 -0
  566. package/dist/src/mcp/stackmemory-mcp-server.js +554 -0
  567. package/dist/src/mcp/stackmemory-mcp-server.js.map +7 -0
  568. package/dist/src/middleware/exponential-rate-limiter.js +289 -0
  569. package/dist/src/middleware/exponential-rate-limiter.js.map +7 -0
  570. package/dist/src/models/user.model.js +358 -0
  571. package/dist/src/models/user.model.js.map +7 -0
  572. package/dist/src/servers/production/auth-middleware.js +528 -0
  573. package/dist/src/servers/production/auth-middleware.js.map +7 -0
  574. package/dist/src/services/config-service.js +65 -0
  575. package/dist/src/services/config-service.js.map +7 -0
  576. package/dist/src/services/context-service.js +194 -0
  577. package/dist/src/services/context-service.js.map +7 -0
  578. package/dist/src/skills/api-discovery.js +354 -0
  579. package/dist/src/skills/api-discovery.js.map +7 -0
  580. package/dist/src/skills/api-skill.js +475 -0
  581. package/dist/src/skills/api-skill.js.map +7 -0
  582. package/dist/src/skills/claude-skills.js +1061 -0
  583. package/dist/src/skills/claude-skills.js.map +7 -0
  584. package/dist/src/skills/dashboard-launcher.js +216 -0
  585. package/dist/src/skills/dashboard-launcher.js.map +7 -0
  586. package/dist/src/skills/recursive-agent-orchestrator.js +575 -0
  587. package/dist/src/skills/recursive-agent-orchestrator.js.map +7 -0
  588. package/dist/src/skills/repo-ingestion-skill.js +609 -0
  589. package/dist/src/skills/repo-ingestion-skill.js.map +7 -0
  590. package/dist/src/skills/unified-rlm-orchestrator.js +404 -0
  591. package/dist/src/skills/unified-rlm-orchestrator.js.map +7 -0
  592. package/dist/src/types/task.js +5 -0
  593. package/dist/src/types/task.js.map +7 -0
  594. package/dist/src/utils/env.js +50 -0
  595. package/dist/src/utils/env.js.map +7 -0
  596. package/dist/src/utils/formatting.js +62 -0
  597. package/dist/src/utils/formatting.js.map +7 -0
  598. package/dist/src/utils/process-cleanup.js +136 -0
  599. package/dist/src/utils/process-cleanup.js.map +7 -0
  600. package/package.json +4 -3
  601. package/scripts/create-cleanup-issues.js +302 -0
  602. package/scripts/demos/browser-test.ts +39 -0
  603. package/scripts/demos/ralph-integration-demo.ts +244 -0
  604. package/scripts/demos/trace-demo.ts +214 -0
  605. package/scripts/demos/trace-detector.demo.ts +171 -0
  606. package/scripts/demos/trace-test.ts +67 -0
  607. package/scripts/initialize.ts +16 -7
  608. package/scripts/install.sh +14 -62
  609. package/scripts/status.ts +111 -46
  610. package/scripts/test-claude-config.sh +123 -0
  611. package/scripts/validate-claude-config.sh +155 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/session/enhanced-handoff.ts"],
4
- "sourcesContent": ["/**\n * Enhanced Handoff Generator\n * Produces high-efficacy handoffs (70-85% context preservation)\n * Target: 2,000-3,000 tokens for rich context\n */\n\nimport { execSync } from 'child_process';\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs';\nimport { join, basename } from 'path';\nimport { homedir, tmpdir } from 'os';\nimport { globSync } from 'glob';\n\n// Token counting - use Anthropic's tokenizer for accurate counts\nlet countTokens: (text: string) => number;\ntry {\n // Dynamic import for CommonJS compatibility\n const tokenizer = await import('@anthropic-ai/tokenizer');\n countTokens = tokenizer.countTokens;\n} catch {\n // Fallback to estimation if tokenizer not available\n countTokens = (text: string) => Math.ceil(text.length / 3.5);\n}\n\n// Load session decisions if available\ninterface SessionDecision {\n id: string;\n what: string;\n why: string;\n alternatives?: string[];\n timestamp: string;\n category?: string;\n}\n\n// Review feedback persistence\ninterface StoredReviewFeedback {\n timestamp: string;\n source: string;\n keyPoints: string[];\n actionItems: string[];\n sourceFile?: string;\n}\n\ninterface ReviewFeedbackStore {\n feedbacks: StoredReviewFeedback[];\n lastUpdated: string;\n}\n\nfunction loadSessionDecisions(projectRoot: string): SessionDecision[] {\n const storePath = join(projectRoot, '.stackmemory', 'session-decisions.json');\n if (existsSync(storePath)) {\n try {\n const store = JSON.parse(readFileSync(storePath, 'utf-8'));\n return store.decisions || [];\n } catch {\n return [];\n }\n }\n return [];\n}\n\nfunction loadReviewFeedback(projectRoot: string): StoredReviewFeedback[] {\n const storePath = join(projectRoot, '.stackmemory', 'review-feedback.json');\n if (existsSync(storePath)) {\n try {\n const store: ReviewFeedbackStore = JSON.parse(\n readFileSync(storePath, 'utf-8')\n );\n // Return feedbacks from last 24 hours\n const cutoff = Date.now() - 24 * 60 * 60 * 1000;\n return store.feedbacks.filter(\n (f) => new Date(f.timestamp).getTime() > cutoff\n );\n } catch {\n return [];\n }\n }\n return [];\n}\n\nfunction saveReviewFeedback(\n projectRoot: string,\n feedbacks: StoredReviewFeedback[]\n): void {\n const dir = join(projectRoot, '.stackmemory');\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const storePath = join(dir, 'review-feedback.json');\n\n // Load existing and merge\n let existing: StoredReviewFeedback[] = [];\n if (existsSync(storePath)) {\n try {\n const store: ReviewFeedbackStore = JSON.parse(\n readFileSync(storePath, 'utf-8')\n );\n existing = store.feedbacks || [];\n } catch {\n // Ignore parse errors\n }\n }\n\n // Deduplicate by source + first key point\n const seen = new Set<string>();\n const merged: StoredReviewFeedback[] = [];\n\n for (const f of [...feedbacks, ...existing]) {\n const key = `${f.source}:${f.keyPoints[0] || ''}`;\n if (!seen.has(key)) {\n seen.add(key);\n merged.push(f);\n }\n }\n\n // Keep only last 20 feedbacks\n const store: ReviewFeedbackStore = {\n feedbacks: merged.slice(0, 20),\n lastUpdated: new Date().toISOString(),\n };\n\n writeFileSync(storePath, JSON.stringify(store, null, 2));\n}\n\n/**\n * Find Claude agent output directories dynamically\n */\nfunction findAgentOutputDirs(projectRoot: string): string[] {\n const dirs: string[] = [];\n\n // Try multiple locations where agent outputs might be stored\n const tmpBase = process.env['TMPDIR'] || tmpdir() || '/tmp';\n\n // Pattern 1: /tmp/claude/-path-to-project/tasks\n const projectPathEncoded = projectRoot.replace(/\\//g, '-').replace(/^-/, '');\n const pattern1 = join(tmpBase, 'claude', `*${projectPathEncoded}*`, 'tasks');\n try {\n const matches = globSync(pattern1);\n dirs.push(...matches);\n } catch {\n // Glob failed\n }\n\n // Pattern 2: /private/tmp/claude/... (macOS specific)\n if (tmpBase !== '/private/tmp') {\n const pattern2 = join(\n '/private/tmp',\n 'claude',\n `*${projectPathEncoded}*`,\n 'tasks'\n );\n try {\n const matches = globSync(pattern2);\n dirs.push(...matches);\n } catch {\n // Glob failed\n }\n }\n\n // Pattern 3: ~/.claude/projects/*/tasks (if exists)\n const homeClaudeDir = join(homedir(), '.claude', 'projects');\n if (existsSync(homeClaudeDir)) {\n try {\n const projectDirs = readdirSync(homeClaudeDir);\n for (const d of projectDirs) {\n const tasksDir = join(homeClaudeDir, d, 'tasks');\n if (existsSync(tasksDir)) {\n dirs.push(tasksDir);\n }\n }\n } catch {\n // Failed to read\n }\n }\n\n return [...new Set(dirs)]; // Deduplicate\n}\n\nexport interface EnhancedHandoff {\n // Metadata\n timestamp: string;\n project: string;\n branch: string;\n sessionDuration?: string;\n\n // What we're building (HIGH VALUE)\n activeWork: {\n description: string;\n status: 'in_progress' | 'blocked' | 'review' | 'done';\n keyFiles: string[];\n progress?: string;\n };\n\n // Decisions made (HIGH VALUE)\n decisions: Array<{\n what: string;\n why: string;\n alternatives?: string[];\n }>;\n\n // Architecture context (MEDIUM VALUE)\n architecture: {\n keyComponents: Array<{\n file: string;\n purpose: string;\n }>;\n patterns: string[];\n };\n\n // Blockers and issues (HIGH VALUE)\n blockers: Array<{\n issue: string;\n attempted: string[];\n status: 'resolved' | 'open';\n }>;\n\n // Review feedback (HIGH VALUE if present)\n reviewFeedback?: {\n source: string;\n keyPoints: string[];\n actionItems: string[];\n }[];\n\n // Next actions (MEDIUM VALUE)\n nextActions: string[];\n\n // Patterns established (LOW-MEDIUM VALUE)\n codePatterns?: string[];\n\n // Token metrics\n estimatedTokens: number;\n}\n\nexport class EnhancedHandoffGenerator {\n private projectRoot: string;\n private claudeProjectsDir: string;\n\n constructor(projectRoot: string) {\n this.projectRoot = projectRoot;\n this.claudeProjectsDir = join(homedir(), '.claude', 'projects');\n }\n\n /**\n * Generate a high-efficacy handoff\n */\n async generate(): Promise<EnhancedHandoff> {\n const handoff: EnhancedHandoff = {\n timestamp: new Date().toISOString(),\n project: basename(this.projectRoot),\n branch: this.getCurrentBranch(),\n activeWork: await this.extractActiveWork(),\n decisions: await this.extractDecisions(),\n architecture: await this.extractArchitecture(),\n blockers: await this.extractBlockers(),\n reviewFeedback: await this.extractReviewFeedback(),\n nextActions: await this.extractNextActions(),\n codePatterns: await this.extractCodePatterns(),\n estimatedTokens: 0,\n };\n\n // Calculate estimated tokens\n const markdown = this.toMarkdown(handoff);\n handoff.estimatedTokens = countTokens(markdown);\n\n return handoff;\n }\n\n /**\n * Extract what we're currently building from git and recent files\n */\n private async extractActiveWork(): Promise<EnhancedHandoff['activeWork']> {\n // Get recent commits to understand current work\n const recentCommits = this.getRecentCommits(5);\n const recentFiles = this.getRecentlyModifiedFiles(10);\n\n // Try to infer the active work from commit messages\n let description = 'Unknown - check git log for context';\n let status: EnhancedHandoff['activeWork']['status'] = 'in_progress';\n\n if (recentCommits.length > 0) {\n // Use most recent commit as indicator\n const lastCommit = recentCommits[0];\n if (lastCommit.includes('feat:') || lastCommit.includes('implement')) {\n description = lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n } else if (lastCommit.includes('fix:')) {\n description = 'Bug fix: ' + lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n } else if (\n lastCommit.includes('chore:') ||\n lastCommit.includes('refactor:')\n ) {\n description = lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n } else {\n description = lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n }\n }\n\n // Check for blocking indicators\n const gitStatus = this.getGitStatus();\n if (gitStatus.includes('conflict')) {\n status = 'blocked';\n }\n\n return {\n description,\n status,\n keyFiles: recentFiles.slice(0, 5),\n progress:\n recentCommits.length > 0\n ? `${recentCommits.length} commits in current session`\n : undefined,\n };\n }\n\n /**\n * Extract decisions from session store, git commits, and decision logs\n */\n private async extractDecisions(): Promise<EnhancedHandoff['decisions']> {\n const decisions: EnhancedHandoff['decisions'] = [];\n\n // First, load session decisions (highest priority - explicitly recorded)\n const sessionDecisions = loadSessionDecisions(this.projectRoot);\n for (const d of sessionDecisions) {\n decisions.push({\n what: d.what,\n why: d.why,\n alternatives: d.alternatives,\n });\n }\n\n // Then look for decision markers in recent commits\n const commits = this.getRecentCommits(20);\n for (const commit of commits) {\n // Look for decision-like patterns\n if (\n commit.toLowerCase().includes('use ') ||\n commit.toLowerCase().includes('switch to ') ||\n commit.toLowerCase().includes('default to ') ||\n (commit.toLowerCase().includes('make ') &&\n commit.toLowerCase().includes('optional'))\n ) {\n // Avoid duplicates\n const commitText = commit.replace(/^[a-f0-9]+\\s+/, '');\n if (!decisions.some((d) => d.what.includes(commitText.slice(0, 30)))) {\n decisions.push({\n what: commitText,\n why: 'See commit for details',\n });\n }\n }\n }\n\n // Check for a decisions file\n const decisionsFile = join(\n this.projectRoot,\n '.stackmemory',\n 'decisions.md'\n );\n if (existsSync(decisionsFile)) {\n const content = readFileSync(decisionsFile, 'utf-8');\n const parsed = this.parseDecisionsFile(content);\n decisions.push(...parsed);\n }\n\n return decisions.slice(0, 10); // Limit to prevent bloat\n }\n\n /**\n * Parse a decisions.md file\n */\n private parseDecisionsFile(content: string): EnhancedHandoff['decisions'] {\n const decisions: EnhancedHandoff['decisions'] = [];\n const lines = content.split('\\n');\n\n let currentDecision: {\n what: string;\n why: string;\n alternatives?: string[];\n } | null = null;\n\n for (const line of lines) {\n if (line.startsWith('## ') || line.startsWith('### ')) {\n if (currentDecision) {\n decisions.push(currentDecision);\n }\n currentDecision = { what: line.replace(/^#+\\s+/, ''), why: '' };\n } else if (currentDecision && line.toLowerCase().includes('rationale:')) {\n currentDecision.why = line.replace(/rationale:\\s*/i, '').trim();\n } else if (currentDecision && line.toLowerCase().includes('why:')) {\n currentDecision.why = line.replace(/why:\\s*/i, '').trim();\n } else if (\n currentDecision &&\n line.toLowerCase().includes('alternatives:')\n ) {\n currentDecision.alternatives = [];\n } else if (currentDecision?.alternatives && line.trim().startsWith('-')) {\n currentDecision.alternatives.push(line.replace(/^\\s*-\\s*/, '').trim());\n }\n }\n\n if (currentDecision) {\n decisions.push(currentDecision);\n }\n\n return decisions;\n }\n\n /**\n * Extract architecture context from key files\n */\n private async extractArchitecture(): Promise<\n EnhancedHandoff['architecture']\n > {\n const keyComponents: EnhancedHandoff['architecture']['keyComponents'] = [];\n const patterns: string[] = [];\n\n // Find recently modified TypeScript/JavaScript files\n const recentFiles = this.getRecentlyModifiedFiles(20);\n const codeFiles = recentFiles.filter(\n (f) => f.endsWith('.ts') || f.endsWith('.js') || f.endsWith('.tsx')\n );\n\n for (const file of codeFiles.slice(0, 8)) {\n const purpose = this.inferFilePurpose(file);\n if (purpose) {\n keyComponents.push({ file, purpose });\n }\n }\n\n // Detect patterns from file structure\n if (codeFiles.some((f) => f.includes('/daemon/'))) {\n patterns.push('Daemon/background process pattern');\n }\n if (codeFiles.some((f) => f.includes('/cli/'))) {\n patterns.push('CLI command pattern');\n }\n if (\n codeFiles.some((f) => f.includes('.test.') || f.includes('__tests__'))\n ) {\n patterns.push('Test files present');\n }\n if (codeFiles.some((f) => f.includes('/core/'))) {\n patterns.push('Core/domain separation');\n }\n\n return { keyComponents, patterns };\n }\n\n /**\n * Infer purpose from file name and path\n */\n private inferFilePurpose(filePath: string): string | null {\n const name = basename(filePath).replace(/\\.(ts|js|tsx)$/, '');\n const path = filePath.toLowerCase();\n\n if (path.includes('daemon')) return 'Background daemon/service';\n if (path.includes('cli/command')) return 'CLI command handler';\n if (path.includes('config')) return 'Configuration management';\n if (path.includes('storage')) return 'Data storage layer';\n if (path.includes('handoff')) return 'Session handoff logic';\n if (path.includes('service')) return 'Service orchestration';\n if (path.includes('manager')) return 'Resource/state management';\n if (path.includes('handler')) return 'Event/request handler';\n if (path.includes('util') || path.includes('helper'))\n return 'Utility functions';\n if (path.includes('types') || path.includes('interface'))\n return 'Type definitions';\n if (path.includes('test')) return null; // Skip test files\n if (name.includes('-')) {\n return name\n .split('-')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n }\n return null;\n }\n\n /**\n * Extract blockers from git status and recent errors\n */\n private async extractBlockers(): Promise<EnhancedHandoff['blockers']> {\n const blockers: EnhancedHandoff['blockers'] = [];\n\n // Check for merge conflicts\n const gitStatus = this.getGitStatus();\n if (gitStatus.includes('UU ') || gitStatus.includes('both modified')) {\n blockers.push({\n issue: 'Merge conflict detected',\n attempted: ['Check git status for affected files'],\n status: 'open',\n });\n }\n\n // Check for failing tests\n try {\n const testResult = execSync('npm test 2>&1 || true', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n timeout: 30000,\n });\n if (testResult.includes('FAIL') || testResult.includes('failed')) {\n const failCount = (testResult.match(/(\\d+) failed/i) || ['', '?'])[1];\n blockers.push({\n issue: `Test failures: ${failCount} tests failing`,\n attempted: ['Run npm test for details'],\n status: 'open',\n });\n }\n } catch {\n // Test command failed - might indicate issues\n }\n\n // Check for lint errors\n try {\n const lintResult = execSync('npm run lint 2>&1 || true', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n timeout: 30000,\n });\n if (lintResult.includes('error') && !lintResult.includes('0 errors')) {\n blockers.push({\n issue: 'Lint errors present',\n attempted: ['Run npm run lint for details'],\n status: 'open',\n });\n }\n } catch {\n // Lint command failed\n }\n\n return blockers;\n }\n\n /**\n * Extract review feedback from agent output files and persisted storage\n */\n private async extractReviewFeedback(): Promise<\n EnhancedHandoff['reviewFeedback']\n > {\n const feedback: EnhancedHandoff['reviewFeedback'] = [];\n const newFeedbacks: StoredReviewFeedback[] = [];\n\n // Find agent output directories dynamically\n const outputDirs = findAgentOutputDirs(this.projectRoot);\n\n for (const tmpDir of outputDirs) {\n if (!existsSync(tmpDir)) continue;\n\n try {\n const files = readdirSync(tmpDir).filter((f) => f.endsWith('.output'));\n const recentFiles = files\n .map((f) => ({\n name: f,\n path: join(tmpDir, f),\n stat: statSync(join(tmpDir, f)),\n }))\n .filter((f) => Date.now() - f.stat.mtimeMs < 3600000) // Last hour\n .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs)\n .slice(0, 3);\n\n for (const file of recentFiles) {\n const content = readFileSync(file.path, 'utf-8');\n const extracted = this.extractKeyPointsFromReview(content);\n if (extracted.keyPoints.length > 0) {\n feedback.push(extracted);\n\n // Also store for persistence\n newFeedbacks.push({\n timestamp: new Date().toISOString(),\n source: extracted.source,\n keyPoints: extracted.keyPoints,\n actionItems: extracted.actionItems,\n sourceFile: file.name,\n });\n }\n }\n } catch {\n // Failed to read agent outputs from this directory\n }\n }\n\n // Save new feedback to persistent storage\n if (newFeedbacks.length > 0) {\n saveReviewFeedback(this.projectRoot, newFeedbacks);\n }\n\n // Load persisted feedback if no new feedback found\n if (feedback.length === 0) {\n const stored = loadReviewFeedback(this.projectRoot);\n for (const s of stored.slice(0, 3)) {\n feedback.push({\n source: s.source,\n keyPoints: s.keyPoints,\n actionItems: s.actionItems,\n });\n }\n }\n\n return feedback.length > 0 ? feedback : undefined;\n }\n\n /**\n * Extract key points from a review output\n */\n private extractKeyPointsFromReview(content: string): {\n source: string;\n keyPoints: string[];\n actionItems: string[];\n } {\n const keyPoints: string[] = [];\n const actionItems: string[] = [];\n let source = 'Agent Review';\n\n // Detect review type\n if (\n content.includes('Product Manager') ||\n content.includes('product-manager')\n ) {\n source = 'Product Manager';\n } else if (\n content.includes('Staff Architect') ||\n content.includes('staff-architect')\n ) {\n source = 'Staff Architect';\n }\n\n // Extract key recommendations (look for common patterns)\n const lines = content.split('\\n');\n let inRecommendations = false;\n let inActionItems = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Detect section headers\n if (\n trimmed.toLowerCase().includes('recommendation') ||\n trimmed.toLowerCase().includes('key finding')\n ) {\n inRecommendations = true;\n inActionItems = false;\n continue;\n }\n if (\n trimmed.toLowerCase().includes('action') ||\n trimmed.toLowerCase().includes('next step') ||\n trimmed.toLowerCase().includes('priority')\n ) {\n inActionItems = true;\n inRecommendations = false;\n continue;\n }\n\n // Extract bullet points\n if (\n trimmed.startsWith('- ') ||\n trimmed.startsWith('* ') ||\n /^\\d+\\.\\s/.test(trimmed)\n ) {\n const point = trimmed.replace(/^[-*]\\s+/, '').replace(/^\\d+\\.\\s+/, '');\n if (point.length > 10 && point.length < 200) {\n if (inActionItems) {\n actionItems.push(point);\n } else if (inRecommendations) {\n keyPoints.push(point);\n }\n }\n }\n }\n\n // Limit to prevent bloat\n return {\n source,\n keyPoints: keyPoints.slice(0, 5),\n actionItems: actionItems.slice(0, 5),\n };\n }\n\n /**\n * Extract next actions from todo state and git\n */\n private async extractNextActions(): Promise<string[]> {\n const actions: string[] = [];\n\n // Check for uncommitted changes\n const gitStatus = this.getGitStatus();\n if (gitStatus.trim()) {\n actions.push('Commit pending changes');\n }\n\n // Look for TODO comments in recent files\n const recentFiles = this.getRecentlyModifiedFiles(5);\n for (const file of recentFiles) {\n try {\n const fullPath = join(this.projectRoot, file);\n if (existsSync(fullPath)) {\n const content = readFileSync(fullPath, 'utf-8');\n const todos = content.match(/\\/\\/\\s*TODO:?\\s*.+/gi) || [];\n for (const todo of todos.slice(0, 2)) {\n actions.push(todo.replace(/\\/\\/\\s*TODO:?\\s*/i, 'TODO: '));\n }\n }\n } catch {\n // Skip unreadable files\n }\n }\n\n // Check for pending tasks in .stackmemory\n const tasksFile = join(this.projectRoot, '.stackmemory', 'tasks.json');\n if (existsSync(tasksFile)) {\n try {\n const tasks = JSON.parse(readFileSync(tasksFile, 'utf-8'));\n const pending = tasks.filter(\n (t: any) => t.status === 'pending' || t.status === 'in_progress'\n );\n for (const task of pending.slice(0, 3)) {\n actions.push(task.title || task.description);\n }\n } catch {\n // Invalid tasks file\n }\n }\n\n return actions.slice(0, 8);\n }\n\n /**\n * Extract established code patterns\n */\n private async extractCodePatterns(): Promise<string[]> {\n const patterns: string[] = [];\n\n // Check ESLint config for patterns\n const eslintConfig = join(this.projectRoot, 'eslint.config.js');\n if (existsSync(eslintConfig)) {\n const content = readFileSync(eslintConfig, 'utf-8');\n if (content.includes('argsIgnorePattern')) {\n patterns.push('Underscore prefix for unused vars (_var)');\n }\n if (content.includes('ignores') && content.includes('test')) {\n patterns.push('Test files excluded from lint');\n }\n }\n\n // Check tsconfig for patterns\n const tsconfig = join(this.projectRoot, 'tsconfig.json');\n if (existsSync(tsconfig)) {\n const content = readFileSync(tsconfig, 'utf-8');\n if (content.includes('\"strict\": true')) {\n patterns.push('TypeScript strict mode enabled');\n }\n if (content.includes('ES2022') || content.includes('ESNext')) {\n patterns.push('ESM module system');\n }\n }\n\n return patterns;\n }\n\n /**\n * Get recent git commits\n */\n private getRecentCommits(count: number): string[] {\n try {\n const result = execSync(`git log --oneline -${count}`, {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n });\n return result.trim().split('\\n').filter(Boolean);\n } catch {\n return [];\n }\n }\n\n /**\n * Get current git branch\n */\n private getCurrentBranch(): string {\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n }).trim();\n } catch {\n return 'unknown';\n }\n }\n\n /**\n * Get git status\n */\n private getGitStatus(): string {\n try {\n return execSync('git status --short', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n });\n } catch {\n return '';\n }\n }\n\n /**\n * Get recently modified files\n */\n private getRecentlyModifiedFiles(count: number): string[] {\n try {\n const result = execSync(\n `git diff --name-only HEAD~10 HEAD 2>/dev/null || git diff --name-only`,\n {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n }\n );\n return result.trim().split('\\n').filter(Boolean).slice(0, count);\n } catch {\n return [];\n }\n }\n\n /**\n * Convert handoff to markdown\n */\n toMarkdown(handoff: EnhancedHandoff): string {\n const lines: string[] = [];\n\n lines.push(`# Session Handoff - ${handoff.timestamp.split('T')[0]}`);\n lines.push('');\n lines.push(`**Project**: ${handoff.project}`);\n lines.push(`**Branch**: ${handoff.branch}`);\n lines.push('');\n\n // Active Work (HIGH VALUE)\n lines.push('## Active Work');\n lines.push(`- **Building**: ${handoff.activeWork.description}`);\n lines.push(`- **Status**: ${handoff.activeWork.status}`);\n if (handoff.activeWork.keyFiles.length > 0) {\n lines.push(`- **Key files**: ${handoff.activeWork.keyFiles.join(', ')}`);\n }\n if (handoff.activeWork.progress) {\n lines.push(`- **Progress**: ${handoff.activeWork.progress}`);\n }\n lines.push('');\n\n // Decisions (HIGH VALUE)\n if (handoff.decisions.length > 0) {\n lines.push('## Key Decisions');\n for (const d of handoff.decisions) {\n lines.push(`1. **${d.what}**`);\n if (d.why) {\n lines.push(` - Rationale: ${d.why}`);\n }\n if (d.alternatives && d.alternatives.length > 0) {\n lines.push(\n ` - Alternatives considered: ${d.alternatives.join(', ')}`\n );\n }\n }\n lines.push('');\n }\n\n // Architecture (MEDIUM VALUE)\n if (handoff.architecture.keyComponents.length > 0) {\n lines.push('## Architecture Context');\n for (const c of handoff.architecture.keyComponents) {\n lines.push(`- \\`${c.file}\\`: ${c.purpose}`);\n }\n if (handoff.architecture.patterns.length > 0) {\n lines.push('');\n lines.push('**Patterns**: ' + handoff.architecture.patterns.join(', '));\n }\n lines.push('');\n }\n\n // Blockers (HIGH VALUE)\n if (handoff.blockers.length > 0) {\n lines.push('## Blockers');\n for (const b of handoff.blockers) {\n lines.push(`- **${b.issue}** [${b.status}]`);\n if (b.attempted.length > 0) {\n lines.push(` - Tried: ${b.attempted.join(', ')}`);\n }\n }\n lines.push('');\n }\n\n // Review Feedback (HIGH VALUE)\n if (handoff.reviewFeedback && handoff.reviewFeedback.length > 0) {\n lines.push('## Review Feedback');\n for (const r of handoff.reviewFeedback) {\n lines.push(`### ${r.source}`);\n if (r.keyPoints.length > 0) {\n lines.push('**Key Points**:');\n for (const p of r.keyPoints) {\n lines.push(`- ${p}`);\n }\n }\n if (r.actionItems.length > 0) {\n lines.push('**Action Items**:');\n for (const a of r.actionItems) {\n lines.push(`- ${a}`);\n }\n }\n lines.push('');\n }\n }\n\n // Next Actions (MEDIUM VALUE)\n if (handoff.nextActions.length > 0) {\n lines.push('## Next Actions');\n for (const a of handoff.nextActions) {\n lines.push(`1. ${a}`);\n }\n lines.push('');\n }\n\n // Code Patterns (LOW VALUE)\n if (handoff.codePatterns && handoff.codePatterns.length > 0) {\n lines.push('## Established Patterns');\n for (const p of handoff.codePatterns) {\n lines.push(`- ${p}`);\n }\n lines.push('');\n }\n\n lines.push('---');\n lines.push(`*Estimated tokens: ~${handoff.estimatedTokens}*`);\n lines.push(`*Generated at ${handoff.timestamp}*`);\n\n return lines.join('\\n');\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["store"]
4
+ "sourcesContent": ["/**\n * Enhanced Handoff Generator\n * Produces high-efficacy handoffs (70-85% context preservation)\n * Target: 2,000-3,000 tokens for rich context\n */\n\nimport { execSync } from 'child_process';\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs';\nimport { basename, join } from 'path';\nimport { homedir, tmpdir } from 'os';\nimport { globSync } from 'glob';\n\n// Token counting - use Anthropic's tokenizer for accurate counts\nlet countTokens: (text: string) => number;\ntry {\n // Dynamic import for CommonJS compatibility\n const tokenizer = await import('@anthropic-ai/tokenizer');\n countTokens = tokenizer.countTokens;\n} catch {\n // Fallback to estimation if tokenizer not available\n countTokens = (text: string) => Math.ceil(text.length / 3.5);\n}\n\n// Load session decisions if available\ninterface SessionDecision {\n id: string;\n what: string;\n why: string;\n alternatives?: string[];\n timestamp: string;\n category?: string;\n}\n\n// Review feedback persistence\ninterface StoredReviewFeedback {\n timestamp: string;\n source: string;\n keyPoints: string[];\n actionItems: string[];\n sourceFile?: string;\n}\n\ninterface ReviewFeedbackStore {\n feedbacks: StoredReviewFeedback[];\n lastUpdated: string;\n}\n\nfunction loadSessionDecisions(projectRoot: string): SessionDecision[] {\n const storePath = join(projectRoot, '.stackmemory', 'session-decisions.json');\n if (existsSync(storePath)) {\n try {\n const store = JSON.parse(readFileSync(storePath, 'utf-8'));\n return store.decisions || [];\n } catch {\n return [];\n }\n }\n return [];\n}\n\nfunction loadReviewFeedback(projectRoot: string): StoredReviewFeedback[] {\n const storePath = join(projectRoot, '.stackmemory', 'review-feedback.json');\n if (existsSync(storePath)) {\n try {\n const store: ReviewFeedbackStore = JSON.parse(\n readFileSync(storePath, 'utf-8')\n );\n // Return feedbacks from last 24 hours\n const cutoff = Date.now() - 24 * 60 * 60 * 1000;\n return store.feedbacks.filter(\n (f) => new Date(f.timestamp).getTime() > cutoff\n );\n } catch {\n return [];\n }\n }\n return [];\n}\n\nfunction saveReviewFeedback(\n projectRoot: string,\n feedbacks: StoredReviewFeedback[]\n): void {\n const dir = join(projectRoot, '.stackmemory');\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const storePath = join(dir, 'review-feedback.json');\n\n // Load existing and merge\n let existing: StoredReviewFeedback[] = [];\n if (existsSync(storePath)) {\n try {\n const store: ReviewFeedbackStore = JSON.parse(\n readFileSync(storePath, 'utf-8')\n );\n existing = store.feedbacks || [];\n } catch {\n // Ignore parse errors\n }\n }\n\n // Deduplicate by source + first key point\n const seen = new Set<string>();\n const merged: StoredReviewFeedback[] = [];\n\n for (const f of [...feedbacks, ...existing]) {\n const key = `${f.source}:${f.keyPoints[0] || ''}`;\n if (!seen.has(key)) {\n seen.add(key);\n merged.push(f);\n }\n }\n\n // Keep only last 20 feedbacks\n const store: ReviewFeedbackStore = {\n feedbacks: merged.slice(0, 20),\n lastUpdated: new Date().toISOString(),\n };\n\n writeFileSync(storePath, JSON.stringify(store, null, 2));\n}\n\n/**\n * Find Claude agent output directories dynamically\n */\nfunction findAgentOutputDirs(projectRoot: string): string[] {\n const dirs: string[] = [];\n\n // Try multiple locations where agent outputs might be stored\n const tmpBase = process.env['TMPDIR'] || tmpdir() || '/tmp';\n\n // Pattern 1: /tmp/claude/-path-to-project/tasks\n const projectPathEncoded = projectRoot.replace(/\\//g, '-').replace(/^-/, '');\n const pattern1 = join(tmpBase, 'claude', `*${projectPathEncoded}*`, 'tasks');\n try {\n const matches = globSync(pattern1);\n dirs.push(...matches);\n } catch {\n // Glob failed\n }\n\n // Pattern 2: /private/tmp/claude/... (macOS specific)\n if (tmpBase !== '/private/tmp') {\n const pattern2 = join(\n '/private/tmp',\n 'claude',\n `*${projectPathEncoded}*`,\n 'tasks'\n );\n try {\n const matches = globSync(pattern2);\n dirs.push(...matches);\n } catch {\n // Glob failed\n }\n }\n\n // Pattern 3: ~/.claude/projects/*/tasks (if exists)\n const homeClaudeDir = join(homedir(), '.claude', 'projects');\n if (existsSync(homeClaudeDir)) {\n try {\n const projectDirs = readdirSync(homeClaudeDir);\n for (const d of projectDirs) {\n const tasksDir = join(homeClaudeDir, d, 'tasks');\n if (existsSync(tasksDir)) {\n dirs.push(tasksDir);\n }\n }\n } catch {\n // Failed to read\n }\n }\n\n return [...new Set(dirs)]; // Deduplicate\n}\n\nexport interface EnhancedHandoff {\n // Metadata\n timestamp: string;\n project: string;\n branch: string;\n sessionDuration?: string;\n\n // What we're building (HIGH VALUE)\n activeWork: {\n description: string;\n status: 'in_progress' | 'blocked' | 'review' | 'done';\n keyFiles: string[];\n progress?: string;\n };\n\n // Decisions made (HIGH VALUE)\n decisions: Array<{\n what: string;\n why: string;\n alternatives?: string[];\n }>;\n\n // Architecture context (MEDIUM VALUE)\n architecture: {\n keyComponents: Array<{\n file: string;\n purpose: string;\n }>;\n patterns: string[];\n };\n\n // Blockers and issues (HIGH VALUE)\n blockers: Array<{\n issue: string;\n attempted: string[];\n status: 'resolved' | 'open';\n }>;\n\n // Review feedback (HIGH VALUE if present)\n reviewFeedback?: {\n source: string;\n keyPoints: string[];\n actionItems: string[];\n }[];\n\n // Next actions (MEDIUM VALUE)\n nextActions: string[];\n\n // Patterns established (LOW-MEDIUM VALUE)\n codePatterns?: string[];\n\n // Token metrics\n estimatedTokens: number;\n}\n\nexport class EnhancedHandoffGenerator {\n private projectRoot: string;\n private claudeProjectsDir: string;\n\n constructor(projectRoot: string) {\n this.projectRoot = projectRoot;\n this.claudeProjectsDir = join(homedir(), '.claude', 'projects');\n }\n\n /**\n * Generate a high-efficacy handoff\n */\n async generate(): Promise<EnhancedHandoff> {\n const handoff: EnhancedHandoff = {\n timestamp: new Date().toISOString(),\n project: basename(this.projectRoot),\n branch: this.getCurrentBranch(),\n activeWork: await this.extractActiveWork(),\n decisions: await this.extractDecisions(),\n architecture: await this.extractArchitecture(),\n blockers: await this.extractBlockers(),\n reviewFeedback: await this.extractReviewFeedback(),\n nextActions: await this.extractNextActions(),\n codePatterns: await this.extractCodePatterns(),\n estimatedTokens: 0,\n };\n\n // Calculate estimated tokens\n const markdown = this.toMarkdown(handoff);\n handoff.estimatedTokens = countTokens(markdown);\n\n return handoff;\n }\n\n /**\n * Extract what we're currently building from git and recent files\n */\n private async extractActiveWork(): Promise<EnhancedHandoff['activeWork']> {\n // Get recent commits to understand current work\n const recentCommits = this.getRecentCommits(5);\n const recentFiles = this.getRecentlyModifiedFiles(10);\n\n // Try to infer the active work from commit messages\n let description = 'Unknown - check git log for context';\n let status: EnhancedHandoff['activeWork']['status'] = 'in_progress';\n\n if (recentCommits.length > 0) {\n // Use most recent commit as indicator\n const lastCommit = recentCommits[0];\n if (lastCommit.includes('feat:') || lastCommit.includes('implement')) {\n description = lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n } else if (lastCommit.includes('fix:')) {\n description = 'Bug fix: ' + lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n } else if (\n lastCommit.includes('chore:') ||\n lastCommit.includes('refactor:')\n ) {\n description = lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n } else {\n description = lastCommit.replace(/^[a-f0-9]+\\s+/, '');\n }\n }\n\n // Check for blocking indicators\n const gitStatus = this.getGitStatus();\n if (gitStatus.includes('conflict')) {\n status = 'blocked';\n }\n\n return {\n description,\n status,\n keyFiles: recentFiles.slice(0, 5),\n progress:\n recentCommits.length > 0\n ? `${recentCommits.length} commits in current session`\n : undefined,\n };\n }\n\n /**\n * Extract decisions from session store, git commits, and decision logs\n */\n private async extractDecisions(): Promise<EnhancedHandoff['decisions']> {\n const decisions: EnhancedHandoff['decisions'] = [];\n\n // First, load session decisions (highest priority - explicitly recorded)\n const sessionDecisions = loadSessionDecisions(this.projectRoot);\n for (const d of sessionDecisions) {\n decisions.push({\n what: d.what,\n why: d.why,\n alternatives: d.alternatives,\n });\n }\n\n // Then look for decision markers in recent commits\n const commits = this.getRecentCommits(20);\n for (const commit of commits) {\n // Look for decision-like patterns\n if (\n commit.toLowerCase().includes('use ') ||\n commit.toLowerCase().includes('switch to ') ||\n commit.toLowerCase().includes('default to ') ||\n (commit.toLowerCase().includes('make ') &&\n commit.toLowerCase().includes('optional'))\n ) {\n // Avoid duplicates\n const commitText = commit.replace(/^[a-f0-9]+\\s+/, '');\n if (!decisions.some((d) => d.what.includes(commitText.slice(0, 30)))) {\n decisions.push({\n what: commitText,\n why: 'See commit for details',\n });\n }\n }\n }\n\n // Check for a decisions file\n const decisionsFile = join(\n this.projectRoot,\n '.stackmemory',\n 'decisions.md'\n );\n if (existsSync(decisionsFile)) {\n const content = readFileSync(decisionsFile, 'utf-8');\n const parsed = this.parseDecisionsFile(content);\n decisions.push(...parsed);\n }\n\n return decisions.slice(0, 10); // Limit to prevent bloat\n }\n\n /**\n * Parse a decisions.md file\n */\n private parseDecisionsFile(content: string): EnhancedHandoff['decisions'] {\n const decisions: EnhancedHandoff['decisions'] = [];\n const lines = content.split('\\n');\n\n let currentDecision: {\n what: string;\n why: string;\n alternatives?: string[];\n } | null = null;\n\n for (const line of lines) {\n if (line.startsWith('## ') || line.startsWith('### ')) {\n if (currentDecision) {\n decisions.push(currentDecision);\n }\n currentDecision = { what: line.replace(/^#+\\s+/, ''), why: '' };\n } else if (currentDecision && line.toLowerCase().includes('rationale:')) {\n currentDecision.why = line.replace(/rationale:\\s*/i, '').trim();\n } else if (currentDecision && line.toLowerCase().includes('why:')) {\n currentDecision.why = line.replace(/why:\\s*/i, '').trim();\n } else if (\n currentDecision &&\n line.toLowerCase().includes('alternatives:')\n ) {\n currentDecision.alternatives = [];\n } else if (currentDecision?.alternatives && line.trim().startsWith('-')) {\n currentDecision.alternatives.push(line.replace(/^\\s*-\\s*/, '').trim());\n }\n }\n\n if (currentDecision) {\n decisions.push(currentDecision);\n }\n\n return decisions;\n }\n\n /**\n * Extract architecture context from key files\n */\n private async extractArchitecture(): Promise<\n EnhancedHandoff['architecture']\n > {\n const keyComponents: EnhancedHandoff['architecture']['keyComponents'] = [];\n const patterns: string[] = [];\n\n // Find recently modified TypeScript/JavaScript files\n const recentFiles = this.getRecentlyModifiedFiles(20);\n const codeFiles = recentFiles.filter(\n (f) => f.endsWith('.ts') || f.endsWith('.js') || f.endsWith('.tsx')\n );\n\n for (const file of codeFiles.slice(0, 8)) {\n const purpose = this.inferFilePurpose(file);\n if (purpose) {\n keyComponents.push({ file, purpose });\n }\n }\n\n // Detect patterns from file structure\n if (codeFiles.some((f) => f.includes('/daemon/'))) {\n patterns.push('Daemon/background process pattern');\n }\n if (codeFiles.some((f) => f.includes('/cli/'))) {\n patterns.push('CLI command pattern');\n }\n if (\n codeFiles.some((f) => f.includes('.test.') || f.includes('__tests__'))\n ) {\n patterns.push('Test files present');\n }\n if (codeFiles.some((f) => f.includes('/core/'))) {\n patterns.push('Core/domain separation');\n }\n\n return { keyComponents, patterns };\n }\n\n /**\n * Infer purpose from file name and path\n */\n private inferFilePurpose(filePath: string): string | null {\n const name = basename(filePath).replace(/\\.(ts|js|tsx)$/, '');\n const path = filePath.toLowerCase();\n\n if (path.includes('daemon')) return 'Background daemon/service';\n if (path.includes('cli/command')) return 'CLI command handler';\n if (path.includes('config')) return 'Configuration management';\n if (path.includes('storage')) return 'Data storage layer';\n if (path.includes('handoff')) return 'Session handoff logic';\n if (path.includes('service')) return 'Service orchestration';\n if (path.includes('manager')) return 'Resource/state management';\n if (path.includes('handler')) return 'Event/request handler';\n if (path.includes('util') || path.includes('helper'))\n return 'Utility functions';\n if (path.includes('types') || path.includes('interface'))\n return 'Type definitions';\n if (path.includes('test')) return null; // Skip test files\n if (name.includes('-')) {\n return name\n .split('-')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n }\n return null;\n }\n\n /**\n * Extract blockers from git status and recent errors\n */\n private async extractBlockers(): Promise<EnhancedHandoff['blockers']> {\n const blockers: EnhancedHandoff['blockers'] = [];\n\n // Check for merge conflicts\n const gitStatus = this.getGitStatus();\n if (gitStatus.includes('UU ') || gitStatus.includes('both modified')) {\n blockers.push({\n issue: 'Merge conflict detected',\n attempted: ['Check git status for affected files'],\n status: 'open',\n });\n }\n\n // Check for failing tests\n try {\n const testResult = execSync('npm test 2>&1 || true', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n timeout: 30000,\n });\n if (testResult.includes('FAIL') || testResult.includes('failed')) {\n const failCount = (testResult.match(/(\\d+) failed/i) || ['', '?'])[1];\n blockers.push({\n issue: `Test failures: ${failCount} tests failing`,\n attempted: ['Run npm test for details'],\n status: 'open',\n });\n }\n } catch {\n // Test command failed - might indicate issues\n }\n\n // Check for lint errors\n try {\n const lintResult = execSync('npm run lint 2>&1 || true', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n timeout: 30000,\n });\n if (lintResult.includes('error') && !lintResult.includes('0 errors')) {\n blockers.push({\n issue: 'Lint errors present',\n attempted: ['Run npm run lint for details'],\n status: 'open',\n });\n }\n } catch {\n // Lint command failed\n }\n\n return blockers;\n }\n\n /**\n * Extract review feedback from agent output files and persisted storage\n */\n private async extractReviewFeedback(): Promise<\n EnhancedHandoff['reviewFeedback']\n > {\n const feedback: EnhancedHandoff['reviewFeedback'] = [];\n const newFeedbacks: StoredReviewFeedback[] = [];\n\n // Find agent output directories dynamically\n const outputDirs = findAgentOutputDirs(this.projectRoot);\n\n for (const tmpDir of outputDirs) {\n if (!existsSync(tmpDir)) continue;\n\n try {\n const files = readdirSync(tmpDir).filter((f) => f.endsWith('.output'));\n const recentFiles = files\n .map((f) => ({\n name: f,\n path: join(tmpDir, f),\n stat: statSync(join(tmpDir, f)),\n }))\n .filter((f) => Date.now() - f.stat.mtimeMs < 3600000) // Last hour\n .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs)\n .slice(0, 3);\n\n for (const file of recentFiles) {\n const content = readFileSync(file.path, 'utf-8');\n const extracted = this.extractKeyPointsFromReview(content);\n if (extracted.keyPoints.length > 0) {\n feedback.push(extracted);\n\n // Also store for persistence\n newFeedbacks.push({\n timestamp: new Date().toISOString(),\n source: extracted.source,\n keyPoints: extracted.keyPoints,\n actionItems: extracted.actionItems,\n sourceFile: file.name,\n });\n }\n }\n } catch {\n // Failed to read agent outputs from this directory\n }\n }\n\n // Save new feedback to persistent storage\n if (newFeedbacks.length > 0) {\n saveReviewFeedback(this.projectRoot, newFeedbacks);\n }\n\n // Load persisted feedback if no new feedback found\n if (feedback.length === 0) {\n const stored = loadReviewFeedback(this.projectRoot);\n for (const s of stored.slice(0, 3)) {\n feedback.push({\n source: s.source,\n keyPoints: s.keyPoints,\n actionItems: s.actionItems,\n });\n }\n }\n\n return feedback.length > 0 ? feedback : undefined;\n }\n\n /**\n * Extract key points from a review output\n */\n private extractKeyPointsFromReview(content: string): {\n source: string;\n keyPoints: string[];\n actionItems: string[];\n } {\n const keyPoints: string[] = [];\n const actionItems: string[] = [];\n let source = 'Agent Review';\n\n // Detect review type\n if (\n content.includes('Product Manager') ||\n content.includes('product-manager')\n ) {\n source = 'Product Manager';\n } else if (\n content.includes('Staff Architect') ||\n content.includes('staff-architect')\n ) {\n source = 'Staff Architect';\n }\n\n // Extract key recommendations (look for common patterns)\n const lines = content.split('\\n');\n let inRecommendations = false;\n let inActionItems = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Detect section headers\n if (\n trimmed.toLowerCase().includes('recommendation') ||\n trimmed.toLowerCase().includes('key finding')\n ) {\n inRecommendations = true;\n inActionItems = false;\n continue;\n }\n if (\n trimmed.toLowerCase().includes('action') ||\n trimmed.toLowerCase().includes('next step') ||\n trimmed.toLowerCase().includes('priority')\n ) {\n inActionItems = true;\n inRecommendations = false;\n continue;\n }\n\n // Extract bullet points\n if (\n trimmed.startsWith('- ') ||\n trimmed.startsWith('* ') ||\n /^\\d+\\.\\s/.test(trimmed)\n ) {\n const point = trimmed.replace(/^[-*]\\s+/, '').replace(/^\\d+\\.\\s+/, '');\n if (point.length > 10 && point.length < 200) {\n if (inActionItems) {\n actionItems.push(point);\n } else if (inRecommendations) {\n keyPoints.push(point);\n }\n }\n }\n }\n\n // Limit to prevent bloat\n return {\n source,\n keyPoints: keyPoints.slice(0, 5),\n actionItems: actionItems.slice(0, 5),\n };\n }\n\n /**\n * Extract next actions from todo state and git\n */\n private async extractNextActions(): Promise<string[]> {\n const actions: string[] = [];\n\n // Check for uncommitted changes\n const gitStatus = this.getGitStatus();\n if (gitStatus.trim()) {\n actions.push('Commit pending changes');\n }\n\n // Look for TODO comments in recent files\n const recentFiles = this.getRecentlyModifiedFiles(5);\n for (const file of recentFiles) {\n try {\n const fullPath = join(this.projectRoot, file);\n if (existsSync(fullPath)) {\n const content = readFileSync(fullPath, 'utf-8');\n const todos = content.match(/\\/\\/\\s*TODO:?\\s*.+/gi) || [];\n for (const todo of todos.slice(0, 2)) {\n actions.push(todo.replace(/\\/\\/\\s*TODO:?\\s*/i, 'TODO: '));\n }\n }\n } catch {\n // Skip unreadable files\n }\n }\n\n // Check for pending tasks in .stackmemory\n const tasksFile = join(this.projectRoot, '.stackmemory', 'tasks.json');\n if (existsSync(tasksFile)) {\n try {\n const tasks = JSON.parse(readFileSync(tasksFile, 'utf-8'));\n const pending = tasks.filter(\n (t: any) => t.status === 'pending' || t.status === 'in_progress'\n );\n for (const task of pending.slice(0, 3)) {\n actions.push(task.title || task.description);\n }\n } catch {\n // Invalid tasks file\n }\n }\n\n return actions.slice(0, 8);\n }\n\n /**\n * Extract established code patterns\n */\n private async extractCodePatterns(): Promise<string[]> {\n const patterns: string[] = [];\n\n // Check ESLint config for patterns\n const eslintConfig = join(this.projectRoot, 'eslint.config.js');\n if (existsSync(eslintConfig)) {\n const content = readFileSync(eslintConfig, 'utf-8');\n if (content.includes('argsIgnorePattern')) {\n patterns.push('Underscore prefix for unused vars (_var)');\n }\n if (content.includes('ignores') && content.includes('test')) {\n patterns.push('Test files excluded from lint');\n }\n }\n\n // Check tsconfig for patterns\n const tsconfig = join(this.projectRoot, 'tsconfig.json');\n if (existsSync(tsconfig)) {\n const content = readFileSync(tsconfig, 'utf-8');\n if (content.includes('\"strict\": true')) {\n patterns.push('TypeScript strict mode enabled');\n }\n if (content.includes('ES2022') || content.includes('ESNext')) {\n patterns.push('ESM module system');\n }\n }\n\n return patterns;\n }\n\n /**\n * Get recent git commits\n */\n private getRecentCommits(count: number): string[] {\n try {\n const result = execSync(`git log --oneline -${count}`, {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n });\n return result.trim().split('\\n').filter(Boolean);\n } catch {\n return [];\n }\n }\n\n /**\n * Get current git branch\n */\n private getCurrentBranch(): string {\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n }).trim();\n } catch {\n return 'unknown';\n }\n }\n\n /**\n * Get git status\n */\n private getGitStatus(): string {\n try {\n return execSync('git status --short', {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n });\n } catch {\n return '';\n }\n }\n\n /**\n * Get recently modified files\n */\n private getRecentlyModifiedFiles(count: number): string[] {\n try {\n const result = execSync(\n `git diff --name-only HEAD~10 HEAD 2>/dev/null || git diff --name-only`,\n {\n encoding: 'utf-8',\n cwd: this.projectRoot,\n }\n );\n return result.trim().split('\\n').filter(Boolean).slice(0, count);\n } catch {\n return [];\n }\n }\n\n /**\n * Convert handoff to markdown (verbose format)\n */\n toMarkdown(handoff: EnhancedHandoff): string {\n const lines: string[] = [];\n\n lines.push(`# Session Handoff - ${handoff.timestamp.split('T')[0]}`);\n lines.push('');\n lines.push(`**Project**: ${handoff.project}`);\n lines.push(`**Branch**: ${handoff.branch}`);\n lines.push('');\n\n // Active Work (HIGH VALUE)\n lines.push('## Active Work');\n lines.push(`- **Building**: ${handoff.activeWork.description}`);\n lines.push(`- **Status**: ${handoff.activeWork.status}`);\n if (handoff.activeWork.keyFiles.length > 0) {\n lines.push(`- **Key files**: ${handoff.activeWork.keyFiles.join(', ')}`);\n }\n if (handoff.activeWork.progress) {\n lines.push(`- **Progress**: ${handoff.activeWork.progress}`);\n }\n lines.push('');\n\n // Decisions (HIGH VALUE)\n if (handoff.decisions.length > 0) {\n lines.push('## Key Decisions');\n for (const d of handoff.decisions) {\n lines.push(`1. **${d.what}**`);\n if (d.why) {\n lines.push(` - Rationale: ${d.why}`);\n }\n if (d.alternatives && d.alternatives.length > 0) {\n lines.push(\n ` - Alternatives considered: ${d.alternatives.join(', ')}`\n );\n }\n }\n lines.push('');\n }\n\n // Architecture (MEDIUM VALUE)\n if (handoff.architecture.keyComponents.length > 0) {\n lines.push('## Architecture Context');\n for (const c of handoff.architecture.keyComponents) {\n lines.push(`- \\`${c.file}\\`: ${c.purpose}`);\n }\n if (handoff.architecture.patterns.length > 0) {\n lines.push('');\n lines.push('**Patterns**: ' + handoff.architecture.patterns.join(', '));\n }\n lines.push('');\n }\n\n // Blockers (HIGH VALUE)\n if (handoff.blockers.length > 0) {\n lines.push('## Blockers');\n for (const b of handoff.blockers) {\n lines.push(`- **${b.issue}** [${b.status}]`);\n if (b.attempted.length > 0) {\n lines.push(` - Tried: ${b.attempted.join(', ')}`);\n }\n }\n lines.push('');\n }\n\n // Review Feedback (HIGH VALUE)\n if (handoff.reviewFeedback && handoff.reviewFeedback.length > 0) {\n lines.push('## Review Feedback');\n for (const r of handoff.reviewFeedback) {\n lines.push(`### ${r.source}`);\n if (r.keyPoints.length > 0) {\n lines.push('**Key Points**:');\n for (const p of r.keyPoints) {\n lines.push(`- ${p}`);\n }\n }\n if (r.actionItems.length > 0) {\n lines.push('**Action Items**:');\n for (const a of r.actionItems) {\n lines.push(`- ${a}`);\n }\n }\n lines.push('');\n }\n }\n\n // Next Actions (MEDIUM VALUE)\n if (handoff.nextActions.length > 0) {\n lines.push('## Next Actions');\n for (const a of handoff.nextActions) {\n lines.push(`1. ${a}`);\n }\n lines.push('');\n }\n\n // Code Patterns (LOW VALUE)\n if (handoff.codePatterns && handoff.codePatterns.length > 0) {\n lines.push('## Established Patterns');\n for (const p of handoff.codePatterns) {\n lines.push(`- ${p}`);\n }\n lines.push('');\n }\n\n lines.push('---');\n lines.push(`*Estimated tokens: ~${handoff.estimatedTokens}*`);\n lines.push(`*Generated at ${handoff.timestamp}*`);\n\n return lines.join('\\n');\n }\n\n /**\n * Convert handoff to compact format (~50% smaller)\n * Optimized for minimal context window usage\n */\n toCompact(handoff: EnhancedHandoff): string {\n const lines: string[] = [];\n\n // Header: single line\n lines.push(`# Handoff: ${handoff.project}@${handoff.branch}`);\n\n // Active Work: condensed\n const status =\n handoff.activeWork.status === 'in_progress'\n ? 'WIP'\n : handoff.activeWork.status;\n lines.push(`## Work: ${handoff.activeWork.description} [${status}]`);\n if (handoff.activeWork.keyFiles.length > 0) {\n // Use basenames only, limit to 5\n const files = handoff.activeWork.keyFiles\n .slice(0, 5)\n .map((f) => basename(f))\n .join(', ');\n const progress = handoff.activeWork.progress\n ? ` (${handoff.activeWork.progress.replace(' in current session', '')})`\n : '';\n lines.push(`Files: ${files}${progress}`);\n }\n\n // Decisions: single line each with arrow notation\n if (handoff.decisions.length > 0) {\n lines.push('');\n lines.push('## Decisions');\n for (const d of handoff.decisions.slice(0, 7)) {\n // Truncate long decisions\n const what = d.what.length > 40 ? d.what.slice(0, 37) + '...' : d.what;\n const why = d.why ? ` \u2192 ${d.why.slice(0, 50)}` : '';\n lines.push(`- ${what}${why}`);\n }\n }\n\n // Blockers: terse format\n if (handoff.blockers.length > 0) {\n lines.push('');\n lines.push('## Blockers');\n for (const b of handoff.blockers) {\n const status = b.status === 'open' ? '!' : '\u2713';\n const tried = b.attempted.length > 0 ? ` \u2192 ${b.attempted[0]}` : '';\n lines.push(`${status} ${b.issue}${tried}`);\n }\n }\n\n // Review Feedback: only if present, condensed\n if (handoff.reviewFeedback && handoff.reviewFeedback.length > 0) {\n lines.push('');\n lines.push('## Feedback');\n for (const r of handoff.reviewFeedback.slice(0, 2)) {\n lines.push(`[${r.source}]`);\n for (const p of r.keyPoints.slice(0, 3)) {\n lines.push(`- ${p.slice(0, 60)}`);\n }\n for (const a of r.actionItems.slice(0, 2)) {\n lines.push(`\u2192 ${a.slice(0, 60)}`);\n }\n }\n }\n\n // Next Actions: only top 3\n if (handoff.nextActions.length > 0) {\n lines.push('');\n lines.push('## Next');\n for (const a of handoff.nextActions.slice(0, 3)) {\n lines.push(`- ${a.slice(0, 60)}`);\n }\n }\n\n // Skip: Architecture, Patterns (can be inferred from codebase)\n\n // Compact footer\n lines.push('');\n lines.push(`---`);\n lines.push(\n `~${handoff.estimatedTokens} tokens | ${handoff.timestamp.split('T')[0]}`\n );\n\n return lines.join('\\n');\n }\n\n /**\n * Convert handoff to ultra-compact pipe-delimited format (~90% smaller)\n * Optimized for minimal token usage while preserving critical context\n * Target: ~100-150 tokens\n */\n toUltraCompact(handoff: EnhancedHandoff): string {\n const lines: string[] = [];\n\n // Header: [H]project@branch|status|commits\n const status =\n handoff.activeWork.status === 'in_progress'\n ? 'WIP'\n : handoff.activeWork.status;\n const commitCount = handoff.activeWork.progress?.match(/(\\d+)/)?.[1] || '0';\n lines.push(\n `[H]${handoff.project}@${handoff.branch}|${status}|${commitCount}c`\n );\n\n // Files: [F]file1,file2,file3 (basenames only, max 5)\n if (handoff.activeWork.keyFiles.length > 0) {\n const files = handoff.activeWork.keyFiles\n .slice(0, 5)\n .map((f) => basename(f).replace(/\\.(ts|js|tsx|jsx)$/, ''))\n .join(',');\n lines.push(`[F]${files}`);\n }\n\n // Decisions: [D]decision1\u2192why|decision2\u2192why (max 5, truncated)\n if (handoff.decisions.length > 0) {\n const decisions = handoff.decisions\n .slice(0, 5)\n .map((d) => {\n const what = d.what.slice(0, 25).replace(/\\|/g, '/');\n const why = d.why ? `\u2192${d.why.slice(0, 20)}` : '';\n return `${what}${why}`;\n })\n .join('|');\n lines.push(`[D]${decisions}`);\n }\n\n // Blockers: [B]!issue1\u2192tried|!issue2 (! = open, \u2713 = resolved)\n if (handoff.blockers.length > 0) {\n const blockers = handoff.blockers\n .slice(0, 3)\n .map((b) => {\n const marker = b.status === 'open' ? '!' : '\u2713';\n const issue = b.issue.slice(0, 20).replace(/\\|/g, '/');\n const tried =\n b.attempted.length > 0 ? `\u2192${b.attempted[0].slice(0, 15)}` : '';\n return `${marker}${issue}${tried}`;\n })\n .join('|');\n lines.push(`[B]${blockers}`);\n }\n\n // Next actions: [N]action1|action2 (max 3)\n if (handoff.nextActions.length > 0) {\n const actions = handoff.nextActions\n .slice(0, 3)\n .map((a) => a.slice(0, 25).replace(/\\|/g, '/'))\n .join('|');\n lines.push(`[N]${actions}`);\n }\n\n // Footer: ~tokens|date\n const ultraCompactContent = lines.join('\\n');\n const tokens = countTokens(ultraCompactContent);\n lines.push(`~${tokens}t|${handoff.timestamp.split('T')[0]}`);\n\n return lines.join('\\n');\n }\n\n /**\n * Auto-select format based on context budget and content complexity\n * Returns: 'ultra' | 'compact' | 'verbose'\n */\n selectFormat(\n handoff: EnhancedHandoff,\n contextBudget?: number\n ): 'ultra' | 'compact' | 'verbose' {\n // If explicit budget provided, use thresholds\n if (contextBudget !== undefined) {\n if (contextBudget < 500) return 'ultra';\n if (contextBudget < 2000) return 'compact';\n return 'verbose';\n }\n\n // Auto-select based on content complexity\n const complexity =\n handoff.decisions.length +\n handoff.blockers.length +\n (handoff.reviewFeedback?.length || 0) * 2 +\n handoff.nextActions.length;\n\n // Simple sessions: ultra-compact is sufficient\n if (complexity <= 3 && handoff.activeWork.keyFiles.length <= 3) {\n return 'ultra';\n }\n\n // Complex sessions: need more detail\n if (\n complexity > 8 ||\n (handoff.reviewFeedback && handoff.reviewFeedback.length > 1)\n ) {\n return 'verbose';\n }\n\n // Default: compact\n return 'compact';\n }\n\n /**\n * Generate handoff in auto-selected format\n */\n toAutoFormat(handoff: EnhancedHandoff, contextBudget?: number): string {\n const format = this.selectFormat(handoff, contextBudget);\n switch (format) {\n case 'ultra':\n return this.toUltraCompact(handoff);\n case 'verbose':\n return this.toMarkdown(handoff);\n default:\n return this.toCompact(handoff);\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["store", "status"]
7
7
  }
@@ -587,7 +587,11 @@ class LinearClient {
587
587
  try {
588
588
  const result = await this.graphql(query, { issueId });
589
589
  return result.issue;
590
- } catch {
590
+ } catch (error) {
591
+ logger.debug("Failed to fetch issue by ID", {
592
+ issueId,
593
+ error: error instanceof Error ? error.message : String(error)
594
+ });
591
595
  return null;
592
596
  }
593
597
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/integrations/linear/client.ts"],
4
- "sourcesContent": ["/**\n * Linear API Client for StackMemory\n * Handles bi-directional sync with Linear's GraphQL API\n */\n\nimport { logger } from '../../core/monitoring/logger.js';\nimport { IntegrationError, ErrorCode } from '../../core/errors/index.js';\n\nexport interface LinearConfig {\n apiKey: string;\n teamId?: string;\n webhookSecret?: string;\n baseUrl?: string;\n // If true, send Authorization header as `Bearer <apiKey>` (OAuth access token)\n useBearer?: boolean;\n // Optional callback to refresh token on 401 and return the new access token\n onUnauthorized?: () => Promise<string>;\n}\n\nexport interface LinearIssue {\n id: string;\n identifier: string; // Like \"SM-123\"\n title: string;\n description?: string;\n state: {\n id: string;\n name: string;\n type: 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled';\n };\n priority: number; // 0-4 (0=none, 1=urgent, 2=high, 3=medium, 4=low)\n assignee?: {\n id: string;\n name: string;\n email: string;\n };\n estimate?: number; // Story points\n labels: Array<{\n id: string;\n name: string;\n }>;\n createdAt: string;\n updatedAt: string;\n url: string;\n}\n\nexport interface LinearCreateIssueInput {\n title: string;\n description?: string;\n teamId: string;\n priority?: number;\n estimate?: number;\n labelIds?: string[];\n}\n\ninterface RateLimitState {\n remaining: number;\n resetAt: number;\n retryAfter: number;\n}\n\nexport class LinearClient {\n private config: LinearConfig;\n private baseUrl: string;\n private rateLimitState: RateLimitState = {\n remaining: 1500, // Linear's default limit\n resetAt: Date.now() + 3600000,\n retryAfter: 0,\n };\n private requestQueue: Array<() => Promise<void>> = [];\n private isProcessingQueue = false;\n private minRequestInterval = 100; // Minimum ms between requests\n private lastRequestTime = 0;\n\n constructor(config: LinearConfig) {\n this.config = config;\n this.baseUrl = config.baseUrl || 'https://api.linear.app';\n\n if (!config.apiKey) {\n throw new IntegrationError(\n 'Linear API key is required',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n }\n\n /**\n * Wait for rate limit to reset if needed\n */\n private async waitForRateLimit(): Promise<void> {\n const now = Date.now();\n\n // Check if we're in a retry-after period\n if (this.rateLimitState.retryAfter > now) {\n const waitTime = this.rateLimitState.retryAfter - now;\n logger.warn(`Rate limited, waiting ${Math.ceil(waitTime / 1000)}s`);\n await this.sleep(waitTime);\n }\n\n // Check if we've exhausted our rate limit\n if (this.rateLimitState.remaining <= 5) {\n if (this.rateLimitState.resetAt > now) {\n const waitTime = this.rateLimitState.resetAt - now;\n logger.warn(\n `Rate limit nearly exhausted, waiting ${Math.ceil(waitTime / 1000)}s for reset`\n );\n await this.sleep(Math.min(waitTime, 60000)); // Max 60s wait\n }\n }\n\n // Ensure minimum interval between requests\n const timeSinceLastRequest = now - this.lastRequestTime;\n if (timeSinceLastRequest < this.minRequestInterval) {\n await this.sleep(this.minRequestInterval - timeSinceLastRequest);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Update rate limit state from response headers\n */\n private updateRateLimitState(response: Response): void {\n const remaining = response.headers.get('x-ratelimit-remaining');\n const reset = response.headers.get('x-ratelimit-reset');\n const retryAfter = response.headers.get('retry-after');\n\n if (remaining !== null) {\n this.rateLimitState.remaining = parseInt(remaining, 10);\n }\n if (reset !== null) {\n this.rateLimitState.resetAt = parseInt(reset, 10) * 1000;\n }\n if (retryAfter !== null) {\n this.rateLimitState.retryAfter =\n Date.now() + parseInt(retryAfter, 10) * 1000;\n }\n }\n\n /**\n * Execute GraphQL query against Linear API with rate limiting\n */\n private async graphql<T>(\n query: string,\n variables?: Record<string, unknown>,\n retries = 3,\n allowAuthRefresh = true\n ): Promise<T> {\n // Wait for rate limit before making request\n await this.waitForRateLimit();\n\n this.lastRequestTime = Date.now();\n\n const authHeader = this.config.useBearer\n ? `Bearer ${this.config.apiKey}`\n : this.config.apiKey;\n\n let response = await fetch(`${this.baseUrl}/graphql`, {\n method: 'POST',\n headers: {\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query,\n variables,\n }),\n });\n\n // Update rate limit state from response\n this.updateRateLimitState(response);\n\n // Handle unauthorized (e.g., expired OAuth token)\n if (\n response.status === 401 &&\n this.config.onUnauthorized &&\n allowAuthRefresh\n ) {\n try {\n const newToken = await this.config.onUnauthorized();\n // Update local config and retry once without further auth refresh\n this.config.apiKey = newToken;\n const retryHeader = this.config.useBearer\n ? `Bearer ${newToken}`\n : newToken;\n response = await fetch(`${this.baseUrl}/graphql`, {\n method: 'POST',\n headers: {\n Authorization: retryHeader,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ query, variables }),\n });\n this.updateRateLimitState(response);\n } catch (e: unknown) {\n // Fall through to standard error handling\n }\n }\n\n // Handle rate limiting with exponential backoff\n if (response.status === 429) {\n if (retries > 0) {\n const retryAfter = response.headers.get('retry-after');\n const waitTime = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n logger.warn(\n `Rate limited (429), retrying in ${waitTime / 1000}s (${retries} retries left)`\n );\n this.rateLimitState.retryAfter = Date.now() + waitTime;\n await this.sleep(waitTime);\n return this.graphql<T>(query, variables, retries - 1, allowAuthRefresh);\n }\n throw new IntegrationError(\n 'Linear API rate limit exceeded after retries',\n ErrorCode.LINEAR_API_ERROR,\n { retries: 0 }\n );\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n // Don't log 401/403 - expected when not authenticated\n if (response.status !== 401 && response.status !== 403) {\n logger.error(\n 'Linear API error response:',\n new Error(`${response.status}: ${errorText}`)\n );\n }\n throw new IntegrationError(\n `Linear API error: ${response.status} ${response.statusText}`,\n ErrorCode.LINEAR_API_ERROR,\n {\n status: response.status,\n statusText: response.statusText,\n body: errorText,\n }\n );\n }\n\n const result = (await response.json()) as {\n data?: T;\n errors?: Array<{ message: string }>;\n };\n\n if (result.errors) {\n // Check for rate limit errors in GraphQL response\n const rateLimitError = result.errors.find(\n (e) =>\n e.message.toLowerCase().includes('rate limit') ||\n e.message.toLowerCase().includes('usage limit')\n );\n\n if (rateLimitError && retries > 0) {\n const waitTime = 60000; // Default 60s wait for GraphQL rate limit errors\n logger.warn(\n `GraphQL rate limit error, retrying in ${waitTime / 1000}s (${retries} retries left)`\n );\n this.rateLimitState.retryAfter = Date.now() + waitTime;\n await this.sleep(waitTime);\n return this.graphql<T>(query, variables, retries - 1);\n }\n\n logger.error('Linear GraphQL errors:', { errors: result.errors });\n throw new IntegrationError(\n `Linear GraphQL error: ${result.errors[0].message}`,\n ErrorCode.LINEAR_API_ERROR,\n { errors: result.errors }\n );\n }\n\n return result.data as T;\n }\n\n /**\n * Create a new issue in Linear\n */\n async createIssue(input: LinearCreateIssueInput): Promise<LinearIssue> {\n const mutation = `\n mutation CreateIssue($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueCreate: {\n success: boolean;\n issue: LinearIssue;\n };\n }>(mutation, { input });\n\n if (!result.issueCreate.success) {\n throw new IntegrationError(\n 'Failed to create Linear issue',\n ErrorCode.LINEAR_API_ERROR,\n { input }\n );\n }\n\n return result.issueCreate.issue;\n }\n\n /**\n * Update an existing Linear issue\n */\n async updateIssue(\n issueId: string,\n updates: Partial<LinearCreateIssueInput> & { stateId?: string }\n ): Promise<LinearIssue> {\n const mutation = `\n mutation UpdateIssue($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueUpdate: {\n success: boolean;\n issue: LinearIssue;\n };\n }>(mutation, { id: issueId, input: updates });\n\n if (!result.issueUpdate.success) {\n throw new IntegrationError(\n `Failed to update Linear issue ${issueId}`,\n ErrorCode.LINEAR_API_ERROR,\n { issueId, updates }\n );\n }\n\n return result.issueUpdate.issue;\n }\n\n /**\n * Get issue by ID\n */\n async getIssue(issueId: string): Promise<LinearIssue | null> {\n const query = `\n query GetIssue($id: String!) {\n issue(id: $id) {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n `;\n\n const result = await this.graphql<{\n issue: LinearIssue | null;\n }>(query, { id: issueId });\n\n return result.issue;\n }\n\n /**\n * Search for issues by identifier (e.g., \"SM-123\")\n */\n async findIssueByIdentifier(identifier: string): Promise<LinearIssue | null> {\n const query = `\n query FindIssue($filter: IssueFilter!) {\n issues(filter: $filter, first: 1) {\n nodes {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issues: {\n nodes: LinearIssue[];\n };\n }>(query, {\n filter: {\n number: {\n eq: parseInt(identifier.split('-')[1] || '0') || 0,\n },\n },\n });\n\n return result.issues.nodes[0] || null;\n }\n\n /**\n * Get team information\n */\n async getTeam(\n teamId?: string\n ): Promise<{ id: string; name: string; key: string }> {\n const query = teamId\n ? `\n query GetTeam($id: String!) {\n team(id: $id) {\n id\n name\n key\n }\n }\n `\n : `\n query GetTeams {\n teams(first: 1) {\n nodes {\n id\n name\n key\n }\n }\n }\n `;\n\n if (teamId) {\n const result = await this.graphql<{\n team: { id: string; name: string; key: string };\n }>(query, { id: teamId });\n if (!result.team) {\n throw new IntegrationError(\n `Team ${teamId} not found`,\n ErrorCode.LINEAR_API_ERROR,\n { teamId }\n );\n }\n return result.team;\n } else {\n const result = await this.graphql<{\n teams: {\n nodes: Array<{ id: string; name: string; key: string }>;\n };\n }>(query);\n\n if (result.teams.nodes.length === 0) {\n throw new IntegrationError(\n 'No teams found',\n ErrorCode.LINEAR_API_ERROR\n );\n }\n\n return result.teams.nodes[0]!;\n }\n }\n\n /**\n * Get workflow states for a team\n */\n async getWorkflowStates(teamId: string): Promise<\n Array<{\n id: string;\n name: string;\n type: 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled';\n color: string;\n }>\n > {\n const query = `\n query GetWorkflowStates($teamId: String!) {\n team(id: $teamId) {\n states {\n nodes {\n id\n name\n type\n color\n }\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n team: {\n states: {\n nodes: Array<{\n id: string;\n name: string;\n type:\n | 'backlog'\n | 'unstarted'\n | 'started'\n | 'completed'\n | 'cancelled';\n color: string;\n }>;\n };\n };\n }>(query, { teamId });\n\n return result.team.states.nodes;\n }\n\n /**\n * Get current viewer/user information\n */\n async getViewer(): Promise<{\n id: string;\n name: string;\n email: string;\n }> {\n const query = `\n query GetViewer {\n viewer {\n id\n name\n email\n }\n }\n `;\n\n const result = await this.graphql<{\n viewer: {\n id: string;\n name: string;\n email: string;\n };\n }>(query);\n\n return result.viewer;\n }\n\n /**\n * Get all teams for the organization\n */\n async getTeams(): Promise<\n Array<{\n id: string;\n name: string;\n key: string;\n }>\n > {\n const query = `\n query GetTeams {\n teams(first: 50) {\n nodes {\n id\n name\n key\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n teams: {\n nodes: Array<{\n id: string;\n name: string;\n key: string;\n }>;\n };\n }>(query);\n\n return result.teams.nodes;\n }\n\n /**\n * Get issues with filtering options\n */\n async getIssues(options?: {\n teamId?: string;\n assigneeId?: string;\n stateType?: 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled';\n limit?: number;\n }): Promise<LinearIssue[]> {\n const query = `\n query GetIssues($filter: IssueFilter, $first: Int!) {\n issues(filter: $filter, first: $first) {\n nodes {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const filter: Record<string, unknown> = {};\n\n if (options?.teamId) {\n filter.team = { id: { eq: options.teamId } };\n }\n\n if (options?.assigneeId) {\n filter.assignee = { id: { eq: options.assigneeId } };\n }\n\n if (options?.stateType) {\n filter.state = { type: { eq: options.stateType } };\n }\n\n const result = await this.graphql<{\n issues: {\n nodes: LinearIssue[];\n };\n }>(query, {\n filter: Object.keys(filter).length > 0 ? filter : undefined,\n first: options?.limit || 50,\n });\n\n return result.issues.nodes;\n }\n\n /**\n * Assign an issue to a user\n */\n async assignIssue(\n issueId: string,\n assigneeId: string\n ): Promise<{ success: boolean; issue?: LinearIssue }> {\n const mutation = `\n mutation AssignIssue($issueId: String!, $assigneeId: String!) {\n issueUpdate(id: $issueId, input: { assigneeId: $assigneeId }) {\n success\n issue {\n id\n identifier\n title\n assignee {\n id\n name\n }\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueUpdate: {\n success: boolean;\n issue?: LinearIssue;\n };\n }>(mutation, { issueId, assigneeId });\n\n return result.issueUpdate;\n }\n\n /**\n * Update issue state (e.g., move to \"In Progress\")\n */\n async updateIssueState(\n issueId: string,\n stateId: string\n ): Promise<{ success: boolean; issue?: LinearIssue }> {\n const mutation = `\n mutation UpdateIssueState($issueId: String!, $stateId: String!) {\n issueUpdate(id: $issueId, input: { stateId: $stateId }) {\n success\n issue {\n id\n identifier\n title\n state {\n id\n name\n type\n }\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueUpdate: {\n success: boolean;\n issue?: LinearIssue;\n };\n }>(mutation, { issueId, stateId });\n\n return result.issueUpdate;\n }\n\n /**\n * Get an issue by ID with team info\n */\n async getIssueById(issueId: string): Promise<LinearIssue | null> {\n const query = `\n query GetIssue($issueId: String!) {\n issue(id: $issueId) {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n team {\n id\n name\n }\n createdAt\n updatedAt\n url\n }\n }\n `;\n\n try {\n const result = await this.graphql<{\n issue: LinearIssue & { team: { id: string; name: string } };\n }>(query, { issueId });\n return result.issue;\n } catch {\n return null;\n }\n }\n\n /**\n * Start working on an issue (assign to self and move to In Progress)\n */\n async startIssue(issueId: string): Promise<{\n success: boolean;\n issue?: LinearIssue;\n error?: string;\n }> {\n try {\n // Get current user\n const user = await this.getViewer();\n\n // Get the issue to find its team\n const issue = await this.getIssueById(issueId);\n if (!issue) {\n return { success: false, error: 'Issue not found' };\n }\n\n // Assign to self\n const assignResult = await this.assignIssue(issueId, user.id);\n if (!assignResult.success) {\n return { success: false, error: 'Failed to assign issue' };\n }\n\n // Find the \"In Progress\" or \"started\" state for this issue's team\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const teamId = (issue as any).team?.id;\n if (teamId) {\n const states = await this.getWorkflowStates(teamId);\n const inProgressState = states.find(\n (s) =>\n s.type === 'started' || s.name.toLowerCase().includes('progress')\n );\n\n if (inProgressState) {\n await this.updateIssueState(issueId, inProgressState.id);\n }\n }\n\n return { success: true, issue: assignResult.issue };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Linear API Client for StackMemory\n * Handles bi-directional sync with Linear's GraphQL API\n */\n\nimport { logger } from '../../core/monitoring/logger.js';\nimport { IntegrationError, ErrorCode } from '../../core/errors/index.js';\n\nexport interface LinearConfig {\n apiKey: string;\n teamId?: string;\n webhookSecret?: string;\n baseUrl?: string;\n // If true, send Authorization header as `Bearer <apiKey>` (OAuth access token)\n useBearer?: boolean;\n // Optional callback to refresh token on 401 and return the new access token\n onUnauthorized?: () => Promise<string>;\n}\n\nexport interface LinearIssue {\n id: string;\n identifier: string; // Like \"SM-123\"\n title: string;\n description?: string;\n state: {\n id: string;\n name: string;\n type: 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled';\n };\n priority: number; // 0-4 (0=none, 1=urgent, 2=high, 3=medium, 4=low)\n assignee?: {\n id: string;\n name: string;\n email: string;\n };\n estimate?: number; // Story points\n labels: Array<{\n id: string;\n name: string;\n }>;\n createdAt: string;\n updatedAt: string;\n url: string;\n}\n\nexport interface LinearCreateIssueInput {\n title: string;\n description?: string;\n teamId: string;\n priority?: number;\n estimate?: number;\n labelIds?: string[];\n}\n\ninterface RateLimitState {\n remaining: number;\n resetAt: number;\n retryAfter: number;\n}\n\nexport class LinearClient {\n private config: LinearConfig;\n private baseUrl: string;\n private rateLimitState: RateLimitState = {\n remaining: 1500, // Linear's default limit\n resetAt: Date.now() + 3600000,\n retryAfter: 0,\n };\n private requestQueue: Array<() => Promise<void>> = [];\n private isProcessingQueue = false;\n private minRequestInterval = 100; // Minimum ms between requests\n private lastRequestTime = 0;\n\n constructor(config: LinearConfig) {\n this.config = config;\n this.baseUrl = config.baseUrl || 'https://api.linear.app';\n\n if (!config.apiKey) {\n throw new IntegrationError(\n 'Linear API key is required',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n }\n\n /**\n * Wait for rate limit to reset if needed\n */\n private async waitForRateLimit(): Promise<void> {\n const now = Date.now();\n\n // Check if we're in a retry-after period\n if (this.rateLimitState.retryAfter > now) {\n const waitTime = this.rateLimitState.retryAfter - now;\n logger.warn(`Rate limited, waiting ${Math.ceil(waitTime / 1000)}s`);\n await this.sleep(waitTime);\n }\n\n // Check if we've exhausted our rate limit\n if (this.rateLimitState.remaining <= 5) {\n if (this.rateLimitState.resetAt > now) {\n const waitTime = this.rateLimitState.resetAt - now;\n logger.warn(\n `Rate limit nearly exhausted, waiting ${Math.ceil(waitTime / 1000)}s for reset`\n );\n await this.sleep(Math.min(waitTime, 60000)); // Max 60s wait\n }\n }\n\n // Ensure minimum interval between requests\n const timeSinceLastRequest = now - this.lastRequestTime;\n if (timeSinceLastRequest < this.minRequestInterval) {\n await this.sleep(this.minRequestInterval - timeSinceLastRequest);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Update rate limit state from response headers\n */\n private updateRateLimitState(response: Response): void {\n const remaining = response.headers.get('x-ratelimit-remaining');\n const reset = response.headers.get('x-ratelimit-reset');\n const retryAfter = response.headers.get('retry-after');\n\n if (remaining !== null) {\n this.rateLimitState.remaining = parseInt(remaining, 10);\n }\n if (reset !== null) {\n this.rateLimitState.resetAt = parseInt(reset, 10) * 1000;\n }\n if (retryAfter !== null) {\n this.rateLimitState.retryAfter =\n Date.now() + parseInt(retryAfter, 10) * 1000;\n }\n }\n\n /**\n * Execute GraphQL query against Linear API with rate limiting\n */\n private async graphql<T>(\n query: string,\n variables?: Record<string, unknown>,\n retries = 3,\n allowAuthRefresh = true\n ): Promise<T> {\n // Wait for rate limit before making request\n await this.waitForRateLimit();\n\n this.lastRequestTime = Date.now();\n\n const authHeader = this.config.useBearer\n ? `Bearer ${this.config.apiKey}`\n : this.config.apiKey;\n\n let response = await fetch(`${this.baseUrl}/graphql`, {\n method: 'POST',\n headers: {\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query,\n variables,\n }),\n });\n\n // Update rate limit state from response\n this.updateRateLimitState(response);\n\n // Handle unauthorized (e.g., expired OAuth token)\n if (\n response.status === 401 &&\n this.config.onUnauthorized &&\n allowAuthRefresh\n ) {\n try {\n const newToken = await this.config.onUnauthorized();\n // Update local config and retry once without further auth refresh\n this.config.apiKey = newToken;\n const retryHeader = this.config.useBearer\n ? `Bearer ${newToken}`\n : newToken;\n response = await fetch(`${this.baseUrl}/graphql`, {\n method: 'POST',\n headers: {\n Authorization: retryHeader,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ query, variables }),\n });\n this.updateRateLimitState(response);\n } catch (e: unknown) {\n // Fall through to standard error handling\n }\n }\n\n // Handle rate limiting with exponential backoff\n if (response.status === 429) {\n if (retries > 0) {\n const retryAfter = response.headers.get('retry-after');\n const waitTime = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n logger.warn(\n `Rate limited (429), retrying in ${waitTime / 1000}s (${retries} retries left)`\n );\n this.rateLimitState.retryAfter = Date.now() + waitTime;\n await this.sleep(waitTime);\n return this.graphql<T>(query, variables, retries - 1, allowAuthRefresh);\n }\n throw new IntegrationError(\n 'Linear API rate limit exceeded after retries',\n ErrorCode.LINEAR_API_ERROR,\n { retries: 0 }\n );\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n // Don't log 401/403 - expected when not authenticated\n if (response.status !== 401 && response.status !== 403) {\n logger.error(\n 'Linear API error response:',\n new Error(`${response.status}: ${errorText}`)\n );\n }\n throw new IntegrationError(\n `Linear API error: ${response.status} ${response.statusText}`,\n ErrorCode.LINEAR_API_ERROR,\n {\n status: response.status,\n statusText: response.statusText,\n body: errorText,\n }\n );\n }\n\n const result = (await response.json()) as {\n data?: T;\n errors?: Array<{ message: string }>;\n };\n\n if (result.errors) {\n // Check for rate limit errors in GraphQL response\n const rateLimitError = result.errors.find(\n (e) =>\n e.message.toLowerCase().includes('rate limit') ||\n e.message.toLowerCase().includes('usage limit')\n );\n\n if (rateLimitError && retries > 0) {\n const waitTime = 60000; // Default 60s wait for GraphQL rate limit errors\n logger.warn(\n `GraphQL rate limit error, retrying in ${waitTime / 1000}s (${retries} retries left)`\n );\n this.rateLimitState.retryAfter = Date.now() + waitTime;\n await this.sleep(waitTime);\n return this.graphql<T>(query, variables, retries - 1);\n }\n\n logger.error('Linear GraphQL errors:', { errors: result.errors });\n throw new IntegrationError(\n `Linear GraphQL error: ${result.errors[0].message}`,\n ErrorCode.LINEAR_API_ERROR,\n { errors: result.errors }\n );\n }\n\n return result.data as T;\n }\n\n /**\n * Create a new issue in Linear\n */\n async createIssue(input: LinearCreateIssueInput): Promise<LinearIssue> {\n const mutation = `\n mutation CreateIssue($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueCreate: {\n success: boolean;\n issue: LinearIssue;\n };\n }>(mutation, { input });\n\n if (!result.issueCreate.success) {\n throw new IntegrationError(\n 'Failed to create Linear issue',\n ErrorCode.LINEAR_API_ERROR,\n { input }\n );\n }\n\n return result.issueCreate.issue;\n }\n\n /**\n * Update an existing Linear issue\n */\n async updateIssue(\n issueId: string,\n updates: Partial<LinearCreateIssueInput> & { stateId?: string }\n ): Promise<LinearIssue> {\n const mutation = `\n mutation UpdateIssue($id: String!, $input: IssueUpdateInput!) {\n issueUpdate(id: $id, input: $input) {\n success\n issue {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueUpdate: {\n success: boolean;\n issue: LinearIssue;\n };\n }>(mutation, { id: issueId, input: updates });\n\n if (!result.issueUpdate.success) {\n throw new IntegrationError(\n `Failed to update Linear issue ${issueId}`,\n ErrorCode.LINEAR_API_ERROR,\n { issueId, updates }\n );\n }\n\n return result.issueUpdate.issue;\n }\n\n /**\n * Get issue by ID\n */\n async getIssue(issueId: string): Promise<LinearIssue | null> {\n const query = `\n query GetIssue($id: String!) {\n issue(id: $id) {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n `;\n\n const result = await this.graphql<{\n issue: LinearIssue | null;\n }>(query, { id: issueId });\n\n return result.issue;\n }\n\n /**\n * Search for issues by identifier (e.g., \"SM-123\")\n */\n async findIssueByIdentifier(identifier: string): Promise<LinearIssue | null> {\n const query = `\n query FindIssue($filter: IssueFilter!) {\n issues(filter: $filter, first: 1) {\n nodes {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issues: {\n nodes: LinearIssue[];\n };\n }>(query, {\n filter: {\n number: {\n eq: parseInt(identifier.split('-')[1] || '0') || 0,\n },\n },\n });\n\n return result.issues.nodes[0] || null;\n }\n\n /**\n * Get team information\n */\n async getTeam(\n teamId?: string\n ): Promise<{ id: string; name: string; key: string }> {\n const query = teamId\n ? `\n query GetTeam($id: String!) {\n team(id: $id) {\n id\n name\n key\n }\n }\n `\n : `\n query GetTeams {\n teams(first: 1) {\n nodes {\n id\n name\n key\n }\n }\n }\n `;\n\n if (teamId) {\n const result = await this.graphql<{\n team: { id: string; name: string; key: string };\n }>(query, { id: teamId });\n if (!result.team) {\n throw new IntegrationError(\n `Team ${teamId} not found`,\n ErrorCode.LINEAR_API_ERROR,\n { teamId }\n );\n }\n return result.team;\n } else {\n const result = await this.graphql<{\n teams: {\n nodes: Array<{ id: string; name: string; key: string }>;\n };\n }>(query);\n\n if (result.teams.nodes.length === 0) {\n throw new IntegrationError(\n 'No teams found',\n ErrorCode.LINEAR_API_ERROR\n );\n }\n\n return result.teams.nodes[0]!;\n }\n }\n\n /**\n * Get workflow states for a team\n */\n async getWorkflowStates(teamId: string): Promise<\n Array<{\n id: string;\n name: string;\n type: 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled';\n color: string;\n }>\n > {\n const query = `\n query GetWorkflowStates($teamId: String!) {\n team(id: $teamId) {\n states {\n nodes {\n id\n name\n type\n color\n }\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n team: {\n states: {\n nodes: Array<{\n id: string;\n name: string;\n type:\n | 'backlog'\n | 'unstarted'\n | 'started'\n | 'completed'\n | 'cancelled';\n color: string;\n }>;\n };\n };\n }>(query, { teamId });\n\n return result.team.states.nodes;\n }\n\n /**\n * Get current viewer/user information\n */\n async getViewer(): Promise<{\n id: string;\n name: string;\n email: string;\n }> {\n const query = `\n query GetViewer {\n viewer {\n id\n name\n email\n }\n }\n `;\n\n const result = await this.graphql<{\n viewer: {\n id: string;\n name: string;\n email: string;\n };\n }>(query);\n\n return result.viewer;\n }\n\n /**\n * Get all teams for the organization\n */\n async getTeams(): Promise<\n Array<{\n id: string;\n name: string;\n key: string;\n }>\n > {\n const query = `\n query GetTeams {\n teams(first: 50) {\n nodes {\n id\n name\n key\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n teams: {\n nodes: Array<{\n id: string;\n name: string;\n key: string;\n }>;\n };\n }>(query);\n\n return result.teams.nodes;\n }\n\n /**\n * Get issues with filtering options\n */\n async getIssues(options?: {\n teamId?: string;\n assigneeId?: string;\n stateType?: 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled';\n limit?: number;\n }): Promise<LinearIssue[]> {\n const query = `\n query GetIssues($filter: IssueFilter, $first: Int!) {\n issues(filter: $filter, first: $first) {\n nodes {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n createdAt\n updatedAt\n url\n }\n }\n }\n `;\n\n const filter: Record<string, unknown> = {};\n\n if (options?.teamId) {\n filter.team = { id: { eq: options.teamId } };\n }\n\n if (options?.assigneeId) {\n filter.assignee = { id: { eq: options.assigneeId } };\n }\n\n if (options?.stateType) {\n filter.state = { type: { eq: options.stateType } };\n }\n\n const result = await this.graphql<{\n issues: {\n nodes: LinearIssue[];\n };\n }>(query, {\n filter: Object.keys(filter).length > 0 ? filter : undefined,\n first: options?.limit || 50,\n });\n\n return result.issues.nodes;\n }\n\n /**\n * Assign an issue to a user\n */\n async assignIssue(\n issueId: string,\n assigneeId: string\n ): Promise<{ success: boolean; issue?: LinearIssue }> {\n const mutation = `\n mutation AssignIssue($issueId: String!, $assigneeId: String!) {\n issueUpdate(id: $issueId, input: { assigneeId: $assigneeId }) {\n success\n issue {\n id\n identifier\n title\n assignee {\n id\n name\n }\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueUpdate: {\n success: boolean;\n issue?: LinearIssue;\n };\n }>(mutation, { issueId, assigneeId });\n\n return result.issueUpdate;\n }\n\n /**\n * Update issue state (e.g., move to \"In Progress\")\n */\n async updateIssueState(\n issueId: string,\n stateId: string\n ): Promise<{ success: boolean; issue?: LinearIssue }> {\n const mutation = `\n mutation UpdateIssueState($issueId: String!, $stateId: String!) {\n issueUpdate(id: $issueId, input: { stateId: $stateId }) {\n success\n issue {\n id\n identifier\n title\n state {\n id\n name\n type\n }\n }\n }\n }\n `;\n\n const result = await this.graphql<{\n issueUpdate: {\n success: boolean;\n issue?: LinearIssue;\n };\n }>(mutation, { issueId, stateId });\n\n return result.issueUpdate;\n }\n\n /**\n * Get an issue by ID with team info\n */\n async getIssueById(issueId: string): Promise<LinearIssue | null> {\n const query = `\n query GetIssue($issueId: String!) {\n issue(id: $issueId) {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n assignee {\n id\n name\n email\n }\n estimate\n labels {\n nodes {\n id\n name\n }\n }\n team {\n id\n name\n }\n createdAt\n updatedAt\n url\n }\n }\n `;\n\n try {\n const result = await this.graphql<{\n issue: LinearIssue & { team: { id: string; name: string } };\n }>(query, { issueId });\n return result.issue;\n } catch (error: unknown) {\n // Log the error but return null for graceful degradation\n // This allows callers to handle missing issues without crashing\n logger.debug('Failed to fetch issue by ID', {\n issueId,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }\n\n /**\n * Start working on an issue (assign to self and move to In Progress)\n */\n async startIssue(issueId: string): Promise<{\n success: boolean;\n issue?: LinearIssue;\n error?: string;\n }> {\n try {\n // Get current user\n const user = await this.getViewer();\n\n // Get the issue to find its team\n const issue = await this.getIssueById(issueId);\n if (!issue) {\n return { success: false, error: 'Issue not found' };\n }\n\n // Assign to self\n const assignResult = await this.assignIssue(issueId, user.id);\n if (!assignResult.success) {\n return { success: false, error: 'Failed to assign issue' };\n }\n\n // Find the \"In Progress\" or \"started\" state for this issue's team\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const teamId = (issue as any).team?.id;\n if (teamId) {\n const states = await this.getWorkflowStates(teamId);\n const inProgressState = states.find(\n (s) =>\n s.type === 'started' || s.name.toLowerCase().includes('progress')\n );\n\n if (inProgressState) {\n await this.updateIssueState(issueId, inProgressState.id);\n }\n }\n\n return { success: true, issue: assignResult.issue };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n"],
5
+ "mappings": ";;;;AAKA,SAAS,cAAc;AACvB,SAAS,kBAAkB,iBAAiB;AAsDrC,MAAM,aAAa;AAAA,EAChB;AAAA,EACA;AAAA,EACA,iBAAiC;AAAA,IACvC,WAAW;AAAA;AAAA,IACX,SAAS,KAAK,IAAI,IAAI;AAAA,IACtB,YAAY;AAAA,EACd;AAAA,EACQ,eAA2C,CAAC;AAAA,EAC5C,oBAAoB;AAAA,EACpB,qBAAqB;AAAA;AAAA,EACrB,kBAAkB;AAAA,EAE1B,YAAY,QAAsB;AAChC,SAAK,SAAS;AACd,SAAK,UAAU,OAAO,WAAW;AAEjC,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAkC;AAC9C,UAAM,MAAM,KAAK,IAAI;AAGrB,QAAI,KAAK,eAAe,aAAa,KAAK;AACxC,YAAM,WAAW,KAAK,eAAe,aAAa;AAClD,aAAO,KAAK,yBAAyB,KAAK,KAAK,WAAW,GAAI,CAAC,GAAG;AAClE,YAAM,KAAK,MAAM,QAAQ;AAAA,IAC3B;AAGA,QAAI,KAAK,eAAe,aAAa,GAAG;AACtC,UAAI,KAAK,eAAe,UAAU,KAAK;AACrC,cAAM,WAAW,KAAK,eAAe,UAAU;AAC/C,eAAO;AAAA,UACL,wCAAwC,KAAK,KAAK,WAAW,GAAI,CAAC;AAAA,QACpE;AACA,cAAM,KAAK,MAAM,KAAK,IAAI,UAAU,GAAK,CAAC;AAAA,MAC5C;AAAA,IACF;AAGA,UAAM,uBAAuB,MAAM,KAAK;AACxC,QAAI,uBAAuB,KAAK,oBAAoB;AAClD,YAAM,KAAK,MAAM,KAAK,qBAAqB,oBAAoB;AAAA,IACjE;AAAA,EACF;AAAA,EAEQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,UAA0B;AACrD,UAAM,YAAY,SAAS,QAAQ,IAAI,uBAAuB;AAC9D,UAAM,QAAQ,SAAS,QAAQ,IAAI,mBAAmB;AACtD,UAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AAErD,QAAI,cAAc,MAAM;AACtB,WAAK,eAAe,YAAY,SAAS,WAAW,EAAE;AAAA,IACxD;AACA,QAAI,UAAU,MAAM;AAClB,WAAK,eAAe,UAAU,SAAS,OAAO,EAAE,IAAI;AAAA,IACtD;AACA,QAAI,eAAe,MAAM;AACvB,WAAK,eAAe,aAClB,KAAK,IAAI,IAAI,SAAS,YAAY,EAAE,IAAI;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,QACZ,OACA,WACA,UAAU,GACV,mBAAmB,MACP;AAEZ,UAAM,KAAK,iBAAiB;AAE5B,SAAK,kBAAkB,KAAK,IAAI;AAEhC,UAAM,aAAa,KAAK,OAAO,YAC3B,UAAU,KAAK,OAAO,MAAM,KAC5B,KAAK,OAAO;AAEhB,QAAI,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,YAAY;AAAA,MACpD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe;AAAA,QACf,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAGD,SAAK,qBAAqB,QAAQ;AAGlC,QACE,SAAS,WAAW,OACpB,KAAK,OAAO,kBACZ,kBACA;AACA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK,OAAO,eAAe;AAElD,aAAK,OAAO,SAAS;AACrB,cAAM,cAAc,KAAK,OAAO,YAC5B,UAAU,QAAQ,KAClB;AACJ,mBAAW,MAAM,MAAM,GAAG,KAAK,OAAO,YAAY;AAAA,UAChD,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,eAAe;AAAA,YACf,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,UAAU,EAAE,OAAO,UAAU,CAAC;AAAA,QAC3C,CAAC;AACD,aAAK,qBAAqB,QAAQ;AAAA,MACpC,SAAS,GAAY;AAAA,MAErB;AAAA,IACF;AAGA,QAAI,SAAS,WAAW,KAAK;AAC3B,UAAI,UAAU,GAAG;AACf,cAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AACrD,cAAM,WAAW,aAAa,SAAS,YAAY,EAAE,IAAI,MAAO;AAChE,eAAO;AAAA,UACL,mCAAmC,WAAW,GAAI,MAAM,OAAO;AAAA,QACjE;AACA,aAAK,eAAe,aAAa,KAAK,IAAI,IAAI;AAC9C,cAAM,KAAK,MAAM,QAAQ;AACzB,eAAO,KAAK,QAAW,OAAO,WAAW,UAAU,GAAG,gBAAgB;AAAA,MACxE;AACA,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV,EAAE,SAAS,EAAE;AAAA,MACf;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK;AAEtC,UAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,eAAO;AAAA,UACL;AAAA,UACA,IAAI,MAAM,GAAG,SAAS,MAAM,KAAK,SAAS,EAAE;AAAA,QAC9C;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,qBAAqB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QAC3D,UAAU;AAAA,QACV;AAAA,UACE,QAAQ,SAAS;AAAA,UACjB,YAAY,SAAS;AAAA,UACrB,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAU,MAAM,SAAS,KAAK;AAKpC,QAAI,OAAO,QAAQ;AAEjB,YAAM,iBAAiB,OAAO,OAAO;AAAA,QACnC,CAAC,MACC,EAAE,QAAQ,YAAY,EAAE,SAAS,YAAY,KAC7C,EAAE,QAAQ,YAAY,EAAE,SAAS,aAAa;AAAA,MAClD;AAEA,UAAI,kBAAkB,UAAU,GAAG;AACjC,cAAM,WAAW;AACjB,eAAO;AAAA,UACL,yCAAyC,WAAW,GAAI,MAAM,OAAO;AAAA,QACvE;AACA,aAAK,eAAe,aAAa,KAAK,IAAI,IAAI;AAC9C,cAAM,KAAK,MAAM,QAAQ;AACzB,eAAO,KAAK,QAAW,OAAO,WAAW,UAAU,CAAC;AAAA,MACtD;AAEA,aAAO,MAAM,0BAA0B,EAAE,QAAQ,OAAO,OAAO,CAAC;AAChE,YAAM,IAAI;AAAA,QACR,yBAAyB,OAAO,OAAO,CAAC,EAAE,OAAO;AAAA,QACjD,UAAU;AAAA,QACV,EAAE,QAAQ,OAAO,OAAO;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,OAAqD;AACrE,UAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCjB,UAAM,SAAS,MAAM,KAAK,QAKvB,UAAU,EAAE,MAAM,CAAC;AAEtB,QAAI,CAAC,OAAO,YAAY,SAAS;AAC/B,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV,EAAE,MAAM;AAAA,MACV;AAAA,IACF;AAEA,WAAO,OAAO,YAAY;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,SACA,SACsB;AACtB,UAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCjB,UAAM,SAAS,MAAM,KAAK,QAKvB,UAAU,EAAE,IAAI,SAAS,OAAO,QAAQ,CAAC;AAE5C,QAAI,CAAC,OAAO,YAAY,SAAS;AAC/B,YAAM,IAAI;AAAA,QACR,iCAAiC,OAAO;AAAA,QACxC,UAAU;AAAA,QACV,EAAE,SAAS,QAAQ;AAAA,MACrB;AAAA,IACF;AAEA,WAAO,OAAO,YAAY;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,SAA8C;AAC3D,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCd,UAAM,SAAS,MAAM,KAAK,QAEvB,OAAO,EAAE,IAAI,QAAQ,CAAC;AAEzB,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAsB,YAAiD;AAC3E,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCd,UAAM,SAAS,MAAM,KAAK,QAIvB,OAAO;AAAA,MACR,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,IAAI,SAAS,WAAW,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,KAAK;AAAA,QACnD;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,OAAO,OAAO,MAAM,CAAC,KAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QACJ,QACoD;AACpD,UAAM,QAAQ,SACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UASA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYJ,QAAI,QAAQ;AACV,YAAM,SAAS,MAAM,KAAK,QAEvB,OAAO,EAAE,IAAI,OAAO,CAAC;AACxB,UAAI,CAAC,OAAO,MAAM;AAChB,cAAM,IAAI;AAAA,UACR,QAAQ,MAAM;AAAA,UACd,UAAU;AAAA,UACV,EAAE,OAAO;AAAA,QACX;AAAA,MACF;AACA,aAAO,OAAO;AAAA,IAChB,OAAO;AACL,YAAM,SAAS,MAAM,KAAK,QAIvB,KAAK;AAER,UAAI,OAAO,MAAM,MAAM,WAAW,GAAG;AACnC,cAAM,IAAI;AAAA,UACR;AAAA,UACA,UAAU;AAAA,QACZ;AAAA,MACF;AAEA,aAAO,OAAO,MAAM,MAAM,CAAC;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,QAOtB;AACA,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAed,UAAM,SAAS,MAAM,KAAK,QAgBvB,OAAO,EAAE,OAAO,CAAC;AAEpB,WAAO,OAAO,KAAK,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAIH;AACD,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUd,UAAM,SAAS,MAAM,KAAK,QAMvB,KAAK;AAER,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAMJ;AACA,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYd,UAAM,SAAS,MAAM,KAAK,QAQvB,KAAK;AAER,WAAO,OAAO,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,SAKW;AACzB,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCd,UAAM,SAAkC,CAAC;AAEzC,QAAI,SAAS,QAAQ;AACnB,aAAO,OAAO,EAAE,IAAI,EAAE,IAAI,QAAQ,OAAO,EAAE;AAAA,IAC7C;AAEA,QAAI,SAAS,YAAY;AACvB,aAAO,WAAW,EAAE,IAAI,EAAE,IAAI,QAAQ,WAAW,EAAE;AAAA,IACrD;AAEA,QAAI,SAAS,WAAW;AACtB,aAAO,QAAQ,EAAE,MAAM,EAAE,IAAI,QAAQ,UAAU,EAAE;AAAA,IACnD;AAEA,UAAM,SAAS,MAAM,KAAK,QAIvB,OAAO;AAAA,MACR,QAAQ,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS;AAAA,MAClD,OAAO,SAAS,SAAS;AAAA,IAC3B,CAAC;AAED,WAAO,OAAO,OAAO;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,SACA,YACoD;AACpD,UAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBjB,UAAM,SAAS,MAAM,KAAK,QAKvB,UAAU,EAAE,SAAS,WAAW,CAAC;AAEpC,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACJ,SACA,SACoD;AACpD,UAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBjB,UAAM,SAAS,MAAM,KAAK,QAKvB,UAAU,EAAE,SAAS,QAAQ,CAAC;AAEjC,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,SAA8C;AAC/D,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCd,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,QAEvB,OAAO,EAAE,QAAQ,CAAC;AACrB,aAAO,OAAO;AAAA,IAChB,SAAS,OAAgB;AAGvB,aAAO,MAAM,+BAA+B;AAAA,QAC1C;AAAA,QACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,SAId;AACD,QAAI;AAEF,YAAM,OAAO,MAAM,KAAK,UAAU;AAGlC,YAAM,QAAQ,MAAM,KAAK,aAAa,OAAO;AAC7C,UAAI,CAAC,OAAO;AACV,eAAO,EAAE,SAAS,OAAO,OAAO,kBAAkB;AAAA,MACpD;AAGA,YAAM,eAAe,MAAM,KAAK,YAAY,SAAS,KAAK,EAAE;AAC5D,UAAI,CAAC,aAAa,SAAS;AACzB,eAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB;AAAA,MAC3D;AAIA,YAAM,SAAU,MAAc,MAAM;AACpC,UAAI,QAAQ;AACV,cAAM,SAAS,MAAM,KAAK,kBAAkB,MAAM;AAClD,cAAM,kBAAkB,OAAO;AAAA,UAC7B,CAAC,MACC,EAAE,SAAS,aAAa,EAAE,KAAK,YAAY,EAAE,SAAS,UAAU;AAAA,QACpE;AAEA,YAAI,iBAAiB;AACnB,gBAAM,KAAK,iBAAiB,SAAS,gBAAgB,EAAE;AAAA,QACzD;AAAA,MACF;AAEA,aAAO,EAAE,SAAS,MAAM,OAAO,aAAa,MAAM;AAAA,IACpD,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -6,11 +6,12 @@ const __dirname = __pathDirname(__filename);
6
6
  import express from "express";
7
7
  import cors from "cors";
8
8
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
9
- import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
9
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
10
10
  import { z } from "zod";
11
11
  import Database from "better-sqlite3";
12
12
  import { validateInput, StartFrameSchema, AddAnchorSchema } from "./schemas.js";
13
13
  import { readFileSync, existsSync, mkdirSync } from "fs";
14
+ import { randomUUID } from "crypto";
14
15
  import { join, dirname } from "path";
15
16
  import { execSync } from "child_process";
16
17
  import { FrameManager } from "../../core/context/index.js";
@@ -27,7 +28,7 @@ class RemoteStackMemoryMCP {
27
28
  linearSync = null;
28
29
  projectId;
29
30
  contexts = /* @__PURE__ */ new Map();
30
- transports = /* @__PURE__ */ new Map();
31
+ transport = null;
31
32
  constructor(projectRoot) {
32
33
  this.projectRoot = projectRoot || this.findProjectRoot();
33
34
  this.projectId = this.getProjectId();
@@ -596,46 +597,37 @@ Anchor ID: ${anchorId}`
596
597
  projectRoot: this.projectRoot
597
598
  });
598
599
  });
599
- app.get("/sse", async (req, res) => {
600
- logger.info("New SSE connection request");
601
- const transport = new SSEServerTransport("/message", res);
602
- const sessionId = transport.sessionId;
603
- this.transports.set(sessionId, transport);
604
- transport.onclose = () => {
605
- this.transports.delete(sessionId);
606
- logger.info("SSE connection closed", { sessionId });
607
- };
608
- transport.onerror = (error) => {
609
- logger.error("SSE transport error", { sessionId, error });
610
- this.transports.delete(sessionId);
611
- };
612
- await this.server.connect(transport);
613
- await transport.start();
614
- logger.info("SSE connection established", { sessionId });
600
+ this.transport = new StreamableHTTPServerTransport({
601
+ sessionIdGenerator: () => randomUUID()
615
602
  });
616
- app.post("/message", async (req, res) => {
617
- const sessionId = req.query.sessionId;
618
- if (!sessionId) {
619
- res.status(400).json({ error: "Missing sessionId" });
620
- return;
621
- }
622
- const transport = this.transports.get(sessionId);
623
- if (!transport) {
624
- res.status(404).json({ error: "Session not found" });
625
- return;
603
+ await this.server.connect(this.transport);
604
+ app.all("/mcp", async (req, res) => {
605
+ logger.info("MCP request", { method: req.method });
606
+ try {
607
+ await this.transport.handleRequest(req, res, req.body);
608
+ } catch (error) {
609
+ logger.error("MCP request error", { error });
610
+ if (!res.headersSent) {
611
+ res.status(500).json({ error: "Internal server error" });
612
+ }
626
613
  }
627
- await transport.handlePostMessage(req, res);
614
+ });
615
+ app.get("/sse", (req, res) => {
616
+ res.redirect(307, "/mcp");
617
+ });
618
+ app.post("/message", (req, res) => {
619
+ res.redirect(307, "/mcp");
628
620
  });
629
621
  app.get("/info", (req, res) => {
630
622
  res.json({
631
623
  name: "stackmemory-remote",
632
- version: "0.1.0",
624
+ version: "0.2.0",
633
625
  protocol: "mcp",
634
- transport: "sse",
626
+ transport: "streamable-http",
635
627
  endpoints: {
636
- sse: "/sse",
637
- message: "/message",
638
- health: "/health"
628
+ mcp: "/mcp",
629
+ health: "/health",
630
+ info: "/info"
639
631
  },
640
632
  project: {
641
633
  id: this.projectId,
@@ -651,8 +643,7 @@ Anchor ID: ${anchorId}`
651
643
  );
652
644
  console.log(`
653
645
  Endpoints:`);
654
- console.log(` SSE: http://localhost:${port}/sse`);
655
- console.log(` Message: http://localhost:${port}/message`);
646
+ console.log(` MCP: http://localhost:${port}/mcp`);
656
647
  console.log(` Health: http://localhost:${port}/health`);
657
648
  console.log(` Info: http://localhost:${port}/info`);
658
649
  console.log(