claude-flow-novice 2.15.3 → 2.15.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. package/.claude/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
  2. package/.claude/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
  3. package/.claude/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
  4. package/.claude/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
  5. package/.claude/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
  6. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
  7. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
  8. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
  9. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
  10. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
  11. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
  12. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
  13. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
  14. package/.claude/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
  15. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
  16. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
  17. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
  18. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
  19. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
  20. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
  21. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
  22. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
  23. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
  24. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
  25. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
  26. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
  27. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
  28. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
  29. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
  30. package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
  31. package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
  32. package/.claude/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
  33. package/.claude/commands/cfn-loop-cli.md +29 -6
  34. package/.claude/commands/switch-api.md +31 -10
  35. package/.claude/hooks/cfn-lint-sql-injection.sh +61 -0
  36. package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
  37. package/.claude/hooks/cfn-pre-edit-security-warning.sh +40 -0
  38. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  39. package/.claude/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  40. package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  41. package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  42. package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  43. package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  44. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
  45. package/.claude/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  46. package/.claude/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  47. package/.claude/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  48. package/.claude/skills/cfn-redis-coordination/agent-log.sh +4 -0
  49. package/.claude/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  50. package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
  51. package/.claude/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  52. package/.claude/skills/cfn-redis-coordination/get-context.sh +33 -0
  53. package/.claude/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  54. package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
  55. package/.claude/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  56. package/.claude/skills/cfn-redis-coordination/redis-functions.sh +34 -0
  57. package/.claude/skills/cfn-redis-coordination/report-completion.sh +24 -31
  58. package/.claude/skills/cfn-redis-coordination/store-context.sh +4 -0
  59. package/.claude/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  60. package/.claude/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  61. package/.claude/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  62. package/.claude/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  63. package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
  64. package/README.md +116 -475
  65. package/claude-assets/agents/cfn-dev-team/README.md +103 -0
  66. package/claude-assets/agents/cfn-dev-team/architecture/goal-planner.md +1 -1
  67. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +77 -15
  68. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +355 -6
  69. package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +82 -1
  70. package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +82 -1
  71. package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +77 -15
  72. package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +99 -12
  73. package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +1 -1
  74. package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +97 -0
  75. package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +20 -1
  76. package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +97 -0
  77. package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +110 -13
  78. package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +106 -15
  79. package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +115 -11
  80. package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +94 -7
  81. package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +87 -9
  82. package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +85 -7
  83. package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +160 -28
  84. package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +101 -19
  85. package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +108 -14
  86. package/claude-assets/agents/cfn-dev-team/reviewers/{reviewer.md → code-reviewer.md} +95 -8
  87. package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +107 -7
  88. package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +98 -7
  89. package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +95 -7
  90. package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +136 -9
  91. package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +108 -1
  92. package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +107 -13
  93. package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +737 -0
  94. package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
  95. package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +828 -0
  96. package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +106 -7
  97. package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +77 -0
  98. package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +684 -0
  99. package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +110 -1
  100. package/claude-assets/agents/cfn-dev-team/testers/tester.md +94 -7
  101. package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +1 -3
  102. package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +87 -13
  103. package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +103 -7
  104. package/claude-assets/agents/cfn-dev-team/utility/researcher.md +1 -3
  105. package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +94 -7
  106. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +46 -0
  107. package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
  108. package/claude-assets/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
  109. package/claude-assets/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
  110. package/claude-assets/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
  111. package/claude-assets/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
  112. package/claude-assets/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
  113. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
  114. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
  115. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
  116. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
  117. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
  118. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
  119. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
  120. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
  121. package/claude-assets/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
  122. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
  123. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
  124. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
  125. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
  126. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
  127. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
  128. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
  129. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
  130. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
  131. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
  132. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
  133. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
  134. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
  135. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
  136. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
  137. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
  138. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
  139. package/claude-assets/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
  140. package/claude-assets/commands/cfn-loop-cli.md +29 -6
  141. package/claude-assets/commands/switch-api.md +31 -10
  142. package/claude-assets/hooks/cfn-lint-sql-injection.sh +61 -0
  143. package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
  144. package/claude-assets/hooks/cfn-pre-edit-security-warning.sh +40 -0
  145. package/claude-assets/hooks/detect-hardcoded-credentials.sh +212 -0
  146. package/claude-assets/skills/SKILL_TEMPLATE.md +774 -0
  147. package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +84 -113
  148. package/claude-assets/skills/agent-lifecycle/simple-audit.sh +33 -6
  149. package/claude-assets/skills/agent-template-generator/SKILL.md +440 -0
  150. package/claude-assets/skills/agent-template-generator/generate-agent.sh +405 -0
  151. package/claude-assets/skills/agent-validation-linter/SKILL.md +589 -0
  152. package/claude-assets/skills/agent-validation-linter/lint-agents.sh +271 -0
  153. package/claude-assets/skills/bootstrap/bash-fundamentals.md +786 -0
  154. package/claude-assets/skills/bootstrap/database-connection.md +464 -0
  155. package/claude-assets/skills/bootstrap/error-handling.md +580 -0
  156. package/claude-assets/skills/bootstrap/file-operations.md +699 -0
  157. package/claude-assets/skills/bootstrap/skill-loader.md +616 -0
  158. package/claude-assets/skills/bootstrap/sqlite-params.sh +287 -0
  159. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  160. package/claude-assets/skills/cfn-automatic-memory-persistence/test-memory-persistence.sh +17 -16
  161. package/claude-assets/skills/cfn-deployment/SKILL.md +293 -0
  162. package/claude-assets/skills/cfn-deployment/execute.sh +21 -0
  163. package/claude-assets/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  164. package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  165. package/claude-assets/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  166. package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +38 -0
  167. package/claude-assets/skills/cfn-error-batching-strategy/lib/core-functions.sh +47 -47
  168. package/claude-assets/skills/cfn-file-operations/SKILL.md +290 -0
  169. package/claude-assets/skills/cfn-file-operations/execute.sh +129 -0
  170. package/claude-assets/skills/cfn-file-operations/lib/atomic-write.sh +294 -0
  171. package/claude-assets/skills/cfn-file-operations/lib/lock.sh +361 -0
  172. package/claude-assets/skills/cfn-file-operations/test.sh +369 -0
  173. package/claude-assets/skills/cfn-log-operations/SKILL.md +308 -0
  174. package/claude-assets/skills/cfn-log-operations/execute.sh +420 -0
  175. package/claude-assets/skills/cfn-log-operations/lib/rotate.sh +406 -0
  176. package/claude-assets/skills/cfn-log-operations/lib/search.sh +448 -0
  177. package/claude-assets/skills/cfn-log-operations/test.sh +394 -0
  178. package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  179. package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  180. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
  181. package/claude-assets/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  182. package/claude-assets/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  183. package/claude-assets/skills/cfn-parameterized-queries/SKILL.md +339 -0
  184. package/claude-assets/skills/cfn-playbook/query-playbook.sh +19 -15
  185. package/claude-assets/skills/cfn-playbook/update-playbook.sh +25 -14
  186. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +44 -0
  187. package/claude-assets/skills/cfn-promotion/SKILL.md +305 -0
  188. package/claude-assets/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  189. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh +4 -0
  190. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  191. package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
  192. package/claude-assets/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  193. package/claude-assets/skills/cfn-redis-coordination/get-context.sh +33 -0
  194. package/claude-assets/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  195. package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
  196. package/claude-assets/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  197. package/claude-assets/skills/cfn-redis-coordination/redis-functions.sh +34 -0
  198. package/claude-assets/skills/cfn-redis-coordination/report-completion.sh +24 -31
  199. package/claude-assets/skills/cfn-redis-coordination/store-context.sh +4 -0
  200. package/claude-assets/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  201. package/claude-assets/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  202. package/claude-assets/skills/cfn-skill-loader/SKILL.md +466 -0
  203. package/claude-assets/skills/cfn-skill-loader/execute.sh +344 -0
  204. package/claude-assets/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  205. package/claude-assets/skills/cfn-task-audit/get-audit-data.sh +42 -21
  206. package/claude-assets/skills/cfn-task-audit/store-task-audit.sh +17 -10
  207. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh +17 -14
  208. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh.backup-1763392821 +55 -0
  209. package/claude-assets/skills/cfn-test-runner/store-benchmarks.sh +17 -19
  210. package/claude-assets/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  211. package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
  212. package/claude-assets/skills/cfn-utilities/SKILL.md +237 -0
  213. package/claude-assets/skills/cfn-utilities/execute.sh +32 -0
  214. package/claude-assets/skills/cfn-utilities/lib/errors.sh +56 -0
  215. package/claude-assets/skills/cfn-utilities/lib/file-ops.sh +164 -0
  216. package/claude-assets/skills/cfn-utilities/lib/logging.sh +77 -0
  217. package/claude-assets/skills/cfn-utilities/lib/retry.sh +127 -0
  218. package/claude-assets/skills/cfn-utilities/test.sh +317 -0
  219. package/claude-assets/skills/integration/agent-handoff.sh +62 -64
  220. package/claude-assets/skills/json-validation/SKILL.md +431 -0
  221. package/claude-assets/skills/json-validation/test-validate-success-criteria.sh +421 -0
  222. package/claude-assets/skills/json-validation/validate-success-criteria.sh +197 -0
  223. package/claude-assets/skills/redis-coordination/validate-parameters.sh +34 -0
  224. package/claude-assets/skills/workflow-codification/DEPLOY_QUICK_REFERENCE.md +106 -0
  225. package/claude-assets/skills/workflow-codification/PROPAGATE_UPDATE_QUICK_REFERENCE.md +366 -0
  226. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh +481 -0
  227. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh.backup-1763392820 +512 -0
  228. package/claude-assets/skills/workflow-codification/lib/security-utils.sh +204 -0
  229. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh +648 -0
  230. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh.backup-1763392820 +664 -0
  231. package/claude-assets/skills/workflow-codification/test-integration.sh +15 -0
  232. package/claude-assets/skills/workflow-codification/test-metadata-update.sh +350 -0
  233. package/claude-assets/skills/workflow-codification/track-cost-savings.sh +55 -14
  234. package/claude-assets/skills/workflow-codification/track-cost-savings.sh.backup-1763392821 +445 -0
  235. package/claude-assets/skills/workflow-codification/track-edge-case.sh +27 -60
  236. package/claude-assets/skills/workflow-codification/workflow-codification.db +0 -0
  237. package/dist/ace/ace-curator.js +10 -2
  238. package/dist/ace/ace-curator.js.map +1 -1
  239. package/dist/ace/ace-generator.js +4 -0
  240. package/dist/ace/ace-generator.js.map +1 -1
  241. package/dist/ace/ace-reflector.js +1 -1
  242. package/dist/ace/ace-reflector.js.map +1 -1
  243. package/dist/ace/context-injection.js +24 -2
  244. package/dist/ace/context-injection.js.map +1 -1
  245. package/dist/agents/task-agent-integration.js +1 -1
  246. package/dist/agents/task-agent-integration.js.map +1 -1
  247. package/dist/api/health-endpoints.js +390 -0
  248. package/dist/api/health-endpoints.js.map +1 -0
  249. package/dist/cli/agent-executor.js +4 -1
  250. package/dist/cli/agent-executor.js.map +1 -1
  251. package/dist/cli/agent-prompt-builder.js +89 -1
  252. package/dist/cli/agent-prompt-builder.js.map +1 -1
  253. package/dist/cli/agent-spawn.js +130 -37
  254. package/dist/cli/agent-spawn.js.map +1 -1
  255. package/dist/cli/config-manager.js +109 -91
  256. package/dist/cli/config-manager.js.map +1 -1
  257. package/dist/cli/conversation-fork-cleanup.js +201 -0
  258. package/dist/cli/conversation-fork-cleanup.js.map +1 -0
  259. package/dist/cli/conversation-fork.js +16 -3
  260. package/dist/cli/conversation-fork.js.map +1 -1
  261. package/dist/cli/skill-cache-validator.js +412 -0
  262. package/dist/cli/skill-cache-validator.js.map +1 -0
  263. package/dist/cli/skill-cli.js +991 -0
  264. package/dist/cli/skill-cli.js.map +1 -0
  265. package/dist/cli/skill-execution-logger.js +284 -0
  266. package/dist/cli/skill-execution-logger.js.map +1 -0
  267. package/dist/cli/skill-loader.js +457 -0
  268. package/dist/cli/skill-loader.js.map +1 -0
  269. package/dist/coordination/event-bus.js +2 -2
  270. package/dist/coordination/event-bus.js.map +1 -1
  271. package/dist/coordination/fleet-manager.js +1 -1
  272. package/dist/coordination/fleet-manager.js.map +1 -1
  273. package/dist/coordination/index.js +23 -9
  274. package/dist/coordination/index.js.map +1 -1
  275. package/dist/coordination/types/fleet-manager.types.js.map +1 -1
  276. package/dist/db/migration-manager.js +483 -0
  277. package/dist/db/migration-manager.js.map +1 -0
  278. package/dist/db/skills-query.js +535 -0
  279. package/dist/db/skills-query.js.map +1 -0
  280. package/dist/integration/DatabaseHandoff.js +1 -1
  281. package/dist/integration/DatabaseHandoff.js.map +1 -1
  282. package/dist/jobs/edge-case-analyzer.js +367 -0
  283. package/dist/jobs/edge-case-analyzer.js.map +1 -0
  284. package/dist/jobs/promotion-sla-enforcer.js +288 -0
  285. package/dist/jobs/promotion-sla-enforcer.js.map +1 -0
  286. package/dist/lib/agent-output-parser.js.map +1 -1
  287. package/dist/lib/agent-output-validator.js.map +1 -1
  288. package/dist/lib/agent-workspace.js +281 -0
  289. package/dist/lib/agent-workspace.js.map +1 -0
  290. package/dist/lib/atomic-file-writer.js +377 -0
  291. package/dist/lib/atomic-file-writer.js.map +1 -0
  292. package/dist/lib/backup-manager.js +779 -0
  293. package/dist/lib/backup-manager.js.map +1 -0
  294. package/dist/lib/checkpoint-manager.js +837 -0
  295. package/dist/lib/checkpoint-manager.js.map +1 -0
  296. package/dist/lib/circuit-breaker.js +340 -0
  297. package/dist/lib/circuit-breaker.js.map +1 -0
  298. package/dist/lib/completion-signal-handler.js +243 -0
  299. package/dist/lib/completion-signal-handler.js.map +1 -0
  300. package/dist/lib/config-manager.js +312 -0
  301. package/dist/lib/config-manager.js.map +1 -0
  302. package/dist/lib/config-migrator.js +386 -0
  303. package/dist/lib/config-migrator.js.map +1 -0
  304. package/dist/lib/config-validator.js.map +1 -1
  305. package/dist/lib/correlation-cache.js +311 -0
  306. package/dist/lib/correlation-cache.js.map +1 -0
  307. package/dist/lib/correlation.js +263 -0
  308. package/dist/lib/correlation.js.map +1 -0
  309. package/dist/lib/database-service/connection-pool-manager.js +520 -0
  310. package/dist/lib/database-service/connection-pool-manager.js.map +1 -0
  311. package/dist/lib/database-service/correlation.js +329 -0
  312. package/dist/lib/database-service/correlation.js.map +1 -0
  313. package/dist/lib/database-service/errors.js +120 -0
  314. package/dist/lib/database-service/errors.js.map +1 -0
  315. package/dist/lib/database-service/index.js +168 -0
  316. package/dist/lib/database-service/index.js.map +1 -0
  317. package/dist/lib/database-service/postgres-adapter.js +526 -0
  318. package/dist/lib/database-service/postgres-adapter.js.map +1 -0
  319. package/dist/lib/database-service/redis-adapter.js +360 -0
  320. package/dist/lib/database-service/redis-adapter.js.map +1 -0
  321. package/dist/lib/database-service/sqlite-adapter.js +544 -0
  322. package/dist/lib/database-service/sqlite-adapter.js.map +1 -0
  323. package/dist/lib/database-service/transaction-manager.js +773 -0
  324. package/dist/lib/database-service/transaction-manager.js.map +1 -0
  325. package/dist/lib/database-service/types.js +23 -0
  326. package/dist/lib/database-service/types.js.map +1 -0
  327. package/dist/lib/deadlock-resolver.js +292 -0
  328. package/dist/lib/deadlock-resolver.js.map +1 -0
  329. package/dist/lib/distributed-lock.js +451 -0
  330. package/dist/lib/distributed-lock.js.map +1 -0
  331. package/dist/lib/edge-case-deduplicator.js +227 -0
  332. package/dist/lib/edge-case-deduplicator.js.map +1 -0
  333. package/dist/lib/encryption-manager.js +322 -0
  334. package/dist/lib/encryption-manager.js.map +1 -0
  335. package/dist/lib/error-aggregator.js +234 -0
  336. package/dist/lib/error-aggregator.js.map +1 -0
  337. package/dist/lib/errors.js +287 -0
  338. package/dist/lib/errors.js.map +1 -0
  339. package/dist/lib/file-lock-manager.js +578 -0
  340. package/dist/lib/file-lock-manager.js.map +1 -0
  341. package/dist/lib/file-operations.js +367 -0
  342. package/dist/lib/file-operations.js.map +1 -0
  343. package/dist/lib/idempotent-write.js +237 -0
  344. package/dist/lib/idempotent-write.js.map +1 -0
  345. package/dist/lib/integration-schema-validator.js +522 -0
  346. package/dist/lib/integration-schema-validator.js.map +1 -0
  347. package/dist/lib/lock-health-monitor.js +298 -0
  348. package/dist/lib/lock-health-monitor.js.map +1 -0
  349. package/dist/lib/log-shipper.js +422 -0
  350. package/dist/lib/log-shipper.js.map +1 -0
  351. package/dist/lib/logging.js +146 -0
  352. package/dist/lib/logging.js.map +1 -0
  353. package/dist/lib/message-deduplicator.js +439 -0
  354. package/dist/lib/message-deduplicator.js.map +1 -0
  355. package/dist/lib/multi-system-query.js +604 -0
  356. package/dist/lib/multi-system-query.js.map +1 -0
  357. package/dist/lib/orphan-detector.js +332 -0
  358. package/dist/lib/orphan-detector.js.map +1 -0
  359. package/dist/lib/password-generator.js +166 -0
  360. package/dist/lib/password-generator.js.map +1 -0
  361. package/dist/lib/path-validator.js +429 -0
  362. package/dist/lib/path-validator.js.map +1 -0
  363. package/dist/lib/query-translator.js +905 -0
  364. package/dist/lib/query-translator.js.map +1 -0
  365. package/dist/lib/queue-recovery.js +469 -0
  366. package/dist/lib/queue-recovery.js.map +1 -0
  367. package/dist/lib/redis-queue-manager.js +512 -0
  368. package/dist/lib/redis-queue-manager.js.map +1 -0
  369. package/dist/lib/reflection-archiver.js +272 -0
  370. package/dist/lib/reflection-archiver.js.map +1 -0
  371. package/dist/lib/retry-manager.js +453 -0
  372. package/dist/lib/retry-manager.js.map +1 -0
  373. package/dist/lib/retry.js +262 -0
  374. package/dist/lib/retry.js.map +1 -0
  375. package/dist/lib/schema-transform.js +695 -0
  376. package/dist/lib/schema-transform.js.map +1 -0
  377. package/dist/lib/schema-validator.js +491 -0
  378. package/dist/lib/schema-validator.js.map +1 -0
  379. package/dist/lib/skill-cache.js +297 -0
  380. package/dist/lib/skill-cache.js.map +1 -0
  381. package/dist/lib/skill-content-manager.js +337 -0
  382. package/dist/lib/skill-content-manager.js.map +1 -0
  383. package/dist/lib/skill-frontmatter-parser.js +237 -0
  384. package/dist/lib/skill-frontmatter-parser.js.map +1 -0
  385. package/dist/lib/skill-git-integration.js +275 -0
  386. package/dist/lib/skill-git-integration.js.map +1 -0
  387. package/dist/lib/skill-markdown-validator.js +396 -0
  388. package/dist/lib/skill-markdown-validator.js.map +1 -0
  389. package/dist/lib/skill-output-parser.js +312 -0
  390. package/dist/lib/skill-output-parser.js.map +1 -0
  391. package/dist/lib/unified-query-api.js +467 -0
  392. package/dist/lib/unified-query-api.js.map +1 -0
  393. package/dist/middleware/auth-middleware.js +350 -0
  394. package/dist/middleware/auth-middleware.js.map +1 -0
  395. package/dist/middleware/schema-validation.js +347 -0
  396. package/dist/middleware/schema-validation.js.map +1 -0
  397. package/dist/providers/anthropic-provider.js +1 -1
  398. package/dist/providers/anthropic-provider.js.map +1 -1
  399. package/dist/providers/provider-factory.js +2 -2
  400. package/dist/providers/provider-factory.js.map +1 -1
  401. package/dist/services/edge-case-analyzer.js +321 -0
  402. package/dist/services/edge-case-analyzer.js.map +1 -0
  403. package/dist/services/edge-case-deduplicator.js +266 -0
  404. package/dist/services/edge-case-deduplicator.js.map +1 -0
  405. package/dist/services/edge-case-detector.js +337 -0
  406. package/dist/services/edge-case-detector.js.map +1 -0
  407. package/dist/services/edge-case-tracker.js +547 -0
  408. package/dist/services/edge-case-tracker.js.map +1 -0
  409. package/dist/services/health-check-system.js +586 -0
  410. package/dist/services/health-check-system.js.map +1 -0
  411. package/dist/services/metrics-logger.js +412 -0
  412. package/dist/services/metrics-logger.js.map +1 -0
  413. package/dist/services/patch-generator.js +378 -0
  414. package/dist/services/patch-generator.js.map +1 -0
  415. package/dist/services/patch-validator.js +337 -0
  416. package/dist/services/patch-validator.js.map +1 -0
  417. package/dist/services/performance-monitor.js +811 -0
  418. package/dist/services/performance-monitor.js.map +1 -0
  419. package/dist/services/promotion-pipeline.js +918 -0
  420. package/dist/services/promotion-pipeline.js.map +1 -0
  421. package/dist/services/promotion-validator.js +394 -0
  422. package/dist/services/promotion-validator.js.map +1 -0
  423. package/dist/services/reflection-logger.js +388 -0
  424. package/dist/services/reflection-logger.js.map +1 -0
  425. package/dist/services/skill-deployment.js +472 -0
  426. package/dist/services/skill-deployment.js.map +1 -0
  427. package/dist/services/skill-loader.js +427 -0
  428. package/dist/services/skill-loader.js.map +1 -0
  429. package/dist/services/skill-promotion.js +372 -0
  430. package/dist/services/skill-promotion.js.map +1 -0
  431. package/dist/services/skill-validator.js +454 -0
  432. package/dist/services/skill-validator.js.map +1 -0
  433. package/dist/services/skill-versioning.js +244 -0
  434. package/dist/services/skill-versioning.js.map +1 -0
  435. package/dist/services/workspace-supervisor.js +597 -0
  436. package/dist/services/workspace-supervisor.js.map +1 -0
  437. package/dist/types/edge-case.js +45 -0
  438. package/dist/types/edge-case.js.map +1 -0
  439. package/docs/BUG_19_MEMORY_LEAK_TASK_MODE.md +405 -0
  440. package/docs/MEMORY_CLEANUP_GUIDE.md +358 -0
  441. package/docs/MEMORY_LEAK_FIX_SUMMARY.md +322 -0
  442. package/docs/REDIS_CLEANUP_EXECUTIVE_SUMMARY.md +319 -0
  443. package/docs/REDIS_CLEANUP_VERIFICATION_REPORT.md +574 -0
  444. package/package.json +35 -4
  445. package/readme/README.md +53 -5
  446. package/scripts/backup-cleanup.sh +627 -0
  447. package/scripts/cleanup-workspaces.sh +412 -0
  448. package/scripts/cleanup-yaml-configs.sh +141 -0
  449. package/scripts/deploy-approved-skills.sh +263 -0
  450. package/scripts/health-check.sh +447 -0
  451. package/scripts/log-aggregator.sh +554 -0
  452. package/scripts/log-monitor.sh +629 -0
  453. package/scripts/manage-agent-workspaces.sh +434 -0
  454. package/scripts/migrate-schema.sh +533 -0
  455. package/scripts/promote-staged-skills.sh +423 -0
  456. package/scripts/verify-no-secrets.sh +88 -35
  457. package/scripts/verify-redis-cleanup.sh +173 -0
  458. package/tests/README.md +84 -0
  459. package/tests/test-memory-leak-task-mode.sh +435 -0
  460. package/.claude/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  461. package/.claude/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  462. package/.claude/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  463. package/.claude/skills/agent-lifecycle/SKILL.md +0 -60
  464. package/.claude/skills/agent-lifecycle/execute-lifecycle-hook.sh +0 -573
  465. package/.claude/skills/agent-lifecycle/simple-audit.sh +0 -31
  466. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  467. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
  468. package/README.md.backup_before_replace +0 -781
  469. package/claude-assets/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  470. package/claude-assets/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  471. package/claude-assets/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  472. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  473. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Conversation Fork Cleanup Utilities
3
+ *
4
+ * Provides memory leak prevention for Task Mode by:
5
+ * 1. Setting TTL on message lists (24h default)
6
+ * 2. Cleaning up completed task messages
7
+ * 3. Limiting message history size
8
+ * 4. Auto-cleanup of orphaned forks
9
+ */ import { execSync } from 'child_process';
10
+ const redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';
11
+ const redisPort = process.env.CFN_REDIS_PORT || '6379';
12
+ const DEFAULT_OPTIONS = {
13
+ messageTTL: 86400,
14
+ maxMessagesPerAgent: 100,
15
+ autoCleanupForks: true
16
+ };
17
+ /**
18
+ * Set TTL on message list to prevent indefinite accumulation
19
+ */ export function setMessageListTTL(taskId, agentId, ttlSeconds = DEFAULT_OPTIONS.messageTTL) {
20
+ const key = `swarm:${taskId}:${agentId}:messages`;
21
+ try {
22
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} expire "${key}" ${ttlSeconds}`, {
23
+ encoding: 'utf8'
24
+ });
25
+ console.log(`[conversation-cleanup] Set TTL ${ttlSeconds}s on ${key}`);
26
+ } catch (error) {
27
+ console.error(`[conversation-cleanup] Failed to set TTL:`, error);
28
+ }
29
+ }
30
+ /**
31
+ * Trim message list to max size (FIFO - keep recent messages)
32
+ */ export function trimMessageList(taskId, agentId, maxMessages = DEFAULT_OPTIONS.maxMessagesPerAgent) {
33
+ const key = `swarm:${taskId}:${agentId}:messages`;
34
+ try {
35
+ // Keep only the last N messages (0 = oldest, -N = keep last N)
36
+ const start = -maxMessages;
37
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} ltrim "${key}" ${start} -1`, {
38
+ encoding: 'utf8'
39
+ });
40
+ console.log(`[conversation-cleanup] Trimmed ${key} to ${maxMessages} messages`);
41
+ } catch (error) {
42
+ console.error(`[conversation-cleanup] Failed to trim messages:`, error);
43
+ }
44
+ }
45
+ /**
46
+ * Clean up all messages and forks for a completed task
47
+ */ export function cleanupTaskMessages(taskId, agentId) {
48
+ try {
49
+ // Delete main message list
50
+ const messagesKey = `swarm:${taskId}:${agentId}:messages`;
51
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} del "${messagesKey}"`, {
52
+ encoding: 'utf8'
53
+ });
54
+ // Delete all fork message lists
55
+ const forkPattern = `swarm:${taskId}:${agentId}:fork:*:messages`;
56
+ const forkKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys "${forkPattern}"`, {
57
+ encoding: 'utf8'
58
+ }).trim().split('\n').filter((k)=>k);
59
+ if (forkKeys.length > 0) {
60
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${forkKeys.join(' ')}`, {
61
+ encoding: 'utf8'
62
+ });
63
+ }
64
+ // Delete all fork metadata
65
+ const forkMetaPattern = `swarm:${taskId}:${agentId}:fork:*:meta`;
66
+ const metaKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys "${forkMetaPattern}"`, {
67
+ encoding: 'utf8'
68
+ }).trim().split('\n').filter((k)=>k);
69
+ if (metaKeys.length > 0) {
70
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${metaKeys.join(' ')}`, {
71
+ encoding: 'utf8'
72
+ });
73
+ }
74
+ // Delete current fork pointer
75
+ const currentForkKey = `swarm:${taskId}:${agentId}:current-fork`;
76
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} del "${currentForkKey}"`, {
77
+ encoding: 'utf8'
78
+ });
79
+ console.log(`[conversation-cleanup] Cleaned up task ${taskId} agent ${agentId}`);
80
+ console.log(`[conversation-cleanup] Removed: 1 message list, ${forkKeys.length} fork snapshots, ${metaKeys.length} fork metadata`);
81
+ } catch (error) {
82
+ console.error(`[conversation-cleanup] Failed to cleanup task messages:`, error);
83
+ }
84
+ }
85
+ /**
86
+ * Clean up orphaned forks (metadata expired but messages remain)
87
+ */ export function cleanupOrphanedForks(taskId, agentId) {
88
+ try {
89
+ // Find all fork message keys
90
+ const forkPattern = `swarm:${taskId}:${agentId}:fork:*:messages`;
91
+ const forkMessageKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys "${forkPattern}"`, {
92
+ encoding: 'utf8'
93
+ }).trim().split('\n').filter((k)=>k);
94
+ if (forkMessageKeys.length === 0) {
95
+ return;
96
+ }
97
+ const orphanedKeys = [];
98
+ for (const messageKey of forkMessageKeys){
99
+ // Extract fork ID from key: swarm:task:agent:fork:FORK_ID:messages
100
+ const parts = messageKey.split(':');
101
+ const forkId = parts[parts.length - 2];
102
+ // Check if metadata exists
103
+ const metaKey = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;
104
+ const metaExists = execSync(`redis-cli -h ${redisHost} -p ${redisPort} exists "${metaKey}"`, {
105
+ encoding: 'utf8'
106
+ }).trim();
107
+ if (metaExists === '0') {
108
+ // Metadata expired but messages remain = orphaned
109
+ orphanedKeys.push(messageKey);
110
+ }
111
+ }
112
+ if (orphanedKeys.length > 0) {
113
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${orphanedKeys.join(' ')}`, {
114
+ encoding: 'utf8'
115
+ });
116
+ console.log(`[conversation-cleanup] Removed ${orphanedKeys.length} orphaned fork snapshots`);
117
+ }
118
+ } catch (error) {
119
+ console.error(`[conversation-cleanup] Failed to cleanup orphaned forks:`, error);
120
+ }
121
+ }
122
+ /**
123
+ * Get memory usage statistics for a task
124
+ */ export function getTaskMemoryStats(taskId, agentId) {
125
+ try {
126
+ // Count messages in main list
127
+ const messagesKey = `swarm:${taskId}:${agentId}:messages`;
128
+ const messageCount = parseInt(execSync(`redis-cli -h ${redisHost} -p ${redisPort} llen "${messagesKey}"`, {
129
+ encoding: 'utf8'
130
+ }).trim(), 10);
131
+ // Count forks
132
+ const forkPattern = `swarm:${taskId}:${agentId}:fork:*:messages`;
133
+ const forkKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys "${forkPattern}"`, {
134
+ encoding: 'utf8'
135
+ }).trim().split('\n').filter((k)=>k);
136
+ // Estimate size (average message ~5KB)
137
+ const estimatedSizeKB = messageCount * 5;
138
+ return {
139
+ messageCount,
140
+ forkCount: forkKeys.length,
141
+ estimatedSizeKB
142
+ };
143
+ } catch (error) {
144
+ console.error(`[conversation-cleanup] Failed to get memory stats:`, error);
145
+ return {
146
+ messageCount: 0,
147
+ forkCount: 0,
148
+ estimatedSizeKB: 0
149
+ };
150
+ }
151
+ }
152
+ /**
153
+ * Configure automatic cleanup options for a task
154
+ */ export function configureAutoCleanup(taskId, agentId, options = {}) {
155
+ const config = {
156
+ ...DEFAULT_OPTIONS,
157
+ ...options
158
+ };
159
+ // Set TTL on message list
160
+ setMessageListTTL(taskId, agentId, config.messageTTL);
161
+ // Trim to max size
162
+ trimMessageList(taskId, agentId, config.maxMessagesPerAgent);
163
+ // Cleanup orphaned forks
164
+ if (config.autoCleanupForks) {
165
+ cleanupOrphanedForks(taskId, agentId);
166
+ }
167
+ console.log(`[conversation-cleanup] Auto-cleanup configured for ${taskId}/${agentId}`);
168
+ console.log(`[conversation-cleanup] - TTL: ${config.messageTTL}s`);
169
+ console.log(`[conversation-cleanup] - Max messages: ${config.maxMessagesPerAgent}`);
170
+ console.log(`[conversation-cleanup] - Auto-cleanup forks: ${config.autoCleanupForks}`);
171
+ }
172
+ /**
173
+ * Emergency cleanup - remove all conversation data for all tasks
174
+ * USE WITH CAUTION: This will delete ALL conversation history
175
+ */ export function emergencyCleanupAll() {
176
+ try {
177
+ const patterns = [
178
+ 'swarm:*:*:messages',
179
+ 'swarm:*:*:fork:*:messages',
180
+ 'swarm:*:*:fork:*:meta',
181
+ 'swarm:*:*:current-fork'
182
+ ];
183
+ let totalDeleted = 0;
184
+ for (const pattern of patterns){
185
+ const keys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys "${pattern}"`, {
186
+ encoding: 'utf8'
187
+ }).trim().split('\n').filter((k)=>k);
188
+ if (keys.length > 0) {
189
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${keys.join(' ')}`, {
190
+ encoding: 'utf8'
191
+ });
192
+ totalDeleted += keys.length;
193
+ }
194
+ }
195
+ console.log(`[conversation-cleanup] EMERGENCY CLEANUP: Deleted ${totalDeleted} conversation keys`);
196
+ } catch (error) {
197
+ console.error(`[conversation-cleanup] Failed emergency cleanup:`, error);
198
+ }
199
+ }
200
+
201
+ //# sourceMappingURL=conversation-fork-cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/conversation-fork-cleanup.ts"],"sourcesContent":["/**\r\n * Conversation Fork Cleanup Utilities\r\n *\r\n * Provides memory leak prevention for Task Mode by:\r\n * 1. Setting TTL on message lists (24h default)\r\n * 2. Cleaning up completed task messages\r\n * 3. Limiting message history size\r\n * 4. Auto-cleanup of orphaned forks\r\n */\r\n\r\nimport { execSync } from 'child_process';\r\n\r\nconst redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';\r\nconst redisPort = process.env.CFN_REDIS_PORT || '6379';\r\n\r\nexport interface CleanupOptions {\r\n messageTTL?: number; // TTL for message lists (seconds, default: 86400 = 24h)\r\n maxMessagesPerAgent?: number; // Max messages to keep per agent (default: 100)\r\n autoCleanupForks?: boolean; // Auto-cleanup orphaned forks (default: true)\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<CleanupOptions> = {\r\n messageTTL: 86400, // 24 hours\r\n maxMessagesPerAgent: 100, // 100 messages = ~50 iterations\r\n autoCleanupForks: true,\r\n};\r\n\r\n/**\r\n * Set TTL on message list to prevent indefinite accumulation\r\n */\r\nexport function setMessageListTTL(\r\n taskId: string,\r\n agentId: string,\r\n ttlSeconds: number = DEFAULT_OPTIONS.messageTTL\r\n): void {\r\n const key = `swarm:${taskId}:${agentId}:messages`;\r\n\r\n try {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} expire \"${key}\" ${ttlSeconds}`, {\r\n encoding: 'utf8'\r\n });\r\n console.log(`[conversation-cleanup] Set TTL ${ttlSeconds}s on ${key}`);\r\n } catch (error) {\r\n console.error(`[conversation-cleanup] Failed to set TTL:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Trim message list to max size (FIFO - keep recent messages)\r\n */\r\nexport function trimMessageList(\r\n taskId: string,\r\n agentId: string,\r\n maxMessages: number = DEFAULT_OPTIONS.maxMessagesPerAgent\r\n): void {\r\n const key = `swarm:${taskId}:${agentId}:messages`;\r\n\r\n try {\r\n // Keep only the last N messages (0 = oldest, -N = keep last N)\r\n const start = -maxMessages;\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} ltrim \"${key}\" ${start} -1`, {\r\n encoding: 'utf8'\r\n });\r\n console.log(`[conversation-cleanup] Trimmed ${key} to ${maxMessages} messages`);\r\n } catch (error) {\r\n console.error(`[conversation-cleanup] Failed to trim messages:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Clean up all messages and forks for a completed task\r\n */\r\nexport function cleanupTaskMessages(taskId: string, agentId: string): void {\r\n try {\r\n // Delete main message list\r\n const messagesKey = `swarm:${taskId}:${agentId}:messages`;\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del \"${messagesKey}\"`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n // Delete all fork message lists\r\n const forkPattern = `swarm:${taskId}:${agentId}:fork:*:messages`;\r\n const forkKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys \"${forkPattern}\"`, {\r\n encoding: 'utf8'\r\n }).trim().split('\\n').filter(k => k);\r\n\r\n if (forkKeys.length > 0) {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${forkKeys.join(' ')}`, {\r\n encoding: 'utf8'\r\n });\r\n }\r\n\r\n // Delete all fork metadata\r\n const forkMetaPattern = `swarm:${taskId}:${agentId}:fork:*:meta`;\r\n const metaKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys \"${forkMetaPattern}\"`, {\r\n encoding: 'utf8'\r\n }).trim().split('\\n').filter(k => k);\r\n\r\n if (metaKeys.length > 0) {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${metaKeys.join(' ')}`, {\r\n encoding: 'utf8'\r\n });\r\n }\r\n\r\n // Delete current fork pointer\r\n const currentForkKey = `swarm:${taskId}:${agentId}:current-fork`;\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del \"${currentForkKey}\"`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n console.log(`[conversation-cleanup] Cleaned up task ${taskId} agent ${agentId}`);\r\n console.log(`[conversation-cleanup] Removed: 1 message list, ${forkKeys.length} fork snapshots, ${metaKeys.length} fork metadata`);\r\n } catch (error) {\r\n console.error(`[conversation-cleanup] Failed to cleanup task messages:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Clean up orphaned forks (metadata expired but messages remain)\r\n */\r\nexport function cleanupOrphanedForks(taskId: string, agentId: string): void {\r\n try {\r\n // Find all fork message keys\r\n const forkPattern = `swarm:${taskId}:${agentId}:fork:*:messages`;\r\n const forkMessageKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys \"${forkPattern}\"`, {\r\n encoding: 'utf8'\r\n }).trim().split('\\n').filter(k => k);\r\n\r\n if (forkMessageKeys.length === 0) {\r\n return;\r\n }\r\n\r\n const orphanedKeys: string[] = [];\r\n\r\n for (const messageKey of forkMessageKeys) {\r\n // Extract fork ID from key: swarm:task:agent:fork:FORK_ID:messages\r\n const parts = messageKey.split(':');\r\n const forkId = parts[parts.length - 2];\r\n\r\n // Check if metadata exists\r\n const metaKey = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;\r\n const metaExists = execSync(`redis-cli -h ${redisHost} -p ${redisPort} exists \"${metaKey}\"`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (metaExists === '0') {\r\n // Metadata expired but messages remain = orphaned\r\n orphanedKeys.push(messageKey);\r\n }\r\n }\r\n\r\n if (orphanedKeys.length > 0) {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${orphanedKeys.join(' ')}`, {\r\n encoding: 'utf8'\r\n });\r\n console.log(`[conversation-cleanup] Removed ${orphanedKeys.length} orphaned fork snapshots`);\r\n }\r\n } catch (error) {\r\n console.error(`[conversation-cleanup] Failed to cleanup orphaned forks:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Get memory usage statistics for a task\r\n */\r\nexport function getTaskMemoryStats(taskId: string, agentId: string): {\r\n messageCount: number;\r\n forkCount: number;\r\n estimatedSizeKB: number;\r\n} {\r\n try {\r\n // Count messages in main list\r\n const messagesKey = `swarm:${taskId}:${agentId}:messages`;\r\n const messageCount = parseInt(execSync(`redis-cli -h ${redisHost} -p ${redisPort} llen \"${messagesKey}\"`, {\r\n encoding: 'utf8'\r\n }).trim(), 10);\r\n\r\n // Count forks\r\n const forkPattern = `swarm:${taskId}:${agentId}:fork:*:messages`;\r\n const forkKeys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys \"${forkPattern}\"`, {\r\n encoding: 'utf8'\r\n }).trim().split('\\n').filter(k => k);\r\n\r\n // Estimate size (average message ~5KB)\r\n const estimatedSizeKB = messageCount * 5;\r\n\r\n return {\r\n messageCount,\r\n forkCount: forkKeys.length,\r\n estimatedSizeKB,\r\n };\r\n } catch (error) {\r\n console.error(`[conversation-cleanup] Failed to get memory stats:`, error);\r\n return {\r\n messageCount: 0,\r\n forkCount: 0,\r\n estimatedSizeKB: 0,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Configure automatic cleanup options for a task\r\n */\r\nexport function configureAutoCleanup(\r\n taskId: string,\r\n agentId: string,\r\n options: CleanupOptions = {}\r\n): void {\r\n const config = { ...DEFAULT_OPTIONS, ...options };\r\n\r\n // Set TTL on message list\r\n setMessageListTTL(taskId, agentId, config.messageTTL);\r\n\r\n // Trim to max size\r\n trimMessageList(taskId, agentId, config.maxMessagesPerAgent);\r\n\r\n // Cleanup orphaned forks\r\n if (config.autoCleanupForks) {\r\n cleanupOrphanedForks(taskId, agentId);\r\n }\r\n\r\n console.log(`[conversation-cleanup] Auto-cleanup configured for ${taskId}/${agentId}`);\r\n console.log(`[conversation-cleanup] - TTL: ${config.messageTTL}s`);\r\n console.log(`[conversation-cleanup] - Max messages: ${config.maxMessagesPerAgent}`);\r\n console.log(`[conversation-cleanup] - Auto-cleanup forks: ${config.autoCleanupForks}`);\r\n}\r\n\r\n/**\r\n * Emergency cleanup - remove all conversation data for all tasks\r\n * USE WITH CAUTION: This will delete ALL conversation history\r\n */\r\nexport function emergencyCleanupAll(): void {\r\n try {\r\n const patterns = [\r\n 'swarm:*:*:messages',\r\n 'swarm:*:*:fork:*:messages',\r\n 'swarm:*:*:fork:*:meta',\r\n 'swarm:*:*:current-fork',\r\n ];\r\n\r\n let totalDeleted = 0;\r\n\r\n for (const pattern of patterns) {\r\n const keys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys \"${pattern}\"`, {\r\n encoding: 'utf8'\r\n }).trim().split('\\n').filter(k => k);\r\n\r\n if (keys.length > 0) {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del ${keys.join(' ')}`, {\r\n encoding: 'utf8'\r\n });\r\n totalDeleted += keys.length;\r\n }\r\n }\r\n\r\n console.log(`[conversation-cleanup] EMERGENCY CLEANUP: Deleted ${totalDeleted} conversation keys`);\r\n } catch (error) {\r\n console.error(`[conversation-cleanup] Failed emergency cleanup:`, error);\r\n }\r\n}\r\n"],"names":["execSync","redisHost","process","env","CFN_REDIS_HOST","redisPort","CFN_REDIS_PORT","DEFAULT_OPTIONS","messageTTL","maxMessagesPerAgent","autoCleanupForks","setMessageListTTL","taskId","agentId","ttlSeconds","key","encoding","console","log","error","trimMessageList","maxMessages","start","cleanupTaskMessages","messagesKey","forkPattern","forkKeys","trim","split","filter","k","length","join","forkMetaPattern","metaKeys","currentForkKey","cleanupOrphanedForks","forkMessageKeys","orphanedKeys","messageKey","parts","forkId","metaKey","metaExists","push","getTaskMemoryStats","messageCount","parseInt","estimatedSizeKB","forkCount","configureAutoCleanup","options","config","emergencyCleanupAll","patterns","totalDeleted","pattern","keys"],"mappings":"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"}
@@ -12,6 +12,7 @@ const redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';
12
12
  const redisPort = process.env.CFN_REDIS_PORT || '6379';
13
13
  /**
14
14
  * Store a message in conversation history
15
+ * MEMORY LEAK FIX: Now sets TTL on message list to prevent indefinite accumulation
15
16
  */ export async function storeMessage(taskId, agentId, message) {
16
17
  const key = `swarm:${taskId}:${agentId}:messages`;
17
18
  const messageJson = JSON.stringify(message);
@@ -19,6 +20,12 @@ const redisPort = process.env.CFN_REDIS_PORT || '6379';
19
20
  execSync(`redis-cli -h ${redisHost} -p ${redisPort} rpush "${key}" '${messageJson.replace(/'/g, "'\\''")}'`, {
20
21
  encoding: 'utf8'
21
22
  });
23
+ // MEMORY LEAK FIX: Set TTL on message list (24h default)
24
+ // This prevents messages from accumulating indefinitely across multiple tasks
25
+ const messageTTL = parseInt(process.env.CFN_MESSAGE_TTL || '86400', 10); // 24 hours
26
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} expire "${key}" ${messageTTL}`, {
27
+ encoding: 'utf8'
28
+ });
22
29
  } catch (error) {
23
30
  console.error(`[conversation-fork] Failed to store message:`, error);
24
31
  throw error;
@@ -46,6 +53,7 @@ const redisPort = process.env.CFN_REDIS_PORT || '6379';
46
53
  /**
47
54
  * Create a fork from current conversation state
48
55
  * Copies all messages up to current iteration
56
+ * MEMORY LEAK FIX: Now sets TTL on fork message list matching metadata TTL
49
57
  */ export async function createFork(taskId, agentId, currentIteration) {
50
58
  // Generate unique fork ID
51
59
  const forkId = `fork-${currentIteration}-${randomBytes(4).toString('hex')}`;
@@ -57,12 +65,17 @@ const redisPort = process.env.CFN_REDIS_PORT || '6379';
57
65
  }
58
66
  // Store fork snapshot
59
67
  const forkKey = `swarm:${taskId}:${agentId}:fork:${forkId}:messages`;
68
+ const forkTTL = parseInt(process.env.CFN_FORK_TTL || '86400', 10); // 24 hours
60
69
  for (const message of forkMessages){
61
70
  const messageJson = JSON.stringify(message);
62
71
  execSync(`redis-cli -h ${redisHost} -p ${redisPort} rpush "${forkKey}" '${messageJson.replace(/'/g, "'\\''")}'`, {
63
72
  encoding: 'utf8'
64
73
  });
65
74
  }
75
+ // MEMORY LEAK FIX: Set TTL on fork messages (was missing before)
76
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} expire "${forkKey}" ${forkTTL}`, {
77
+ encoding: 'utf8'
78
+ });
66
79
  // Store fork metadata
67
80
  const metadata = {
68
81
  forkId,
@@ -73,15 +86,15 @@ const redisPort = process.env.CFN_REDIS_PORT || '6379';
73
86
  messageCount: forkMessages.length
74
87
  };
75
88
  const metaKey = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;
76
- execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex "${metaKey}" 86400 '${JSON.stringify(metadata)}'`, {
89
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex "${metaKey}" ${forkTTL} '${JSON.stringify(metadata)}'`, {
77
90
  encoding: 'utf8'
78
91
  });
79
92
  // Set as current fork
80
93
  const currentForkKey = `swarm:${taskId}:${agentId}:current-fork`;
81
- execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex "${currentForkKey}" 86400 "${forkId}"`, {
94
+ execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex "${currentForkKey}" ${forkTTL} "${forkId}"`, {
82
95
  encoding: 'utf8'
83
96
  });
84
- console.log(`[conversation-fork] Created fork ${forkId} with ${forkMessages.length} messages`);
97
+ console.log(`[conversation-fork] Created fork ${forkId} with ${forkMessages.length} messages (TTL: ${forkTTL}s)`);
85
98
  return forkId;
86
99
  }
87
100
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/conversation-fork.ts"],"sourcesContent":["/**\r\n * Conversation Fork Management\r\n *\r\n * Implements application-level conversation forking for CFN Loop iterations.\r\n * Stores conversation history in Redis and allows branching at specific points.\r\n *\r\n * Sprint 4: Conversation Forking (v2.7.0)\r\n */\r\n\r\nimport { execSync } from 'child_process';\r\nimport { randomBytes } from 'crypto';\r\n\r\n// Bug #6 Fix: Read Redis connection parameters from process.env\r\nconst redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';\r\nconst redisPort = process.env.CFN_REDIS_PORT || '6379';\r\n\r\nexport interface Message {\r\n role: 'user' | 'assistant';\r\n content: string;\r\n iteration: number;\r\n timestamp: string;\r\n}\r\n\r\nexport interface ForkMetadata {\r\n forkId: string;\r\n taskId: string;\r\n agentId: string;\r\n createdAt: string;\r\n parentIteration: number;\r\n messageCount: number;\r\n}\r\n\r\n/**\r\n * Store a message in conversation history\r\n */\r\nexport async function storeMessage(\r\n taskId: string,\r\n agentId: string,\r\n message: Message\r\n): Promise<void> {\r\n const key = `swarm:${taskId}:${agentId}:messages`;\r\n const messageJson = JSON.stringify(message);\r\n\r\n try {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} rpush \"${key}\" '${messageJson.replace(/'/g, \"'\\\\''\")}'`, {\r\n encoding: 'utf8'\r\n });\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to store message:`, error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load all messages from conversation history\r\n */\r\nexport async function loadMessages(\r\n taskId: string,\r\n agentId: string,\r\n forkId?: string\r\n): Promise<Message[]> {\r\n const key = forkId\r\n ? `swarm:${taskId}:${agentId}:fork:${forkId}:messages`\r\n : `swarm:${taskId}:${agentId}:messages`;\r\n\r\n try {\r\n const output = execSync(`redis-cli -h ${redisHost} -p ${redisPort} lrange \"${key}\" 0 -1`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (!output || output === '(empty array)') {\r\n return [];\r\n }\r\n\r\n // Redis returns each message on a new line\r\n const lines = output.split('\\n');\r\n return lines.map(line => JSON.parse(line));\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to load messages:`, error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Create a fork from current conversation state\r\n * Copies all messages up to current iteration\r\n */\r\nexport async function createFork(\r\n taskId: string,\r\n agentId: string,\r\n currentIteration: number\r\n): Promise<string> {\r\n // Generate unique fork ID\r\n const forkId = `fork-${currentIteration}-${randomBytes(4).toString('hex')}`;\r\n\r\n // Load messages up to current iteration\r\n const messages = await loadMessages(taskId, agentId);\r\n const forkMessages = messages.filter(m => m.iteration <= currentIteration);\r\n\r\n if (forkMessages.length === 0) {\r\n throw new Error(`No messages found for iteration ${currentIteration}`);\r\n }\r\n\r\n // Store fork snapshot\r\n const forkKey = `swarm:${taskId}:${agentId}:fork:${forkId}:messages`;\r\n\r\n for (const message of forkMessages) {\r\n const messageJson = JSON.stringify(message);\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} rpush \"${forkKey}\" '${messageJson.replace(/'/g, \"'\\\\''\")}'`, {\r\n encoding: 'utf8'\r\n });\r\n }\r\n\r\n // Store fork metadata\r\n const metadata: ForkMetadata = {\r\n forkId,\r\n taskId,\r\n agentId,\r\n createdAt: new Date().toISOString(),\r\n parentIteration: currentIteration,\r\n messageCount: forkMessages.length\r\n };\r\n\r\n const metaKey = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex \"${metaKey}\" 86400 '${JSON.stringify(metadata)}'`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n // Set as current fork\r\n const currentForkKey = `swarm:${taskId}:${agentId}:current-fork`;\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex \"${currentForkKey}\" 86400 \"${forkId}\"`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n console.log(`[conversation-fork] Created fork ${forkId} with ${forkMessages.length} messages`);\r\n\r\n return forkId;\r\n}\r\n\r\n/**\r\n * Get current active fork ID\r\n */\r\nexport async function getCurrentFork(\r\n taskId: string,\r\n agentId: string\r\n): Promise<string | null> {\r\n const key = `swarm:${taskId}:${agentId}:current-fork`;\r\n\r\n try {\r\n const forkId = execSync(`redis-cli -h ${redisHost} -p ${redisPort} get \"${key}\"`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (forkId === '(nil)' || !forkId) {\r\n return null;\r\n }\r\n\r\n return forkId;\r\n } catch (error) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get fork metadata\r\n */\r\nexport async function getForkMetadata(\r\n taskId: string,\r\n agentId: string,\r\n forkId: string\r\n): Promise<ForkMetadata | null> {\r\n const key = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;\r\n\r\n try {\r\n const metaJson = execSync(`redis-cli -h ${redisHost} -p ${redisPort} get \"${key}\"`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (metaJson === '(nil)' || !metaJson) {\r\n return null;\r\n }\r\n\r\n return JSON.parse(metaJson);\r\n } catch (error) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * List all forks for an agent\r\n */\r\nexport async function listForks(\r\n taskId: string,\r\n agentId: string\r\n): Promise<ForkMetadata[]> {\r\n const pattern = `swarm:${taskId}:${agentId}:fork:*:meta`;\r\n\r\n try {\r\n const keys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys \"${pattern}\"`, {\r\n encoding: 'utf8'\r\n }).trim().split('\\n').filter(k => k);\r\n\r\n const forks: ForkMetadata[] = [];\r\n\r\n for (const key of keys) {\r\n const metaJson = execSync(`redis-cli -h ${redisHost} -p ${redisPort} get \"${key}\"`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (metaJson && metaJson !== '(nil)') {\r\n forks.push(JSON.parse(metaJson));\r\n }\r\n }\r\n\r\n return forks.sort((a, b) =>\r\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\r\n );\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to list forks:`, error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Delete a fork and its messages\r\n */\r\nexport async function deleteFork(\r\n taskId: string,\r\n agentId: string,\r\n forkId: string\r\n): Promise<void> {\r\n const messagesKey = `swarm:${taskId}:${agentId}:fork:${forkId}:messages`;\r\n const metaKey = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;\r\n\r\n try {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del \"${messagesKey}\" \"${metaKey}\"`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n console.log(`[conversation-fork] Deleted fork ${forkId}`);\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to delete fork:`, error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Clear current fork (start fresh conversation)\r\n */\r\nexport async function clearCurrentFork(\r\n taskId: string,\r\n agentId: string\r\n): Promise<void> {\r\n const key = `swarm:${taskId}:${agentId}:current-fork`;\r\n\r\n try {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del \"${key}\"`, {\r\n encoding: 'utf8'\r\n });\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to clear current fork:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Format messages for Anthropic API\r\n */\r\nexport function formatMessagesForAPI(messages: Message[]): Array<{role: string, content: string}> {\r\n return messages.map(m => ({\r\n role: m.role,\r\n content: m.content\r\n }));\r\n}\r\n\r\n/**\r\n * Get conversation statistics\r\n */\r\nexport async function getConversationStats(\r\n taskId: string,\r\n agentId: string,\r\n forkId?: string\r\n): Promise<{\r\n messageCount: number;\r\n userMessages: number;\r\n assistantMessages: number;\r\n iterations: number;\r\n firstMessage: string | null;\r\n lastMessage: string | null;\r\n}> {\r\n const messages = await loadMessages(taskId, agentId, forkId);\r\n\r\n if (messages.length === 0) {\r\n return {\r\n messageCount: 0,\r\n userMessages: 0,\r\n assistantMessages: 0,\r\n iterations: 0,\r\n firstMessage: null,\r\n lastMessage: null\r\n };\r\n }\r\n\r\n const userMessages = messages.filter(m => m.role === 'user').length;\r\n const assistantMessages = messages.filter(m => m.role === 'assistant').length;\r\n const iterations = Math.max(...messages.map(m => m.iteration));\r\n\r\n return {\r\n messageCount: messages.length,\r\n userMessages,\r\n assistantMessages,\r\n iterations,\r\n firstMessage: messages[0].timestamp,\r\n lastMessage: messages[messages.length - 1].timestamp\r\n };\r\n}\r\n"],"names":["execSync","randomBytes","redisHost","process","env","CFN_REDIS_HOST","redisPort","CFN_REDIS_PORT","storeMessage","taskId","agentId","message","key","messageJson","JSON","stringify","replace","encoding","error","console","loadMessages","forkId","output","trim","lines","split","map","line","parse","createFork","currentIteration","toString","messages","forkMessages","filter","m","iteration","length","Error","forkKey","metadata","createdAt","Date","toISOString","parentIteration","messageCount","metaKey","currentForkKey","log","getCurrentFork","getForkMetadata","metaJson","listForks","pattern","keys","k","forks","push","sort","a","b","getTime","deleteFork","messagesKey","clearCurrentFork","formatMessagesForAPI","role","content","getConversationStats","userMessages","assistantMessages","iterations","firstMessage","lastMessage","Math","max","timestamp"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/cli/conversation-fork.ts"],"sourcesContent":["/**\r\n * Conversation Fork Management\r\n *\r\n * Implements application-level conversation forking for CFN Loop iterations.\r\n * Stores conversation history in Redis and allows branching at specific points.\r\n *\r\n * Sprint 4: Conversation Forking (v2.7.0)\r\n */\r\n\r\nimport { execSync } from 'child_process';\r\nimport { randomBytes } from 'crypto';\r\n\r\n// Bug #6 Fix: Read Redis connection parameters from process.env\r\nconst redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';\r\nconst redisPort = process.env.CFN_REDIS_PORT || '6379';\r\n\r\nexport interface Message {\r\n role: 'user' | 'assistant';\r\n content: string;\r\n iteration: number;\r\n timestamp: string;\r\n}\r\n\r\nexport interface ForkMetadata {\r\n forkId: string;\r\n taskId: string;\r\n agentId: string;\r\n createdAt: string;\r\n parentIteration: number;\r\n messageCount: number;\r\n}\r\n\r\n/**\r\n * Store a message in conversation history\r\n * MEMORY LEAK FIX: Now sets TTL on message list to prevent indefinite accumulation\r\n */\r\nexport async function storeMessage(\r\n taskId: string,\r\n agentId: string,\r\n message: Message\r\n): Promise<void> {\r\n const key = `swarm:${taskId}:${agentId}:messages`;\r\n const messageJson = JSON.stringify(message);\r\n\r\n try {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} rpush \"${key}\" '${messageJson.replace(/'/g, \"'\\\\''\")}'`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n // MEMORY LEAK FIX: Set TTL on message list (24h default)\r\n // This prevents messages from accumulating indefinitely across multiple tasks\r\n const messageTTL = parseInt(process.env.CFN_MESSAGE_TTL || '86400', 10); // 24 hours\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} expire \"${key}\" ${messageTTL}`, {\r\n encoding: 'utf8'\r\n });\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to store message:`, error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load all messages from conversation history\r\n */\r\nexport async function loadMessages(\r\n taskId: string,\r\n agentId: string,\r\n forkId?: string\r\n): Promise<Message[]> {\r\n const key = forkId\r\n ? `swarm:${taskId}:${agentId}:fork:${forkId}:messages`\r\n : `swarm:${taskId}:${agentId}:messages`;\r\n\r\n try {\r\n const output = execSync(`redis-cli -h ${redisHost} -p ${redisPort} lrange \"${key}\" 0 -1`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (!output || output === '(empty array)') {\r\n return [];\r\n }\r\n\r\n // Redis returns each message on a new line\r\n const lines = output.split('\\n');\r\n return lines.map(line => JSON.parse(line));\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to load messages:`, error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Create a fork from current conversation state\r\n * Copies all messages up to current iteration\r\n * MEMORY LEAK FIX: Now sets TTL on fork message list matching metadata TTL\r\n */\r\nexport async function createFork(\r\n taskId: string,\r\n agentId: string,\r\n currentIteration: number\r\n): Promise<string> {\r\n // Generate unique fork ID\r\n const forkId = `fork-${currentIteration}-${randomBytes(4).toString('hex')}`;\r\n\r\n // Load messages up to current iteration\r\n const messages = await loadMessages(taskId, agentId);\r\n const forkMessages = messages.filter(m => m.iteration <= currentIteration);\r\n\r\n if (forkMessages.length === 0) {\r\n throw new Error(`No messages found for iteration ${currentIteration}`);\r\n }\r\n\r\n // Store fork snapshot\r\n const forkKey = `swarm:${taskId}:${agentId}:fork:${forkId}:messages`;\r\n const forkTTL = parseInt(process.env.CFN_FORK_TTL || '86400', 10); // 24 hours\r\n\r\n for (const message of forkMessages) {\r\n const messageJson = JSON.stringify(message);\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} rpush \"${forkKey}\" '${messageJson.replace(/'/g, \"'\\\\''\")}'`, {\r\n encoding: 'utf8'\r\n });\r\n }\r\n\r\n // MEMORY LEAK FIX: Set TTL on fork messages (was missing before)\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} expire \"${forkKey}\" ${forkTTL}`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n // Store fork metadata\r\n const metadata: ForkMetadata = {\r\n forkId,\r\n taskId,\r\n agentId,\r\n createdAt: new Date().toISOString(),\r\n parentIteration: currentIteration,\r\n messageCount: forkMessages.length\r\n };\r\n\r\n const metaKey = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex \"${metaKey}\" ${forkTTL} '${JSON.stringify(metadata)}'`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n // Set as current fork\r\n const currentForkKey = `swarm:${taskId}:${agentId}:current-fork`;\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} setex \"${currentForkKey}\" ${forkTTL} \"${forkId}\"`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n console.log(`[conversation-fork] Created fork ${forkId} with ${forkMessages.length} messages (TTL: ${forkTTL}s)`);\r\n\r\n return forkId;\r\n}\r\n\r\n/**\r\n * Get current active fork ID\r\n */\r\nexport async function getCurrentFork(\r\n taskId: string,\r\n agentId: string\r\n): Promise<string | null> {\r\n const key = `swarm:${taskId}:${agentId}:current-fork`;\r\n\r\n try {\r\n const forkId = execSync(`redis-cli -h ${redisHost} -p ${redisPort} get \"${key}\"`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (forkId === '(nil)' || !forkId) {\r\n return null;\r\n }\r\n\r\n return forkId;\r\n } catch (error) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get fork metadata\r\n */\r\nexport async function getForkMetadata(\r\n taskId: string,\r\n agentId: string,\r\n forkId: string\r\n): Promise<ForkMetadata | null> {\r\n const key = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;\r\n\r\n try {\r\n const metaJson = execSync(`redis-cli -h ${redisHost} -p ${redisPort} get \"${key}\"`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (metaJson === '(nil)' || !metaJson) {\r\n return null;\r\n }\r\n\r\n return JSON.parse(metaJson);\r\n } catch (error) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * List all forks for an agent\r\n */\r\nexport async function listForks(\r\n taskId: string,\r\n agentId: string\r\n): Promise<ForkMetadata[]> {\r\n const pattern = `swarm:${taskId}:${agentId}:fork:*:meta`;\r\n\r\n try {\r\n const keys = execSync(`redis-cli -h ${redisHost} -p ${redisPort} keys \"${pattern}\"`, {\r\n encoding: 'utf8'\r\n }).trim().split('\\n').filter(k => k);\r\n\r\n const forks: ForkMetadata[] = [];\r\n\r\n for (const key of keys) {\r\n const metaJson = execSync(`redis-cli -h ${redisHost} -p ${redisPort} get \"${key}\"`, {\r\n encoding: 'utf8'\r\n }).trim();\r\n\r\n if (metaJson && metaJson !== '(nil)') {\r\n forks.push(JSON.parse(metaJson));\r\n }\r\n }\r\n\r\n return forks.sort((a, b) =>\r\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\r\n );\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to list forks:`, error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Delete a fork and its messages\r\n */\r\nexport async function deleteFork(\r\n taskId: string,\r\n agentId: string,\r\n forkId: string\r\n): Promise<void> {\r\n const messagesKey = `swarm:${taskId}:${agentId}:fork:${forkId}:messages`;\r\n const metaKey = `swarm:${taskId}:${agentId}:fork:${forkId}:meta`;\r\n\r\n try {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del \"${messagesKey}\" \"${metaKey}\"`, {\r\n encoding: 'utf8'\r\n });\r\n\r\n console.log(`[conversation-fork] Deleted fork ${forkId}`);\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to delete fork:`, error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Clear current fork (start fresh conversation)\r\n */\r\nexport async function clearCurrentFork(\r\n taskId: string,\r\n agentId: string\r\n): Promise<void> {\r\n const key = `swarm:${taskId}:${agentId}:current-fork`;\r\n\r\n try {\r\n execSync(`redis-cli -h ${redisHost} -p ${redisPort} del \"${key}\"`, {\r\n encoding: 'utf8'\r\n });\r\n } catch (error) {\r\n console.error(`[conversation-fork] Failed to clear current fork:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Format messages for Anthropic API\r\n */\r\nexport function formatMessagesForAPI(messages: Message[]): Array<{role: string, content: string}> {\r\n return messages.map(m => ({\r\n role: m.role,\r\n content: m.content\r\n }));\r\n}\r\n\r\n/**\r\n * Get conversation statistics\r\n */\r\nexport async function getConversationStats(\r\n taskId: string,\r\n agentId: string,\r\n forkId?: string\r\n): Promise<{\r\n messageCount: number;\r\n userMessages: number;\r\n assistantMessages: number;\r\n iterations: number;\r\n firstMessage: string | null;\r\n lastMessage: string | null;\r\n}> {\r\n const messages = await loadMessages(taskId, agentId, forkId);\r\n\r\n if (messages.length === 0) {\r\n return {\r\n messageCount: 0,\r\n userMessages: 0,\r\n assistantMessages: 0,\r\n iterations: 0,\r\n firstMessage: null,\r\n lastMessage: null\r\n };\r\n }\r\n\r\n const userMessages = messages.filter(m => m.role === 'user').length;\r\n const assistantMessages = messages.filter(m => m.role === 'assistant').length;\r\n const iterations = Math.max(...messages.map(m => m.iteration));\r\n\r\n return {\r\n messageCount: messages.length,\r\n userMessages,\r\n assistantMessages,\r\n iterations,\r\n firstMessage: messages[0].timestamp,\r\n lastMessage: messages[messages.length - 1].timestamp\r\n };\r\n}\r\n"],"names":["execSync","randomBytes","redisHost","process","env","CFN_REDIS_HOST","redisPort","CFN_REDIS_PORT","storeMessage","taskId","agentId","message","key","messageJson","JSON","stringify","replace","encoding","messageTTL","parseInt","CFN_MESSAGE_TTL","error","console","loadMessages","forkId","output","trim","lines","split","map","line","parse","createFork","currentIteration","toString","messages","forkMessages","filter","m","iteration","length","Error","forkKey","forkTTL","CFN_FORK_TTL","metadata","createdAt","Date","toISOString","parentIteration","messageCount","metaKey","currentForkKey","log","getCurrentFork","getForkMetadata","metaJson","listForks","pattern","keys","k","forks","push","sort","a","b","getTime","deleteFork","messagesKey","clearCurrentFork","formatMessagesForAPI","role","content","getConversationStats","userMessages","assistantMessages","iterations","firstMessage","lastMessage","Math","max","timestamp"],"mappings":"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"}