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,451 @@
1
+ /**
2
+ * Distributed Lock Manager - Enhanced v2
3
+ *
4
+ * Provides distributed locking mechanism for cross-database transactions using Redis.
5
+ * Prevents concurrent modifications and ensures data consistency.
6
+ *
7
+ * Enhanced Features (Phase 2, Task P2-2.2):
8
+ * - Mandatory TTL enforcement with automatic expiration
9
+ * - Lock renewal mechanism for long-running operations
10
+ * - Auto-renewal with configurable interval
11
+ * - Lock health monitoring and statistics
12
+ * - Deadlock detection support
13
+ * - Stale lock cleanup
14
+ * - Backward compatible with existing usage
15
+ *
16
+ * Part of Task 3.1 (enhanced in Task P2-2.2)
17
+ */ import { randomUUID } from 'crypto';
18
+ import { createLogger } from './logging.js';
19
+ import { generateCorrelationId } from './correlation.js';
20
+ const logger = createLogger('distributed-lock');
21
+ /**
22
+ * Enhanced Redis-backed distributed lock manager
23
+ */ export class DistributedLockManager {
24
+ redisClient;
25
+ activeLocks = new Map();
26
+ renewalTimers = new Map();
27
+ statistics = {
28
+ totalAcquisitions: 0,
29
+ totalReleases: 0,
30
+ currentlyHeld: 0,
31
+ totalRenewals: 0,
32
+ averageDuration: 0,
33
+ failedAcquisitions: 0
34
+ };
35
+ lockDurations = [];
36
+ constructor(redisClient){
37
+ this.redisClient = redisClient;
38
+ logger.info('Enhanced distributed lock manager initialized (v2)');
39
+ }
40
+ /**
41
+ * Acquire lock on a resource with TTL enforcement and optional auto-renewal
42
+ */ async acquireLock(options) {
43
+ // Validate TTL (REQUIRED in v2)
44
+ if (options.ttl === undefined || options.ttl === null) {
45
+ // Backward compatibility: use default 60s TTL
46
+ options.ttl = 60000;
47
+ }
48
+ if (options.ttl <= 0) {
49
+ throw new Error('TTL must be positive');
50
+ }
51
+ const opts = {
52
+ timeout: options.timeout ?? 10000,
53
+ transactionId: options.transactionId,
54
+ retryInterval: options.retryInterval ?? 100,
55
+ correlationId: options.correlationId ?? generateCorrelationId()
56
+ };
57
+ const lockKey = this.buildLockKey(options.key);
58
+ const lockId = randomUUID();
59
+ const startTime = Date.now();
60
+ logger.debug('Attempting lock acquisition', {
61
+ lockKey,
62
+ lockId,
63
+ ttl: options.ttl,
64
+ renewInterval: options.renewInterval,
65
+ transactionId: opts.transactionId,
66
+ timeout: opts.timeout,
67
+ correlationId: opts.correlationId
68
+ });
69
+ // Try to acquire lock with timeout
70
+ while(Date.now() - startTime < opts.timeout){
71
+ const acquired = await this.tryAcquire(lockKey, lockId, options, opts);
72
+ if (acquired) {
73
+ const lock = {
74
+ id: lockId,
75
+ key: options.key,
76
+ acquiredAt: new Date(),
77
+ transactionId: opts.transactionId,
78
+ ttl: options.ttl,
79
+ renewInterval: options.renewInterval,
80
+ correlationId: opts.correlationId
81
+ };
82
+ this.activeLocks.set(lockId, lock);
83
+ this.statistics.totalAcquisitions++;
84
+ this.statistics.currentlyHeld++;
85
+ // Start auto-renewal if configured
86
+ if (options.renewInterval) {
87
+ this.startAutoRenewal(lock);
88
+ }
89
+ logger.info('Lock acquired successfully', {
90
+ lockId,
91
+ lockKey,
92
+ ttl: options.ttl,
93
+ renewInterval: options.renewInterval,
94
+ transactionId: opts.transactionId,
95
+ duration: Date.now() - startTime
96
+ });
97
+ return lock;
98
+ }
99
+ // Wait before retry
100
+ await this.sleep(opts.retryInterval);
101
+ }
102
+ // Timeout reached
103
+ const currentHolder = await this.getLockInfo(options.key);
104
+ this.statistics.failedAcquisitions++;
105
+ logger.warn('Lock acquisition timeout', {
106
+ lockKey,
107
+ lockId,
108
+ timeout: opts.timeout,
109
+ currentHolder,
110
+ correlationId: opts.correlationId
111
+ });
112
+ throw new LockAcquisitionError(`Failed to acquire lock on ${lockKey} within ${opts.timeout}ms`, lockKey, currentHolder);
113
+ }
114
+ /**
115
+ * Try to acquire lock atomically (single attempt)
116
+ */ async tryAcquire(lockKey, lockId, options, opts) {
117
+ try {
118
+ const now = new Date();
119
+ const metadata = {
120
+ lockId,
121
+ transactionId: opts.transactionId,
122
+ processId: process.pid,
123
+ acquiredAt: now.toISOString(),
124
+ expiresAt: new Date(now.getTime() + options.ttl).toISOString(),
125
+ correlationId: opts.correlationId
126
+ };
127
+ // Use Redis SET NX (set if not exists) with TTL (PX = milliseconds)
128
+ // This is atomic and prevents race conditions
129
+ const result = await this.redisClient.set(lockKey, JSON.stringify(metadata), 'PX', options.ttl, 'NX' // only set if not exists
130
+ );
131
+ return result === 'OK';
132
+ } catch (err) {
133
+ logger.error('Error during lock acquisition attempt', err, {
134
+ lockKey,
135
+ lockId
136
+ });
137
+ return false;
138
+ }
139
+ }
140
+ /**
141
+ * Renew lock TTL (extends expiration time)
142
+ */ async renewLock(lockId, ttl) {
143
+ const lock = this.activeLocks.get(lockId);
144
+ if (!lock) {
145
+ throw new LockOwnershipError(`Cannot renew lock ${lockId}: lock not found in active locks`, lockId, 'unknown');
146
+ }
147
+ const lockKey = this.buildLockKey(lock.key);
148
+ try {
149
+ // Get current lock metadata
150
+ const metadata = await this.getLockInfo(lock.key);
151
+ if (!metadata) {
152
+ throw new Error('Lock has expired or been released');
153
+ }
154
+ if (metadata.lockId !== lockId) {
155
+ throw new LockOwnershipError(`Cannot renew lock ${lockKey}: ownership mismatch`, lockId, metadata.lockId);
156
+ }
157
+ // Update expiration time
158
+ const now = new Date();
159
+ metadata.expiresAt = new Date(now.getTime() + ttl).toISOString();
160
+ metadata.lastRenewedAt = now.toISOString();
161
+ // Update Redis with new TTL
162
+ await this.redisClient.set(lockKey, JSON.stringify(metadata), 'PX', ttl);
163
+ // Update local lock object
164
+ lock.ttl = ttl;
165
+ this.statistics.totalRenewals++;
166
+ logger.debug('Lock renewed successfully', {
167
+ lockId,
168
+ lockKey,
169
+ newTtl: ttl
170
+ });
171
+ } catch (err) {
172
+ logger.error('Error renewing lock', err, {
173
+ lockId,
174
+ lockKey
175
+ });
176
+ throw err;
177
+ }
178
+ }
179
+ /**
180
+ * Start auto-renewal for a lock
181
+ */ startAutoRenewal(lock) {
182
+ if (!lock.renewInterval) {
183
+ return;
184
+ }
185
+ const timer = setInterval(async ()=>{
186
+ try {
187
+ await this.renewLock(lock.id, lock.ttl);
188
+ logger.debug('Auto-renewal completed', {
189
+ lockId: lock.id,
190
+ key: lock.key
191
+ });
192
+ } catch (err) {
193
+ logger.error('Auto-renewal failed', err, {
194
+ lockId: lock.id,
195
+ key: lock.key
196
+ });
197
+ // Stop renewal on failure
198
+ this.stopAutoRenewal(lock.id);
199
+ }
200
+ }, lock.renewInterval);
201
+ this.renewalTimers.set(lock.id, timer);
202
+ logger.debug('Auto-renewal started', {
203
+ lockId: lock.id,
204
+ key: lock.key,
205
+ interval: lock.renewInterval
206
+ });
207
+ }
208
+ /**
209
+ * Stop auto-renewal for a lock
210
+ */ stopAutoRenewal(lockId) {
211
+ const timer = this.renewalTimers.get(lockId);
212
+ if (timer) {
213
+ clearInterval(timer);
214
+ this.renewalTimers.delete(lockId);
215
+ logger.debug('Auto-renewal stopped', {
216
+ lockId
217
+ });
218
+ }
219
+ }
220
+ /**
221
+ * Release a lock manually
222
+ */ async releaseLock(lockId) {
223
+ const lock = this.activeLocks.get(lockId);
224
+ if (!lock) {
225
+ logger.warn('Lock not found in active locks', {
226
+ lockId
227
+ });
228
+ return;
229
+ }
230
+ const lockKey = this.buildLockKey(lock.key);
231
+ logger.debug('Releasing lock', {
232
+ lockId,
233
+ lockKey,
234
+ transactionId: lock.transactionId
235
+ });
236
+ try {
237
+ // Stop auto-renewal if active
238
+ this.stopAutoRenewal(lockId);
239
+ // Verify we own the lock before releasing
240
+ const metadata = await this.getLockInfo(lock.key);
241
+ if (!metadata) {
242
+ logger.warn('Lock already released or expired', {
243
+ lockId,
244
+ lockKey
245
+ });
246
+ this.activeLocks.delete(lockId);
247
+ this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);
248
+ return;
249
+ }
250
+ if (metadata.lockId !== lockId) {
251
+ logger.error('Lock ownership mismatch', new Error('Lock ownership mismatch'), {
252
+ expectedLockId: lockId,
253
+ actualLockId: metadata.lockId,
254
+ lockKey
255
+ });
256
+ throw new LockOwnershipError(`Cannot release lock ${lockKey}: ownership mismatch`, lockId, metadata.lockId);
257
+ }
258
+ // Delete lock from Redis
259
+ await this.redisClient.del(lockKey);
260
+ // Track duration for statistics
261
+ const duration = Date.now() - lock.acquiredAt.getTime();
262
+ this.lockDurations.push(duration);
263
+ // Keep only last 100 durations for average calculation
264
+ if (this.lockDurations.length > 100) {
265
+ this.lockDurations.shift();
266
+ }
267
+ // Update statistics
268
+ this.statistics.totalReleases++;
269
+ this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);
270
+ this.statistics.averageDuration = this.calculateAverageDuration();
271
+ this.activeLocks.delete(lockId);
272
+ logger.info('Lock released successfully', {
273
+ lockId,
274
+ lockKey,
275
+ duration,
276
+ transactionId: lock.transactionId
277
+ });
278
+ } catch (err) {
279
+ logger.error('Error releasing lock', err, {
280
+ lockId,
281
+ lockKey
282
+ });
283
+ throw err;
284
+ }
285
+ }
286
+ /**
287
+ * Check if a resource is currently locked
288
+ */ async isLocked(key) {
289
+ const lockKey = this.buildLockKey(key);
290
+ try {
291
+ const exists = await this.redisClient.exists(lockKey);
292
+ return exists === 1;
293
+ } catch (err) {
294
+ logger.error('Error checking lock status', err, {
295
+ lockKey
296
+ });
297
+ return false; // Assume unlocked on error (fail-safe)
298
+ }
299
+ }
300
+ /**
301
+ * Get lock metadata for a resource
302
+ */ async getLockInfo(key) {
303
+ const lockKey = this.buildLockKey(key);
304
+ try {
305
+ const data = await this.redisClient.get(lockKey);
306
+ if (!data) {
307
+ return null;
308
+ }
309
+ const metadata = JSON.parse(data);
310
+ return metadata;
311
+ } catch (err) {
312
+ logger.error('Error retrieving lock info', err, {
313
+ lockKey
314
+ });
315
+ return null;
316
+ }
317
+ }
318
+ /**
319
+ * Force release of a lock (admin operation - use with caution)
320
+ */ async forceRelease(key) {
321
+ const lockKey = this.buildLockKey(key);
322
+ logger.warn('Force releasing lock', {
323
+ lockKey
324
+ });
325
+ try {
326
+ await this.redisClient.del(lockKey);
327
+ // Clean up from active locks if present
328
+ for (const [id, lock] of Array.from(this.activeLocks.entries())){
329
+ if (lock.key === key) {
330
+ this.stopAutoRenewal(id);
331
+ this.activeLocks.delete(id);
332
+ this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);
333
+ }
334
+ }
335
+ logger.info('Lock force released', {
336
+ lockKey
337
+ });
338
+ } catch (err) {
339
+ logger.error('Error force releasing lock', err, {
340
+ lockKey
341
+ });
342
+ throw err;
343
+ }
344
+ }
345
+ /**
346
+ * Get all active locks managed by this instance
347
+ */ getActiveLocks() {
348
+ return Array.from(this.activeLocks.values());
349
+ }
350
+ /**
351
+ * Get lock statistics
352
+ */ getStatistics() {
353
+ return {
354
+ ...this.statistics
355
+ };
356
+ }
357
+ /**
358
+ * Clean up expired locks from tracking
359
+ */ cleanupExpiredLocks() {
360
+ const now = Date.now();
361
+ let cleaned = 0;
362
+ for (const [id, lock] of Array.from(this.activeLocks.entries())){
363
+ const expiresAt = lock.acquiredAt.getTime() + lock.ttl;
364
+ if (now > expiresAt) {
365
+ this.stopAutoRenewal(id);
366
+ this.activeLocks.delete(id);
367
+ this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);
368
+ cleaned++;
369
+ }
370
+ }
371
+ if (cleaned > 0) {
372
+ logger.debug('Cleaned up expired locks from tracking', {
373
+ count: cleaned
374
+ });
375
+ }
376
+ return cleaned;
377
+ }
378
+ /**
379
+ * Release all active locks (cleanup on shutdown)
380
+ */ async releaseAll() {
381
+ logger.info('Releasing all active locks', {
382
+ count: this.activeLocks.size
383
+ });
384
+ const releases = Array.from(this.activeLocks.values()).map((lock)=>this.releaseLock(lock.id).catch((err)=>{
385
+ logger.error('Error releasing lock during cleanup', err, {
386
+ lockId: lock.id
387
+ });
388
+ }));
389
+ await Promise.all(releases);
390
+ logger.info('All locks released');
391
+ }
392
+ /**
393
+ * Build Redis key for lock resource
394
+ */ buildLockKey(key) {
395
+ return `lock:${key}`;
396
+ }
397
+ /**
398
+ * Calculate average lock duration
399
+ */ calculateAverageDuration() {
400
+ if (this.lockDurations.length === 0) {
401
+ return 0;
402
+ }
403
+ const sum = this.lockDurations.reduce((acc, dur)=>acc + dur, 0);
404
+ return Math.round(sum / this.lockDurations.length);
405
+ }
406
+ /**
407
+ * Sleep utility for retry intervals
408
+ */ sleep(ms) {
409
+ return new Promise((resolve)=>setTimeout(resolve, ms));
410
+ }
411
+ }
412
+ /**
413
+ * Lock acquisition error
414
+ */ export class LockAcquisitionError extends Error {
415
+ lockKey;
416
+ currentHolder;
417
+ constructor(message, lockKey, currentHolder){
418
+ super(message), this.lockKey = lockKey, this.currentHolder = currentHolder;
419
+ this.name = 'LockAcquisitionError';
420
+ }
421
+ }
422
+ /**
423
+ * Lock ownership error
424
+ */ export class LockOwnershipError extends Error {
425
+ expectedLockId;
426
+ actualLockId;
427
+ constructor(message, expectedLockId, actualLockId){
428
+ super(message), this.expectedLockId = expectedLockId, this.actualLockId = actualLockId;
429
+ this.name = 'LockOwnershipError';
430
+ }
431
+ }
432
+ /**
433
+ * Utility: Execute function with distributed lock
434
+ */ export async function withLock(lockManager, key, fn, options) {
435
+ const lock = await lockManager.acquireLock({
436
+ key,
437
+ ttl: options?.ttl ?? 60000,
438
+ ...options
439
+ });
440
+ try {
441
+ const result = await fn();
442
+ await lockManager.releaseLock(lock.id);
443
+ return result;
444
+ } catch (err) {
445
+ await lockManager.releaseLock(lock.id);
446
+ throw err;
447
+ }
448
+ }
449
+ export { DistributedLockManager as DistributedLock };
450
+
451
+ //# sourceMappingURL=distributed-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/distributed-lock.ts"],"sourcesContent":["/**\r\n * Distributed Lock Manager - Enhanced v2\r\n *\r\n * Provides distributed locking mechanism for cross-database transactions using Redis.\r\n * Prevents concurrent modifications and ensures data consistency.\r\n *\r\n * Enhanced Features (Phase 2, Task P2-2.2):\r\n * - Mandatory TTL enforcement with automatic expiration\r\n * - Lock renewal mechanism for long-running operations\r\n * - Auto-renewal with configurable interval\r\n * - Lock health monitoring and statistics\r\n * - Deadlock detection support\r\n * - Stale lock cleanup\r\n * - Backward compatible with existing usage\r\n *\r\n * Part of Task 3.1 (enhanced in Task P2-2.2)\r\n */\r\n\r\nimport { randomUUID } from 'crypto';\r\nimport { createLogger } from './logging.js';\r\nimport { generateCorrelationId } from './correlation.js';\r\n\r\nconst logger = createLogger('distributed-lock');\r\n\r\n/**\r\n * Lock acquisition options (enhanced)\r\n */\r\nexport interface LockOptions {\r\n /** Lock resource key (required) */\r\n key: string;\r\n /** Auto-release TTL in milliseconds (REQUIRED in v2) */\r\n ttl: number;\r\n /** Lock acquisition timeout in milliseconds (default: 10000) */\r\n timeout?: number;\r\n /** Auto-renewal interval in milliseconds (optional, enables auto-renewal) */\r\n renewInterval?: number;\r\n /** Transaction ID to associate with lock */\r\n transactionId?: string;\r\n /** Retry interval for lock acquisition in milliseconds (default: 100) */\r\n retryInterval?: number;\r\n /** Correlation ID for tracking */\r\n correlationId?: string;\r\n}\r\n\r\n/**\r\n * Lock instance (enhanced)\r\n */\r\nexport interface Lock {\r\n /** Unique lock ID */\r\n id: string;\r\n /** Lock resource key */\r\n key: string;\r\n /** Lock acquisition timestamp */\r\n acquiredAt: Date;\r\n /** Associated transaction ID */\r\n transactionId?: string;\r\n /** Lock TTL in milliseconds */\r\n ttl: number;\r\n /** Auto-renewal interval (if enabled) */\r\n renewInterval?: number;\r\n /** Correlation ID */\r\n correlationId: string;\r\n}\r\n\r\n/**\r\n * Lock metadata (stored in Redis)\r\n */\r\nexport interface LockMetadata {\r\n /** Lock ID */\r\n lockId: string;\r\n /** Transaction ID */\r\n transactionId?: string;\r\n /** Process ID (for deadlock detection) */\r\n processId: number;\r\n /** Acquired timestamp (ISO string) */\r\n acquiredAt: string;\r\n /** Expiration timestamp (ISO string) */\r\n expiresAt: string;\r\n /** Last renewal timestamp (ISO string) */\r\n lastRenewedAt?: string;\r\n /** Correlation ID */\r\n correlationId: string;\r\n}\r\n\r\n/**\r\n * Lock statistics\r\n */\r\nexport interface LockStatistics {\r\n /** Total lock acquisitions */\r\n totalAcquisitions: number;\r\n /** Total lock releases */\r\n totalReleases: number;\r\n /** Currently held locks */\r\n currentlyHeld: number;\r\n /** Total renewals performed */\r\n totalRenewals: number;\r\n /** Average lock duration (ms) */\r\n averageDuration: number;\r\n /** Failed acquisition attempts */\r\n failedAcquisitions: number;\r\n}\r\n\r\n/**\r\n * Enhanced Redis-backed distributed lock manager\r\n */\r\nexport class DistributedLockManager {\r\n private redisClient: any;\r\n private activeLocks: Map<string, Lock> = new Map();\r\n private renewalTimers: Map<string, NodeJS.Timeout> = new Map();\r\n private statistics: LockStatistics = {\r\n totalAcquisitions: 0,\r\n totalReleases: 0,\r\n currentlyHeld: 0,\r\n totalRenewals: 0,\r\n averageDuration: 0,\r\n failedAcquisitions: 0,\r\n };\r\n private lockDurations: number[] = [];\r\n\r\n constructor(redisClient: any) {\r\n this.redisClient = redisClient;\r\n logger.info('Enhanced distributed lock manager initialized (v2)');\r\n }\r\n\r\n /**\r\n * Acquire lock on a resource with TTL enforcement and optional auto-renewal\r\n */\r\n async acquireLock(options: LockOptions): Promise<Lock> {\r\n // Validate TTL (REQUIRED in v2)\r\n if (options.ttl === undefined || options.ttl === null) {\r\n // Backward compatibility: use default 60s TTL\r\n options.ttl = 60000;\r\n }\r\n\r\n if (options.ttl <= 0) {\r\n throw new Error('TTL must be positive');\r\n }\r\n\r\n const opts = {\r\n timeout: options.timeout ?? 10000,\r\n transactionId: options.transactionId,\r\n retryInterval: options.retryInterval ?? 100,\r\n correlationId: options.correlationId ?? generateCorrelationId(),\r\n };\r\n\r\n const lockKey = this.buildLockKey(options.key);\r\n const lockId = randomUUID();\r\n const startTime = Date.now();\r\n\r\n logger.debug('Attempting lock acquisition', {\r\n lockKey,\r\n lockId,\r\n ttl: options.ttl,\r\n renewInterval: options.renewInterval,\r\n transactionId: opts.transactionId,\r\n timeout: opts.timeout,\r\n correlationId: opts.correlationId,\r\n });\r\n\r\n // Try to acquire lock with timeout\r\n while (Date.now() - startTime < opts.timeout) {\r\n const acquired = await this.tryAcquire(lockKey, lockId, options, opts);\r\n\r\n if (acquired) {\r\n const lock: Lock = {\r\n id: lockId,\r\n key: options.key,\r\n acquiredAt: new Date(),\r\n transactionId: opts.transactionId,\r\n ttl: options.ttl,\r\n renewInterval: options.renewInterval,\r\n correlationId: opts.correlationId,\r\n };\r\n\r\n this.activeLocks.set(lockId, lock);\r\n this.statistics.totalAcquisitions++;\r\n this.statistics.currentlyHeld++;\r\n\r\n // Start auto-renewal if configured\r\n if (options.renewInterval) {\r\n this.startAutoRenewal(lock);\r\n }\r\n\r\n logger.info('Lock acquired successfully', {\r\n lockId,\r\n lockKey,\r\n ttl: options.ttl,\r\n renewInterval: options.renewInterval,\r\n transactionId: opts.transactionId,\r\n duration: Date.now() - startTime,\r\n });\r\n\r\n return lock;\r\n }\r\n\r\n // Wait before retry\r\n await this.sleep(opts.retryInterval);\r\n }\r\n\r\n // Timeout reached\r\n const currentHolder = await this.getLockInfo(options.key);\r\n\r\n this.statistics.failedAcquisitions++;\r\n\r\n logger.warn('Lock acquisition timeout', {\r\n lockKey,\r\n lockId,\r\n timeout: opts.timeout,\r\n currentHolder,\r\n correlationId: opts.correlationId,\r\n });\r\n\r\n throw new LockAcquisitionError(\r\n `Failed to acquire lock on ${lockKey} within ${opts.timeout}ms`,\r\n lockKey,\r\n currentHolder\r\n );\r\n }\r\n\r\n /**\r\n * Try to acquire lock atomically (single attempt)\r\n */\r\n private async tryAcquire(\r\n lockKey: string,\r\n lockId: string,\r\n options: LockOptions,\r\n opts: { transactionId?: string; correlationId: string }\r\n ): Promise<boolean> {\r\n try {\r\n const now = new Date();\r\n const metadata: LockMetadata = {\r\n lockId,\r\n transactionId: opts.transactionId,\r\n processId: process.pid,\r\n acquiredAt: now.toISOString(),\r\n expiresAt: new Date(now.getTime() + options.ttl).toISOString(),\r\n correlationId: opts.correlationId,\r\n };\r\n\r\n // Use Redis SET NX (set if not exists) with TTL (PX = milliseconds)\r\n // This is atomic and prevents race conditions\r\n const result = await this.redisClient.set(\r\n lockKey,\r\n JSON.stringify(metadata),\r\n 'PX', // milliseconds\r\n options.ttl,\r\n 'NX' // only set if not exists\r\n );\r\n\r\n return result === 'OK';\r\n } catch (err) {\r\n logger.error('Error during lock acquisition attempt', err as Error, {\r\n lockKey,\r\n lockId,\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Renew lock TTL (extends expiration time)\r\n */\r\n async renewLock(lockId: string, ttl: number): Promise<void> {\r\n const lock = this.activeLocks.get(lockId);\r\n\r\n if (!lock) {\r\n throw new LockOwnershipError(\r\n `Cannot renew lock ${lockId}: lock not found in active locks`,\r\n lockId,\r\n 'unknown'\r\n );\r\n }\r\n\r\n const lockKey = this.buildLockKey(lock.key);\r\n\r\n try {\r\n // Get current lock metadata\r\n const metadata = await this.getLockInfo(lock.key);\r\n\r\n if (!metadata) {\r\n throw new Error('Lock has expired or been released');\r\n }\r\n\r\n if (metadata.lockId !== lockId) {\r\n throw new LockOwnershipError(\r\n `Cannot renew lock ${lockKey}: ownership mismatch`,\r\n lockId,\r\n metadata.lockId\r\n );\r\n }\r\n\r\n // Update expiration time\r\n const now = new Date();\r\n metadata.expiresAt = new Date(now.getTime() + ttl).toISOString();\r\n metadata.lastRenewedAt = now.toISOString();\r\n\r\n // Update Redis with new TTL\r\n await this.redisClient.set(\r\n lockKey,\r\n JSON.stringify(metadata),\r\n 'PX',\r\n ttl\r\n );\r\n\r\n // Update local lock object\r\n lock.ttl = ttl;\r\n\r\n this.statistics.totalRenewals++;\r\n\r\n logger.debug('Lock renewed successfully', {\r\n lockId,\r\n lockKey,\r\n newTtl: ttl,\r\n });\r\n } catch (err) {\r\n logger.error('Error renewing lock', err as Error, {\r\n lockId,\r\n lockKey,\r\n });\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Start auto-renewal for a lock\r\n */\r\n private startAutoRenewal(lock: Lock): void {\r\n if (!lock.renewInterval) {\r\n return;\r\n }\r\n\r\n const timer = setInterval(async () => {\r\n try {\r\n await this.renewLock(lock.id, lock.ttl);\r\n logger.debug('Auto-renewal completed', {\r\n lockId: lock.id,\r\n key: lock.key,\r\n });\r\n } catch (err) {\r\n logger.error('Auto-renewal failed', err as Error, {\r\n lockId: lock.id,\r\n key: lock.key,\r\n });\r\n // Stop renewal on failure\r\n this.stopAutoRenewal(lock.id);\r\n }\r\n }, lock.renewInterval);\r\n\r\n this.renewalTimers.set(lock.id, timer);\r\n\r\n logger.debug('Auto-renewal started', {\r\n lockId: lock.id,\r\n key: lock.key,\r\n interval: lock.renewInterval,\r\n });\r\n }\r\n\r\n /**\r\n * Stop auto-renewal for a lock\r\n */\r\n private stopAutoRenewal(lockId: string): void {\r\n const timer = this.renewalTimers.get(lockId);\r\n\r\n if (timer) {\r\n clearInterval(timer);\r\n this.renewalTimers.delete(lockId);\r\n\r\n logger.debug('Auto-renewal stopped', { lockId });\r\n }\r\n }\r\n\r\n /**\r\n * Release a lock manually\r\n */\r\n async releaseLock(lockId: string): Promise<void> {\r\n const lock = this.activeLocks.get(lockId);\r\n\r\n if (!lock) {\r\n logger.warn('Lock not found in active locks', { lockId });\r\n return;\r\n }\r\n\r\n const lockKey = this.buildLockKey(lock.key);\r\n\r\n logger.debug('Releasing lock', {\r\n lockId,\r\n lockKey,\r\n transactionId: lock.transactionId,\r\n });\r\n\r\n try {\r\n // Stop auto-renewal if active\r\n this.stopAutoRenewal(lockId);\r\n\r\n // Verify we own the lock before releasing\r\n const metadata = await this.getLockInfo(lock.key);\r\n\r\n if (!metadata) {\r\n logger.warn('Lock already released or expired', {\r\n lockId,\r\n lockKey,\r\n });\r\n this.activeLocks.delete(lockId);\r\n this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);\r\n return;\r\n }\r\n\r\n if (metadata.lockId !== lockId) {\r\n logger.error('Lock ownership mismatch', new Error('Lock ownership mismatch'), {\r\n expectedLockId: lockId,\r\n actualLockId: metadata.lockId,\r\n lockKey,\r\n });\r\n throw new LockOwnershipError(\r\n `Cannot release lock ${lockKey}: ownership mismatch`,\r\n lockId,\r\n metadata.lockId\r\n );\r\n }\r\n\r\n // Delete lock from Redis\r\n await this.redisClient.del(lockKey);\r\n\r\n // Track duration for statistics\r\n const duration = Date.now() - lock.acquiredAt.getTime();\r\n this.lockDurations.push(duration);\r\n\r\n // Keep only last 100 durations for average calculation\r\n if (this.lockDurations.length > 100) {\r\n this.lockDurations.shift();\r\n }\r\n\r\n // Update statistics\r\n this.statistics.totalReleases++;\r\n this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);\r\n this.statistics.averageDuration = this.calculateAverageDuration();\r\n\r\n this.activeLocks.delete(lockId);\r\n\r\n logger.info('Lock released successfully', {\r\n lockId,\r\n lockKey,\r\n duration,\r\n transactionId: lock.transactionId,\r\n });\r\n } catch (err) {\r\n logger.error('Error releasing lock', err as Error, {\r\n lockId,\r\n lockKey,\r\n });\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Check if a resource is currently locked\r\n */\r\n async isLocked(key: string): Promise<boolean> {\r\n const lockKey = this.buildLockKey(key);\r\n\r\n try {\r\n const exists = await this.redisClient.exists(lockKey);\r\n return exists === 1;\r\n } catch (err) {\r\n logger.error('Error checking lock status', err as Error, {\r\n lockKey,\r\n });\r\n return false; // Assume unlocked on error (fail-safe)\r\n }\r\n }\r\n\r\n /**\r\n * Get lock metadata for a resource\r\n */\r\n async getLockInfo(key: string): Promise<LockMetadata | null> {\r\n const lockKey = this.buildLockKey(key);\r\n\r\n try {\r\n const data = await this.redisClient.get(lockKey);\r\n\r\n if (!data) {\r\n return null;\r\n }\r\n\r\n const metadata: LockMetadata = JSON.parse(data);\r\n return metadata;\r\n } catch (err) {\r\n logger.error('Error retrieving lock info', err as Error, {\r\n lockKey,\r\n });\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Force release of a lock (admin operation - use with caution)\r\n */\r\n async forceRelease(key: string): Promise<void> {\r\n const lockKey = this.buildLockKey(key);\r\n\r\n logger.warn('Force releasing lock', {\r\n lockKey,\r\n });\r\n\r\n try {\r\n await this.redisClient.del(lockKey);\r\n\r\n // Clean up from active locks if present\r\n for (const [id, lock] of Array.from(this.activeLocks.entries())) {\r\n if (lock.key === key) {\r\n this.stopAutoRenewal(id);\r\n this.activeLocks.delete(id);\r\n this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);\r\n }\r\n }\r\n\r\n logger.info('Lock force released', {\r\n lockKey,\r\n });\r\n } catch (err) {\r\n logger.error('Error force releasing lock', err as Error, {\r\n lockKey,\r\n });\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Get all active locks managed by this instance\r\n */\r\n getActiveLocks(): Lock[] {\r\n return Array.from(this.activeLocks.values());\r\n }\r\n\r\n /**\r\n * Get lock statistics\r\n */\r\n getStatistics(): LockStatistics {\r\n return { ...this.statistics };\r\n }\r\n\r\n /**\r\n * Clean up expired locks from tracking\r\n */\r\n cleanupExpiredLocks(): number {\r\n const now = Date.now();\r\n let cleaned = 0;\r\n\r\n for (const [id, lock] of Array.from(this.activeLocks.entries())) {\r\n const expiresAt = lock.acquiredAt.getTime() + lock.ttl;\r\n\r\n if (now > expiresAt) {\r\n this.stopAutoRenewal(id);\r\n this.activeLocks.delete(id);\r\n this.statistics.currentlyHeld = Math.max(0, this.statistics.currentlyHeld - 1);\r\n cleaned++;\r\n }\r\n }\r\n\r\n if (cleaned > 0) {\r\n logger.debug('Cleaned up expired locks from tracking', { count: cleaned });\r\n }\r\n\r\n return cleaned;\r\n }\r\n\r\n /**\r\n * Release all active locks (cleanup on shutdown)\r\n */\r\n async releaseAll(): Promise<void> {\r\n logger.info('Releasing all active locks', { count: this.activeLocks.size });\r\n\r\n const releases = Array.from(this.activeLocks.values()).map(lock =>\r\n this.releaseLock(lock.id).catch(err => {\r\n logger.error('Error releasing lock during cleanup', err, {\r\n lockId: lock.id,\r\n });\r\n })\r\n );\r\n\r\n await Promise.all(releases);\r\n\r\n logger.info('All locks released');\r\n }\r\n\r\n /**\r\n * Build Redis key for lock resource\r\n */\r\n private buildLockKey(key: string): string {\r\n return `lock:${key}`;\r\n }\r\n\r\n /**\r\n * Calculate average lock duration\r\n */\r\n private calculateAverageDuration(): number {\r\n if (this.lockDurations.length === 0) {\r\n return 0;\r\n }\r\n\r\n const sum = this.lockDurations.reduce((acc, dur) => acc + dur, 0);\r\n return Math.round(sum / this.lockDurations.length);\r\n }\r\n\r\n /**\r\n * Sleep utility for retry intervals\r\n */\r\n private sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n }\r\n}\r\n\r\n/**\r\n * Lock acquisition error\r\n */\r\nexport class LockAcquisitionError extends Error {\r\n constructor(\r\n message: string,\r\n public lockKey: string,\r\n public currentHolder?: LockMetadata | null\r\n ) {\r\n super(message);\r\n this.name = 'LockAcquisitionError';\r\n }\r\n}\r\n\r\n/**\r\n * Lock ownership error\r\n */\r\nexport class LockOwnershipError extends Error {\r\n constructor(\r\n message: string,\r\n public expectedLockId: string,\r\n public actualLockId: string\r\n ) {\r\n super(message);\r\n this.name = 'LockOwnershipError';\r\n }\r\n}\r\n\r\n/**\r\n * Utility: Execute function with distributed lock\r\n */\r\nexport async function withLock<T>(\r\n lockManager: DistributedLockManager,\r\n key: string,\r\n fn: () => Promise<T>,\r\n options?: Omit<LockOptions, 'key'>\r\n): Promise<T> {\r\n const lock = await lockManager.acquireLock({\r\n key,\r\n ttl: options?.ttl ?? 60000,\r\n ...options,\r\n });\r\n\r\n try {\r\n const result = await fn();\r\n await lockManager.releaseLock(lock.id);\r\n return result;\r\n } catch (err) {\r\n await lockManager.releaseLock(lock.id);\r\n throw err;\r\n }\r\n}\r\n\r\n// Backward compatibility exports\r\nexport type { LockOptions, Lock, LockMetadata };\r\nexport { DistributedLockManager as DistributedLock };\r\n"],"names":["randomUUID","createLogger","generateCorrelationId","logger","DistributedLockManager","redisClient","activeLocks","Map","renewalTimers","statistics","totalAcquisitions","totalReleases","currentlyHeld","totalRenewals","averageDuration","failedAcquisitions","lockDurations","info","acquireLock","options","ttl","undefined","Error","opts","timeout","transactionId","retryInterval","correlationId","lockKey","buildLockKey","key","lockId","startTime","Date","now","debug","renewInterval","acquired","tryAcquire","lock","id","acquiredAt","set","startAutoRenewal","duration","sleep","currentHolder","getLockInfo","warn","LockAcquisitionError","metadata","processId","process","pid","toISOString","expiresAt","getTime","result","JSON","stringify","err","error","renewLock","get","LockOwnershipError","lastRenewedAt","newTtl","timer","setInterval","stopAutoRenewal","interval","clearInterval","delete","releaseLock","Math","max","expectedLockId","actualLockId","del","push","length","shift","calculateAverageDuration","isLocked","exists","data","parse","forceRelease","Array","from","entries","getActiveLocks","values","getStatistics","cleanupExpiredLocks","cleaned","count","releaseAll","size","releases","map","catch","Promise","all","sum","reduce","acc","dur","round","ms","resolve","setTimeout","message","name","withLock","lockManager","fn","DistributedLock"],"mappings":"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"}