claude-flow-novice 2.15.2 → 2.15.4

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 (533) 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 +16 -2
  34. package/.claude/commands/switch-api.md +31 -10
  35. package/.claude/hooks/cfn-BACKUP_USAGE.md +243 -243
  36. package/.claude/hooks/cfn-invoke-security-validation.sh +69 -69
  37. package/.claude/hooks/cfn-lint-sql-injection.sh +61 -0
  38. package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +109 -78
  39. package/.claude/hooks/cfn-post-edit.config.json +44 -44
  40. package/.claude/hooks/cfn-pre-edit-security-warning.sh +40 -0
  41. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  42. package/.claude/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  43. package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  44. package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  45. package/.claude/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
  46. package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  47. package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  48. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +184 -23
  49. package/.claude/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  50. package/.claude/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  51. package/.claude/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
  52. package/.claude/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  53. package/.claude/skills/cfn-redis-coordination/agent-log.sh +4 -0
  54. package/.claude/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  55. package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
  56. package/.claude/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  57. package/.claude/skills/cfn-redis-coordination/get-context.sh +145 -112
  58. package/.claude/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  59. package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +3 -0
  60. package/.claude/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  61. package/.claude/skills/cfn-redis-coordination/redis-functions.sh +33 -0
  62. package/.claude/skills/cfn-redis-coordination/report-completion.sh +24 -31
  63. package/.claude/skills/cfn-redis-coordination/store-context.sh +4 -0
  64. package/.claude/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  65. package/.claude/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  66. package/.claude/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  67. package/.claude/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
  68. package/.claude/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
  69. package/.claude/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  70. package/.claude/skills/cfn-transparency-middleware/test-integration.sh +161 -161
  71. package/.claude/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
  72. package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +107 -92
  73. package/.claude/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
  74. package/README.md +116 -475
  75. package/claude-assets/agents/cfn-dev-team/README.md +103 -0
  76. package/claude-assets/agents/cfn-dev-team/architecture/goal-planner.md +1 -1
  77. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +77 -15
  78. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +355 -6
  79. package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +82 -1
  80. package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +82 -1
  81. package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +77 -15
  82. package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +99 -12
  83. package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +1 -1
  84. package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +97 -0
  85. package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +20 -1
  86. package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +97 -0
  87. package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +110 -13
  88. package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +106 -15
  89. package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +115 -11
  90. package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +94 -7
  91. package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +87 -9
  92. package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +85 -7
  93. package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +160 -28
  94. package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +101 -19
  95. package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +108 -14
  96. package/claude-assets/agents/cfn-dev-team/reviewers/{reviewer.md → code-reviewer.md} +95 -8
  97. package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +107 -7
  98. package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +98 -7
  99. package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +95 -7
  100. package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +136 -9
  101. package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +108 -1
  102. package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +107 -13
  103. package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +737 -0
  104. package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
  105. package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +828 -0
  106. package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +106 -7
  107. package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +77 -0
  108. package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +684 -0
  109. package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +110 -1
  110. package/claude-assets/agents/cfn-dev-team/testers/tester.md +94 -7
  111. package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +1 -3
  112. package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +87 -13
  113. package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +103 -7
  114. package/claude-assets/agents/cfn-dev-team/utility/researcher.md +1 -3
  115. package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +94 -7
  116. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +46 -0
  117. package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
  118. package/claude-assets/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
  119. package/claude-assets/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
  120. package/claude-assets/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
  121. package/claude-assets/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
  122. package/claude-assets/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
  123. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
  124. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
  125. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
  126. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
  127. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
  128. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
  129. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
  130. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
  131. package/claude-assets/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
  132. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
  133. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
  134. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
  135. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
  136. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
  137. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
  138. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
  139. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
  140. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
  141. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
  142. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
  143. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
  144. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
  145. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
  146. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
  147. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
  148. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
  149. package/claude-assets/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
  150. package/claude-assets/commands/cfn-loop-cli.md +16 -2
  151. package/claude-assets/commands/switch-api.md +31 -10
  152. package/claude-assets/hooks/cfn-BACKUP_USAGE.md +243 -243
  153. package/claude-assets/hooks/cfn-invoke-security-validation.sh +69 -69
  154. package/claude-assets/hooks/cfn-lint-sql-injection.sh +61 -0
  155. package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +109 -78
  156. package/claude-assets/hooks/cfn-post-edit.config.json +44 -44
  157. package/claude-assets/hooks/cfn-post-execution/memory-cleanup.sh +19 -19
  158. package/claude-assets/hooks/cfn-pre-edit-security-warning.sh +40 -0
  159. package/claude-assets/hooks/cfn-pre-execution/memory-check.sh +19 -19
  160. package/claude-assets/hooks/detect-hardcoded-credentials.sh +212 -0
  161. package/claude-assets/skills/SKILL_TEMPLATE.md +774 -0
  162. package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +543 -572
  163. package/claude-assets/skills/agent-lifecycle/simple-audit.sh +57 -30
  164. package/claude-assets/skills/agent-template-generator/SKILL.md +440 -0
  165. package/claude-assets/skills/agent-template-generator/generate-agent.sh +405 -0
  166. package/claude-assets/skills/agent-validation-linter/SKILL.md +589 -0
  167. package/claude-assets/skills/agent-validation-linter/lint-agents.sh +271 -0
  168. package/claude-assets/skills/bootstrap/bash-fundamentals.md +786 -0
  169. package/claude-assets/skills/bootstrap/database-connection.md +464 -0
  170. package/claude-assets/skills/bootstrap/error-handling.md +580 -0
  171. package/claude-assets/skills/bootstrap/file-operations.md +699 -0
  172. package/claude-assets/skills/bootstrap/skill-loader.md +616 -0
  173. package/claude-assets/skills/bootstrap/sqlite-params.sh +287 -0
  174. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  175. package/claude-assets/skills/cfn-automatic-memory-persistence/persist-agent-output.sh +48 -48
  176. package/claude-assets/skills/cfn-automatic-memory-persistence/query-agent-history.sh +34 -34
  177. package/claude-assets/skills/cfn-automatic-memory-persistence/test-memory-persistence.sh +17 -16
  178. package/claude-assets/skills/cfn-deliverable-validation/confidence-calculator.sh +261 -261
  179. package/claude-assets/skills/cfn-deployment/SKILL.md +293 -0
  180. package/claude-assets/skills/cfn-deployment/execute.sh +21 -0
  181. package/claude-assets/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  182. package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  183. package/claude-assets/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  184. package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +38 -0
  185. package/claude-assets/skills/cfn-error-batching-strategy/lib/core-functions.sh +47 -47
  186. package/claude-assets/skills/cfn-expert-update/update-expert.sh +345 -345
  187. package/claude-assets/skills/cfn-file-operations/SKILL.md +290 -0
  188. package/claude-assets/skills/cfn-file-operations/execute.sh +129 -0
  189. package/claude-assets/skills/cfn-file-operations/lib/atomic-write.sh +294 -0
  190. package/claude-assets/skills/cfn-file-operations/lib/lock.sh +361 -0
  191. package/claude-assets/skills/cfn-file-operations/test.sh +369 -0
  192. package/claude-assets/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
  193. package/claude-assets/skills/cfn-intervention-detector/detect-intervention.sh +110 -110
  194. package/claude-assets/skills/cfn-intervention-orchestrator/execute-intervention.sh +58 -58
  195. package/claude-assets/skills/cfn-log-operations/SKILL.md +308 -0
  196. package/claude-assets/skills/cfn-log-operations/execute.sh +420 -0
  197. package/claude-assets/skills/cfn-log-operations/lib/rotate.sh +406 -0
  198. package/claude-assets/skills/cfn-log-operations/lib/search.sh +448 -0
  199. package/claude-assets/skills/cfn-log-operations/test.sh +394 -0
  200. package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  201. package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  202. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +184 -23
  203. package/claude-assets/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  204. package/claude-assets/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  205. package/claude-assets/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
  206. package/claude-assets/skills/cfn-loop2-output-processing/process-validator-output.sh +275 -275
  207. package/claude-assets/skills/cfn-memory-management/check-memory.sh +159 -159
  208. package/claude-assets/skills/cfn-memory-management/cleanup-memory.sh +196 -196
  209. package/claude-assets/skills/cfn-node-heap-sizer/task-mode-heap-limiter.sh +325 -325
  210. package/claude-assets/skills/cfn-parameterized-queries/SKILL.md +339 -0
  211. package/claude-assets/skills/cfn-playbook/query-playbook.sh +19 -15
  212. package/claude-assets/skills/cfn-playbook/update-playbook.sh +25 -14
  213. package/claude-assets/skills/cfn-playbook-auto-update/auto-update-playbook.sh +85 -85
  214. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +44 -0
  215. package/claude-assets/skills/cfn-promotion/SKILL.md +305 -0
  216. package/claude-assets/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  217. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh +4 -0
  218. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  219. package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
  220. package/claude-assets/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  221. package/claude-assets/skills/cfn-redis-coordination/get-context.sh +145 -112
  222. package/claude-assets/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  223. package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +3 -0
  224. package/claude-assets/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  225. package/claude-assets/skills/cfn-redis-coordination/redis-functions.sh +33 -0
  226. package/claude-assets/skills/cfn-redis-coordination/report-completion.sh +24 -31
  227. package/claude-assets/skills/cfn-redis-coordination/store-context.sh +4 -0
  228. package/claude-assets/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  229. package/claude-assets/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  230. package/claude-assets/skills/cfn-scope-simplifier/simplify-scope.sh +67 -67
  231. package/claude-assets/skills/cfn-skill-loader/SKILL.md +466 -0
  232. package/claude-assets/skills/cfn-skill-loader/execute.sh +344 -0
  233. package/claude-assets/skills/cfn-specialist-injection/recommend-specialist.sh +56 -56
  234. package/claude-assets/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  235. package/claude-assets/skills/cfn-standardized-error-handling/capture-agent-error.sh +86 -86
  236. package/claude-assets/skills/cfn-standardized-error-handling/test-error-handling.sh +165 -165
  237. package/claude-assets/skills/cfn-task-audit/get-audit-data.sh +42 -21
  238. package/claude-assets/skills/cfn-task-audit/store-task-audit.sh +17 -10
  239. package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +264 -264
  240. package/claude-assets/skills/cfn-task-decomposition/task-decomposer.sh +278 -278
  241. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh +17 -14
  242. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh.backup-1763392821 +55 -0
  243. package/claude-assets/skills/cfn-test-runner/store-benchmarks.sh +17 -19
  244. package/claude-assets/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
  245. package/claude-assets/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
  246. package/claude-assets/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  247. package/claude-assets/skills/cfn-transparency-middleware/test-integration.sh +161 -161
  248. package/claude-assets/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
  249. package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +107 -92
  250. package/claude-assets/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
  251. package/claude-assets/skills/cfn-utilities/SKILL.md +237 -0
  252. package/claude-assets/skills/cfn-utilities/execute.sh +32 -0
  253. package/claude-assets/skills/cfn-utilities/lib/errors.sh +56 -0
  254. package/claude-assets/skills/cfn-utilities/lib/file-ops.sh +164 -0
  255. package/claude-assets/skills/cfn-utilities/lib/logging.sh +77 -0
  256. package/claude-assets/skills/cfn-utilities/lib/retry.sh +127 -0
  257. package/claude-assets/skills/cfn-utilities/test.sh +317 -0
  258. package/claude-assets/skills/docker-build/SKILL.md +96 -203
  259. package/claude-assets/skills/docker-build/build.sh +73 -73
  260. package/claude-assets/skills/integration/agent-handoff.sh +492 -0
  261. package/claude-assets/skills/integration/file-operations.sh +414 -0
  262. package/claude-assets/skills/json-validation/SKILL.md +431 -0
  263. package/claude-assets/skills/json-validation/test-validate-success-criteria.sh +421 -0
  264. package/claude-assets/skills/json-validation/validate-success-criteria.sh +197 -0
  265. package/claude-assets/skills/redis-coordination/validate-parameters.sh +34 -0
  266. package/claude-assets/skills/workflow-codification/APPROVAL_WORKFLOW.md +806 -0
  267. package/claude-assets/skills/workflow-codification/COST_TRACKING.md +637 -0
  268. package/claude-assets/skills/workflow-codification/DEPLOY_QUICK_REFERENCE.md +106 -0
  269. package/claude-assets/skills/workflow-codification/EDGE_CASE_TRACKING.md +404 -0
  270. package/claude-assets/skills/workflow-codification/PROPAGATE_UPDATE_QUICK_REFERENCE.md +366 -0
  271. package/claude-assets/skills/workflow-codification/README_PHASE4.md +457 -0
  272. package/claude-assets/skills/workflow-codification/SKILL.md +110 -0
  273. package/claude-assets/skills/workflow-codification/analyze-patterns.sh +899 -0
  274. package/claude-assets/skills/workflow-codification/approval-workflow.sh +514 -0
  275. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh +481 -0
  276. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh.backup-1763392820 +512 -0
  277. package/claude-assets/skills/workflow-codification/generate-skill-update.sh +525 -0
  278. package/claude-assets/skills/workflow-codification/lib/security-utils.sh +204 -0
  279. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh +648 -0
  280. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh.backup-1763392820 +664 -0
  281. package/claude-assets/skills/workflow-codification/review-skill.sh +643 -0
  282. package/claude-assets/skills/workflow-codification/templates/email-notification.txt +114 -0
  283. package/claude-assets/skills/workflow-codification/templates/slack-notification.md +85 -0
  284. package/claude-assets/skills/workflow-codification/test-integration.sh +296 -0
  285. package/claude-assets/skills/workflow-codification/test-metadata-update.sh +350 -0
  286. package/claude-assets/skills/workflow-codification/track-cost-savings.sh +486 -0
  287. package/claude-assets/skills/workflow-codification/track-cost-savings.sh.backup-1763392821 +445 -0
  288. package/claude-assets/skills/workflow-codification/track-edge-case.sh +290 -0
  289. package/claude-assets/skills/workflow-codification/workflow-codification.db +0 -0
  290. package/dist/ace/ace-curator.js +10 -2
  291. package/dist/ace/ace-curator.js.map +1 -1
  292. package/dist/ace/ace-generator.js +4 -0
  293. package/dist/ace/ace-generator.js.map +1 -1
  294. package/dist/ace/ace-reflector.js +1 -1
  295. package/dist/ace/ace-reflector.js.map +1 -1
  296. package/dist/ace/context-injection.js +24 -2
  297. package/dist/ace/context-injection.js.map +1 -1
  298. package/dist/agents/agent-loader.js +146 -165
  299. package/dist/agents/agent-loader.js.map +1 -1
  300. package/dist/agents/task-agent-integration.js +1 -1
  301. package/dist/agents/task-agent-integration.js.map +1 -1
  302. package/dist/api/health-endpoints.js +390 -0
  303. package/dist/api/health-endpoints.js.map +1 -0
  304. package/dist/cli/agent-executor.js +4 -1
  305. package/dist/cli/agent-executor.js.map +1 -1
  306. package/dist/cli/agent-prompt-builder.js +89 -1
  307. package/dist/cli/agent-prompt-builder.js.map +1 -1
  308. package/dist/cli/agent-spawn.js +130 -37
  309. package/dist/cli/agent-spawn.js.map +1 -1
  310. package/dist/cli/config-manager.js +91 -109
  311. package/dist/cli/config-manager.js.map +1 -1
  312. package/dist/cli/skill-cache-validator.js +412 -0
  313. package/dist/cli/skill-cache-validator.js.map +1 -0
  314. package/dist/cli/skill-cli.js +991 -0
  315. package/dist/cli/skill-cli.js.map +1 -0
  316. package/dist/cli/skill-execution-logger.js +284 -0
  317. package/dist/cli/skill-execution-logger.js.map +1 -0
  318. package/dist/cli/skill-loader.js +457 -0
  319. package/dist/cli/skill-loader.js.map +1 -0
  320. package/dist/coordination/event-bus.js +2 -2
  321. package/dist/coordination/event-bus.js.map +1 -1
  322. package/dist/coordination/fleet-manager.js +1 -1
  323. package/dist/coordination/fleet-manager.js.map +1 -1
  324. package/dist/coordination/index.js +23 -9
  325. package/dist/coordination/index.js.map +1 -1
  326. package/dist/coordination/types/fleet-manager.types.js.map +1 -1
  327. package/dist/db/migration-manager.js +483 -0
  328. package/dist/db/migration-manager.js.map +1 -0
  329. package/dist/db/skills-query.js +535 -0
  330. package/dist/db/skills-query.js.map +1 -0
  331. package/dist/integration/DatabaseHandoff.js +507 -0
  332. package/dist/integration/DatabaseHandoff.js.map +1 -0
  333. package/dist/integration/StandardAdapter.js +291 -0
  334. package/dist/integration/StandardAdapter.js.map +1 -0
  335. package/dist/jobs/edge-case-analyzer.js +367 -0
  336. package/dist/jobs/edge-case-analyzer.js.map +1 -0
  337. package/dist/jobs/promotion-sla-enforcer.js +288 -0
  338. package/dist/jobs/promotion-sla-enforcer.js.map +1 -0
  339. package/dist/lib/agent-output-parser.js +518 -0
  340. package/dist/lib/agent-output-parser.js.map +1 -0
  341. package/dist/lib/agent-output-validator.js +950 -0
  342. package/dist/lib/agent-output-validator.js.map +1 -0
  343. package/dist/lib/agent-workspace.js +281 -0
  344. package/dist/lib/agent-workspace.js.map +1 -0
  345. package/dist/lib/artifact-registry.js +443 -0
  346. package/dist/lib/artifact-registry.js.map +1 -0
  347. package/dist/lib/atomic-file-writer.js +377 -0
  348. package/dist/lib/atomic-file-writer.js.map +1 -0
  349. package/dist/lib/backup-manager.js +779 -0
  350. package/dist/lib/backup-manager.js.map +1 -0
  351. package/dist/lib/checkpoint-manager.js +837 -0
  352. package/dist/lib/checkpoint-manager.js.map +1 -0
  353. package/dist/lib/circuit-breaker.js +340 -0
  354. package/dist/lib/circuit-breaker.js.map +1 -0
  355. package/dist/lib/completion-signal-handler.js +243 -0
  356. package/dist/lib/completion-signal-handler.js.map +1 -0
  357. package/dist/lib/config-manager.js +312 -0
  358. package/dist/lib/config-manager.js.map +1 -0
  359. package/dist/lib/config-migrator.js +386 -0
  360. package/dist/lib/config-migrator.js.map +1 -0
  361. package/dist/lib/config-validator.js +687 -0
  362. package/dist/lib/config-validator.js.map +1 -0
  363. package/dist/lib/correlation-cache.js +311 -0
  364. package/dist/lib/correlation-cache.js.map +1 -0
  365. package/dist/lib/correlation.js +263 -0
  366. package/dist/lib/correlation.js.map +1 -0
  367. package/dist/lib/database-service/connection-pool-manager.js +520 -0
  368. package/dist/lib/database-service/connection-pool-manager.js.map +1 -0
  369. package/dist/lib/database-service/correlation.js +329 -0
  370. package/dist/lib/database-service/correlation.js.map +1 -0
  371. package/dist/lib/database-service/errors.js +120 -0
  372. package/dist/lib/database-service/errors.js.map +1 -0
  373. package/dist/lib/database-service/index.js +168 -0
  374. package/dist/lib/database-service/index.js.map +1 -0
  375. package/dist/lib/database-service/postgres-adapter.js +526 -0
  376. package/dist/lib/database-service/postgres-adapter.js.map +1 -0
  377. package/dist/lib/database-service/redis-adapter.js +360 -0
  378. package/dist/lib/database-service/redis-adapter.js.map +1 -0
  379. package/dist/lib/database-service/sqlite-adapter.js +544 -0
  380. package/dist/lib/database-service/sqlite-adapter.js.map +1 -0
  381. package/dist/lib/database-service/transaction-manager.js +773 -0
  382. package/dist/lib/database-service/transaction-manager.js.map +1 -0
  383. package/dist/lib/database-service/types.js +23 -0
  384. package/dist/lib/database-service/types.js.map +1 -0
  385. package/dist/lib/deadlock-resolver.js +292 -0
  386. package/dist/lib/deadlock-resolver.js.map +1 -0
  387. package/dist/lib/distributed-lock.js +451 -0
  388. package/dist/lib/distributed-lock.js.map +1 -0
  389. package/dist/lib/edge-case-deduplicator.js +227 -0
  390. package/dist/lib/edge-case-deduplicator.js.map +1 -0
  391. package/dist/lib/encryption-manager.js +322 -0
  392. package/dist/lib/encryption-manager.js.map +1 -0
  393. package/dist/lib/error-aggregator.js +234 -0
  394. package/dist/lib/error-aggregator.js.map +1 -0
  395. package/dist/lib/errors.js +287 -0
  396. package/dist/lib/errors.js.map +1 -0
  397. package/dist/lib/file-lock-manager.js +578 -0
  398. package/dist/lib/file-lock-manager.js.map +1 -0
  399. package/dist/lib/file-operations.js +367 -0
  400. package/dist/lib/file-operations.js.map +1 -0
  401. package/dist/lib/idempotent-write.js +237 -0
  402. package/dist/lib/idempotent-write.js.map +1 -0
  403. package/dist/lib/integration-schema-validator.js +522 -0
  404. package/dist/lib/integration-schema-validator.js.map +1 -0
  405. package/dist/lib/lock-health-monitor.js +298 -0
  406. package/dist/lib/lock-health-monitor.js.map +1 -0
  407. package/dist/lib/log-shipper.js +422 -0
  408. package/dist/lib/log-shipper.js.map +1 -0
  409. package/dist/lib/logging.js +146 -0
  410. package/dist/lib/logging.js.map +1 -0
  411. package/dist/lib/message-deduplicator.js +439 -0
  412. package/dist/lib/message-deduplicator.js.map +1 -0
  413. package/dist/lib/multi-system-query.js +604 -0
  414. package/dist/lib/multi-system-query.js.map +1 -0
  415. package/dist/lib/orphan-detector.js +332 -0
  416. package/dist/lib/orphan-detector.js.map +1 -0
  417. package/dist/lib/password-generator.js +166 -0
  418. package/dist/lib/password-generator.js.map +1 -0
  419. package/dist/lib/path-validator.js +429 -0
  420. package/dist/lib/path-validator.js.map +1 -0
  421. package/dist/lib/query-translator.js +905 -0
  422. package/dist/lib/query-translator.js.map +1 -0
  423. package/dist/lib/queue-recovery.js +469 -0
  424. package/dist/lib/queue-recovery.js.map +1 -0
  425. package/dist/lib/redis-queue-manager.js +512 -0
  426. package/dist/lib/redis-queue-manager.js.map +1 -0
  427. package/dist/lib/reflection-archiver.js +272 -0
  428. package/dist/lib/reflection-archiver.js.map +1 -0
  429. package/dist/lib/retry-manager.js +453 -0
  430. package/dist/lib/retry-manager.js.map +1 -0
  431. package/dist/lib/retry.js +262 -0
  432. package/dist/lib/retry.js.map +1 -0
  433. package/dist/lib/schema-transform.js +695 -0
  434. package/dist/lib/schema-transform.js.map +1 -0
  435. package/dist/lib/schema-validator.js +491 -0
  436. package/dist/lib/schema-validator.js.map +1 -0
  437. package/dist/lib/skill-cache.js +297 -0
  438. package/dist/lib/skill-cache.js.map +1 -0
  439. package/dist/lib/skill-content-manager.js +337 -0
  440. package/dist/lib/skill-content-manager.js.map +1 -0
  441. package/dist/lib/skill-frontmatter-parser.js +237 -0
  442. package/dist/lib/skill-frontmatter-parser.js.map +1 -0
  443. package/dist/lib/skill-git-integration.js +275 -0
  444. package/dist/lib/skill-git-integration.js.map +1 -0
  445. package/dist/lib/skill-markdown-validator.js +396 -0
  446. package/dist/lib/skill-markdown-validator.js.map +1 -0
  447. package/dist/lib/skill-output-parser.js +312 -0
  448. package/dist/lib/skill-output-parser.js.map +1 -0
  449. package/dist/lib/unified-query-api.js +467 -0
  450. package/dist/lib/unified-query-api.js.map +1 -0
  451. package/dist/middleware/auth-middleware.js +350 -0
  452. package/dist/middleware/auth-middleware.js.map +1 -0
  453. package/dist/middleware/schema-validation.js +347 -0
  454. package/dist/middleware/schema-validation.js.map +1 -0
  455. package/dist/providers/anthropic-provider.js +1 -1
  456. package/dist/providers/anthropic-provider.js.map +1 -1
  457. package/dist/providers/provider-factory.js +2 -2
  458. package/dist/providers/provider-factory.js.map +1 -1
  459. package/dist/services/edge-case-analyzer.js +321 -0
  460. package/dist/services/edge-case-analyzer.js.map +1 -0
  461. package/dist/services/edge-case-deduplicator.js +266 -0
  462. package/dist/services/edge-case-deduplicator.js.map +1 -0
  463. package/dist/services/edge-case-detector.js +337 -0
  464. package/dist/services/edge-case-detector.js.map +1 -0
  465. package/dist/services/edge-case-tracker.js +547 -0
  466. package/dist/services/edge-case-tracker.js.map +1 -0
  467. package/dist/services/health-check-system.js +586 -0
  468. package/dist/services/health-check-system.js.map +1 -0
  469. package/dist/services/metrics-logger.js +412 -0
  470. package/dist/services/metrics-logger.js.map +1 -0
  471. package/dist/services/patch-generator.js +378 -0
  472. package/dist/services/patch-generator.js.map +1 -0
  473. package/dist/services/patch-validator.js +337 -0
  474. package/dist/services/patch-validator.js.map +1 -0
  475. package/dist/services/performance-monitor.js +811 -0
  476. package/dist/services/performance-monitor.js.map +1 -0
  477. package/dist/services/promotion-pipeline.js +918 -0
  478. package/dist/services/promotion-pipeline.js.map +1 -0
  479. package/dist/services/promotion-validator.js +394 -0
  480. package/dist/services/promotion-validator.js.map +1 -0
  481. package/dist/services/reflection-logger.js +388 -0
  482. package/dist/services/reflection-logger.js.map +1 -0
  483. package/dist/services/skill-deployment.js +472 -0
  484. package/dist/services/skill-deployment.js.map +1 -0
  485. package/dist/services/skill-loader.js +427 -0
  486. package/dist/services/skill-loader.js.map +1 -0
  487. package/dist/services/skill-promotion.js +372 -0
  488. package/dist/services/skill-promotion.js.map +1 -0
  489. package/dist/services/skill-validator.js +454 -0
  490. package/dist/services/skill-validator.js.map +1 -0
  491. package/dist/services/skill-versioning.js +244 -0
  492. package/dist/services/skill-versioning.js.map +1 -0
  493. package/dist/services/workspace-supervisor.js +597 -0
  494. package/dist/services/workspace-supervisor.js.map +1 -0
  495. package/dist/types/agent-output.js +44 -0
  496. package/dist/types/agent-output.js.map +1 -0
  497. package/dist/types/config.js +28 -0
  498. package/dist/types/config.js.map +1 -0
  499. package/dist/types/edge-case.js +45 -0
  500. package/dist/types/edge-case.js.map +1 -0
  501. package/package.json +201 -176
  502. package/readme/README.md +19 -4
  503. package/scripts/artifact-cleanup.sh +392 -0
  504. package/scripts/backup-cleanup.sh +627 -0
  505. package/scripts/cleanup-workspaces.sh +412 -0
  506. package/scripts/cleanup-yaml-configs.sh +141 -0
  507. package/scripts/deploy-approved-skills.sh +263 -0
  508. package/scripts/deploy-production.sh +355 -355
  509. package/scripts/docker-playwright-fix.sh +311 -311
  510. package/scripts/docker-rebuild-all-agents.sh +127 -127
  511. package/scripts/health-check.sh +447 -0
  512. package/scripts/log-aggregator.sh +554 -0
  513. package/scripts/log-monitor.sh +629 -0
  514. package/scripts/manage-agent-workspaces.sh +434 -0
  515. package/scripts/memory-leak-prevention.sh +305 -305
  516. package/scripts/migrate-artifacts.sh +563 -0
  517. package/scripts/migrate-schema.sh +533 -0
  518. package/scripts/migrate-yaml-to-json.sh +465 -0
  519. package/scripts/promote-staged-skills.sh +423 -0
  520. package/scripts/run-marketing-tests.sh +42 -42
  521. package/scripts/update_paths.sh +46 -46
  522. package/scripts/verify-no-secrets.sh +88 -35
  523. package/.claude/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  524. package/.claude/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  525. package/.claude/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  526. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  527. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
  528. package/README.md.backup_before_replace +0 -781
  529. package/claude-assets/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  530. package/claude-assets/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  531. package/claude-assets/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  532. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  533. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
@@ -0,0 +1,578 @@
1
+ /**
2
+ * File Lock Manager
3
+ *
4
+ * Centralized file locking system with queuing, renewal, and monitoring.
5
+ * Part of Task 4.2: Centralized File Locking & Atomic Operations
6
+ *
7
+ * Features:
8
+ * - Lock acquisition with configurable timeout (300s default)
9
+ * - Waiting queue for blocked processes
10
+ * - Lock renewal for long-running operations
11
+ * - Force release capability for stuck locks
12
+ * - Owner tracking (process ID + agent ID)
13
+ * - Stale lock detection and cleanup
14
+ * - Performance monitoring (<100ms acquisition target)
15
+ * - Automatic lock release on process exit
16
+ *
17
+ * Usage:
18
+ * const manager = new FileLockManager();
19
+ * const lock = await manager.acquireLock('/path/to/file.txt', {
20
+ * agentId: 'backend-dev-001',
21
+ * timeout: 30000
22
+ * });
23
+ * try {
24
+ * // Perform file operations
25
+ * } finally {
26
+ * await manager.releaseLock(lock.id);
27
+ * }
28
+ */ import * as fs from 'fs';
29
+ import * as path from 'path';
30
+ import { promisify } from 'util';
31
+ import { randomUUID } from 'crypto';
32
+ import { createLogger } from './logging.js';
33
+ import { createError, ErrorCode, createTimeoutError } from './errors.js';
34
+ const logger = createLogger('file-lock-manager');
35
+ const fsWriteFile = promisify(fs.writeFile);
36
+ const fsReadFile = promisify(fs.readFile);
37
+ const fsUnlink = promisify(fs.unlink);
38
+ const fsStat = promisify(fs.stat);
39
+ const fsMkdir = promisify(fs.mkdir);
40
+ const fsAccess = promisify(fs.access);
41
+ /**
42
+ * Lock directory (defaults to /tmp/cfn-locks/)
43
+ */ const LOCK_DIR = process.env.CFN_LOCK_DIR || '/tmp/cfn-locks';
44
+ /**
45
+ * File Lock Manager
46
+ *
47
+ * Manages file locks with queuing, renewal, and monitoring capabilities.
48
+ */ export class FileLockManager {
49
+ activeLocks = new Map();
50
+ lockQueues = new Map();
51
+ metrics = {
52
+ acquisitions: 0,
53
+ releases: 0,
54
+ activeLocks: 0,
55
+ timeouts: 0,
56
+ staleLocksRemoved: 0,
57
+ avgAcquisitionTimeMs: 0,
58
+ totalAcquisitionTimeMs: 0,
59
+ renewals: 0,
60
+ forceReleases: 0
61
+ };
62
+ cleanupInterval = null;
63
+ constructor(){
64
+ this.ensureLockDirectory();
65
+ this.setupCleanupInterval();
66
+ this.setupProcessExitHandlers();
67
+ }
68
+ /**
69
+ * Acquire a file lock
70
+ *
71
+ * @param filePath - Path to file to lock
72
+ * @param options - Lock acquisition options
73
+ * @returns Promise<FileLock> - Lock instance
74
+ * @throws LOCK_TIMEOUT if acquisition times out
75
+ */ async acquireLock(filePath, options = {}) {
76
+ const startTime = Date.now();
77
+ const opts = {
78
+ timeout: options.timeout || 300000,
79
+ retryInterval: options.retryInterval || 100,
80
+ agentId: options.agentId,
81
+ waitInQueue: options.waitInQueue !== false,
82
+ staleTimeout: options.staleTimeout || 300000
83
+ };
84
+ const absolutePath = path.resolve(filePath);
85
+ const lockPath = this.getLockPath(absolutePath);
86
+ const lockId = randomUUID();
87
+ logger.debug('Attempting lock acquisition', {
88
+ filePath: absolutePath,
89
+ lockId,
90
+ agentId: opts.agentId
91
+ });
92
+ // Try immediate acquisition
93
+ const immediateLock = await this.tryAcquireLock(absolutePath, lockPath, lockId, opts);
94
+ if (immediateLock) {
95
+ const acquisitionTime = Date.now() - startTime;
96
+ this.recordAcquisition(acquisitionTime);
97
+ logger.info('Lock acquired immediately', {
98
+ filePath: absolutePath,
99
+ lockId,
100
+ acquisitionTimeMs: acquisitionTime
101
+ });
102
+ return immediateLock;
103
+ }
104
+ // If immediate acquisition failed and queuing is enabled, wait in queue
105
+ if (opts.waitInQueue) {
106
+ return this.waitInQueue(absolutePath, lockPath, lockId, opts, startTime);
107
+ }
108
+ throw createTimeoutError(`acquire lock on ${absolutePath}`, 0);
109
+ }
110
+ /**
111
+ * Try to acquire lock immediately
112
+ */ async tryAcquireLock(filePath, lockPath, lockId, options) {
113
+ try {
114
+ // Check if lock file exists
115
+ const exists = await this.fileExists(lockPath);
116
+ if (exists) {
117
+ // Check if lock is stale
118
+ const isStale = await this.isLockStale(lockPath, options.staleTimeout);
119
+ if (isStale) {
120
+ logger.warn('Removing stale lock', {
121
+ lockPath
122
+ });
123
+ await this.forceReleaseLock(lockPath);
124
+ this.metrics.staleLocksRemoved++;
125
+ } else {
126
+ return null; // Lock is held by another process
127
+ }
128
+ }
129
+ // Create lock
130
+ const owner = {
131
+ pid: process.pid,
132
+ agentId: options.agentId,
133
+ hostname: require('os').hostname()
134
+ };
135
+ const expiresAt = new Date(Date.now() + options.timeout);
136
+ const metadata = {
137
+ lockId,
138
+ filePath,
139
+ owner,
140
+ acquiredAt: new Date().toISOString(),
141
+ expiresAt: expiresAt.toISOString(),
142
+ timeoutMs: options.timeout,
143
+ renewalCount: 0
144
+ };
145
+ // Write lock file atomically
146
+ await this.writeLockFile(lockPath, metadata);
147
+ // Verify we won the race
148
+ const verify = await this.readLockFile(lockPath);
149
+ if (verify.lockId !== lockId) {
150
+ logger.debug('Lost lock race', {
151
+ lockId,
152
+ winnerId: verify.lockId
153
+ });
154
+ return null;
155
+ }
156
+ // Create and store lock instance
157
+ const lock = {
158
+ id: lockId,
159
+ filePath,
160
+ lockPath,
161
+ owner,
162
+ acquiredAt: new Date(),
163
+ expiresAt,
164
+ timeoutMs: options.timeout,
165
+ renewalCount: 0
166
+ };
167
+ this.activeLocks.set(lockId, lock);
168
+ this.metrics.activeLocks++;
169
+ return lock;
170
+ } catch (error) {
171
+ logger.error('Error during lock acquisition attempt', error instanceof Error ? error : undefined, {
172
+ filePath,
173
+ lockId
174
+ });
175
+ return null;
176
+ }
177
+ }
178
+ /**
179
+ * Wait in queue for lock availability
180
+ */ async waitInQueue(filePath, lockPath, lockId, options, startTime) {
181
+ return new Promise((resolve, reject)=>{
182
+ const queueEntry = {
183
+ id: randomUUID(),
184
+ filePath,
185
+ agentId: options.agentId,
186
+ pid: process.pid,
187
+ queuedAt: new Date(),
188
+ resolve,
189
+ reject
190
+ };
191
+ // Set timeout
192
+ queueEntry.timeoutTimer = setTimeout(()=>{
193
+ this.removeFromQueue(filePath, queueEntry.id);
194
+ this.metrics.timeouts++;
195
+ reject(createTimeoutError(`acquire lock on ${filePath}`, options.timeout));
196
+ }, options.timeout);
197
+ // Add to queue
198
+ if (!this.lockQueues.has(filePath)) {
199
+ this.lockQueues.set(filePath, []);
200
+ }
201
+ this.lockQueues.get(filePath).push(queueEntry);
202
+ logger.debug('Added to lock queue', {
203
+ filePath,
204
+ queuePosition: this.lockQueues.get(filePath).length,
205
+ agentId: options.agentId
206
+ });
207
+ // Start polling for lock availability
208
+ this.pollForLock(filePath, lockPath, lockId, options, queueEntry, startTime);
209
+ });
210
+ }
211
+ /**
212
+ * Poll for lock availability
213
+ */ async pollForLock(filePath, lockPath, lockId, options, queueEntry, startTime) {
214
+ const pollInterval = setInterval(async ()=>{
215
+ try {
216
+ const lock = await this.tryAcquireLock(filePath, lockPath, lockId, options);
217
+ if (lock) {
218
+ clearInterval(pollInterval);
219
+ if (queueEntry.timeoutTimer) {
220
+ clearTimeout(queueEntry.timeoutTimer);
221
+ }
222
+ this.removeFromQueue(filePath, queueEntry.id);
223
+ const acquisitionTime = Date.now() - startTime;
224
+ this.recordAcquisition(acquisitionTime);
225
+ logger.info('Lock acquired from queue', {
226
+ filePath,
227
+ lockId,
228
+ waitTimeMs: acquisitionTime
229
+ });
230
+ queueEntry.resolve(lock);
231
+ }
232
+ } catch (error) {
233
+ clearInterval(pollInterval);
234
+ if (queueEntry.timeoutTimer) {
235
+ clearTimeout(queueEntry.timeoutTimer);
236
+ }
237
+ this.removeFromQueue(filePath, queueEntry.id);
238
+ queueEntry.reject(error instanceof Error ? error : new Error(`Lock acquisition failed: ${String(error)}`));
239
+ }
240
+ }, options.retryInterval);
241
+ }
242
+ /**
243
+ * Release a lock
244
+ *
245
+ * @param lockId - Lock ID to release
246
+ * @returns Promise that resolves when lock is released
247
+ */ async releaseLock(lockId) {
248
+ const lock = this.activeLocks.get(lockId);
249
+ if (!lock) {
250
+ logger.warn('Attempted to release non-existent lock', {
251
+ lockId
252
+ });
253
+ return;
254
+ }
255
+ try {
256
+ // Remove lock file
257
+ await fsUnlink(lock.lockPath);
258
+ // Remove from active locks
259
+ this.activeLocks.delete(lockId);
260
+ this.metrics.activeLocks--;
261
+ this.metrics.releases++;
262
+ logger.info('Lock released', {
263
+ lockId,
264
+ filePath: lock.filePath,
265
+ heldDurationMs: Date.now() - lock.acquiredAt.getTime()
266
+ });
267
+ } catch (error) {
268
+ logger.error('Error releasing lock', error instanceof Error ? error : undefined, {
269
+ lockId,
270
+ filePath: lock.filePath
271
+ });
272
+ throw createError(ErrorCode.LOCK_RELEASE_FAILED, `Failed to release lock ${lockId}`, {
273
+ lockId,
274
+ filePath: lock.filePath
275
+ }, error instanceof Error ? error : undefined);
276
+ }
277
+ }
278
+ /**
279
+ * Renew a lock (extend expiration time)
280
+ *
281
+ * @param lockId - Lock ID to renew
282
+ * @param extensionMs - Extension time in milliseconds
283
+ * @returns Promise that resolves when lock is renewed
284
+ */ async renewLock(lockId, extensionMs = 300000) {
285
+ const lock = this.activeLocks.get(lockId);
286
+ if (!lock) {
287
+ throw createError(ErrorCode.LOCK_NOT_FOUND, `Lock not found: ${lockId}`, {
288
+ lockId
289
+ });
290
+ }
291
+ try {
292
+ // Read current metadata
293
+ const metadata = await this.readLockFile(lock.lockPath);
294
+ // Verify ownership
295
+ if (metadata.lockId !== lockId) {
296
+ throw createError(ErrorCode.LOCK_OWNERSHIP_MISMATCH, 'Lock ownership mismatch during renewal', {
297
+ lockId,
298
+ actualOwnerId: metadata.lockId
299
+ });
300
+ }
301
+ // Update expiration
302
+ const newExpiresAt = new Date(Date.now() + extensionMs);
303
+ metadata.expiresAt = newExpiresAt.toISOString();
304
+ metadata.lastRenewedAt = new Date().toISOString();
305
+ metadata.renewalCount++;
306
+ // Write updated metadata
307
+ await this.writeLockFile(lock.lockPath, metadata);
308
+ // Update in-memory lock
309
+ lock.expiresAt = newExpiresAt;
310
+ lock.renewalCount = metadata.renewalCount;
311
+ this.metrics.renewals++;
312
+ logger.info('Lock renewed', {
313
+ lockId,
314
+ filePath: lock.filePath,
315
+ newExpiresAt: newExpiresAt.toISOString(),
316
+ renewalCount: metadata.renewalCount
317
+ });
318
+ } catch (error) {
319
+ logger.error('Error renewing lock', error instanceof Error ? error : undefined, {
320
+ lockId,
321
+ filePath: lock.filePath
322
+ });
323
+ throw error;
324
+ }
325
+ }
326
+ /**
327
+ * Force release a lock (for stuck locks)
328
+ *
329
+ * @param lockPath - Path to lock file
330
+ * @returns Promise that resolves when lock is force-released
331
+ */ async forceReleaseLock(lockPath) {
332
+ try {
333
+ const exists = await this.fileExists(lockPath);
334
+ if (exists) {
335
+ const metadata = await this.readLockFile(lockPath);
336
+ await fsUnlink(lockPath);
337
+ // Remove from active locks if present
338
+ if (this.activeLocks.has(metadata.lockId)) {
339
+ this.activeLocks.delete(metadata.lockId);
340
+ this.metrics.activeLocks--;
341
+ }
342
+ this.metrics.forceReleases++;
343
+ logger.warn('Lock force-released', {
344
+ lockPath,
345
+ lockId: metadata.lockId,
346
+ owner: metadata.owner
347
+ });
348
+ }
349
+ } catch (error) {
350
+ logger.error('Error force-releasing lock', error instanceof Error ? error : undefined, {
351
+ lockPath
352
+ });
353
+ throw error;
354
+ }
355
+ }
356
+ /**
357
+ * Get lock metrics
358
+ */ getMetrics() {
359
+ return {
360
+ ...this.metrics
361
+ };
362
+ }
363
+ /**
364
+ * Get queue status for a file
365
+ */ getQueueStatus(filePath) {
366
+ const absolutePath = path.resolve(filePath);
367
+ const queue = this.lockQueues.get(absolutePath);
368
+ if (!queue || queue.length === 0) {
369
+ return null;
370
+ }
371
+ return {
372
+ position: 1,
373
+ total: queue.length
374
+ };
375
+ }
376
+ /**
377
+ * Helper: Get lock file path
378
+ */ getLockPath(filePath) {
379
+ const hash = this.hashFilePath(filePath);
380
+ return path.join(LOCK_DIR, `${hash}.lock`);
381
+ }
382
+ /**
383
+ * Helper: Hash file path for lock file naming
384
+ */ hashFilePath(filePath) {
385
+ const crypto = require('crypto');
386
+ return crypto.createHash('sha256').update(filePath).digest('hex').substring(0, 16);
387
+ }
388
+ /**
389
+ * Helper: Check if file exists
390
+ */ async fileExists(filePath) {
391
+ try {
392
+ await fsAccess(filePath, fs.constants.F_OK);
393
+ return true;
394
+ } catch {
395
+ return false;
396
+ }
397
+ }
398
+ /**
399
+ * Helper: Check if lock is stale
400
+ */ async isLockStale(lockPath, staleTimeout) {
401
+ try {
402
+ const metadata = await this.readLockFile(lockPath);
403
+ const expiresAt = new Date(metadata.expiresAt);
404
+ const now = new Date();
405
+ return now > expiresAt;
406
+ } catch {
407
+ // If we can't read the lock file, consider it stale
408
+ return true;
409
+ }
410
+ }
411
+ /**
412
+ * Helper: Write lock file
413
+ */ async writeLockFile(lockPath, metadata) {
414
+ await fsWriteFile(lockPath, JSON.stringify(metadata, null, 2), 'utf8');
415
+ }
416
+ /**
417
+ * Helper: Read lock file
418
+ */ async readLockFile(lockPath) {
419
+ const content = await fsReadFile(lockPath, 'utf8');
420
+ return JSON.parse(content);
421
+ }
422
+ /**
423
+ * Helper: Remove entry from queue
424
+ */ removeFromQueue(filePath, entryId) {
425
+ const queue = this.lockQueues.get(filePath);
426
+ if (queue) {
427
+ const index = queue.findIndex((e)=>e.id === entryId);
428
+ if (index !== -1) {
429
+ queue.splice(index, 1);
430
+ }
431
+ if (queue.length === 0) {
432
+ this.lockQueues.delete(filePath);
433
+ }
434
+ }
435
+ }
436
+ /**
437
+ * Helper: Record acquisition metrics
438
+ */ recordAcquisition(acquisitionTimeMs) {
439
+ this.metrics.acquisitions++;
440
+ this.metrics.totalAcquisitionTimeMs += acquisitionTimeMs;
441
+ this.metrics.avgAcquisitionTimeMs = this.metrics.totalAcquisitionTimeMs / this.metrics.acquisitions;
442
+ }
443
+ /**
444
+ * Ensure lock directory exists
445
+ */ ensureLockDirectory() {
446
+ try {
447
+ if (!fs.existsSync(LOCK_DIR)) {
448
+ fs.mkdirSync(LOCK_DIR, {
449
+ recursive: true,
450
+ mode: 0o755
451
+ });
452
+ logger.info('Created lock directory', {
453
+ directory: LOCK_DIR
454
+ });
455
+ }
456
+ } catch (error) {
457
+ logger.error('Failed to create lock directory', error instanceof Error ? error : undefined, {
458
+ directory: LOCK_DIR
459
+ });
460
+ }
461
+ }
462
+ /**
463
+ * Setup periodic cleanup of stale locks
464
+ */ setupCleanupInterval() {
465
+ // Clean up stale locks every 60 seconds
466
+ this.cleanupInterval = setInterval(async ()=>{
467
+ await this.cleanupStaleLocks();
468
+ }, 60000);
469
+ }
470
+ /**
471
+ * Cleanup stale locks
472
+ */ async cleanupStaleLocks() {
473
+ try {
474
+ const files = fs.readdirSync(LOCK_DIR);
475
+ for (const file of files){
476
+ if (file.endsWith('.lock')) {
477
+ const lockPath = path.join(LOCK_DIR, file);
478
+ const isStale = await this.isLockStale(lockPath, 300000);
479
+ if (isStale) {
480
+ await this.forceReleaseLock(lockPath);
481
+ }
482
+ }
483
+ }
484
+ } catch (error) {
485
+ logger.error('Error during stale lock cleanup', error instanceof Error ? error : undefined);
486
+ }
487
+ }
488
+ /**
489
+ * Setup process exit handlers to release locks
490
+ */ setupProcessExitHandlers() {
491
+ const cleanup = async ()=>{
492
+ logger.info('Process exiting, releasing all locks', {
493
+ activeLocksCount: this.activeLocks.size
494
+ });
495
+ for (const [lockId, lock] of this.activeLocks.entries()){
496
+ try {
497
+ await this.releaseLock(lockId);
498
+ } catch (error) {
499
+ logger.error('Error releasing lock on exit', error instanceof Error ? error : undefined, {
500
+ lockId,
501
+ filePath: lock.filePath
502
+ });
503
+ }
504
+ }
505
+ if (this.cleanupInterval) {
506
+ clearInterval(this.cleanupInterval);
507
+ }
508
+ };
509
+ process.on('exit', ()=>{
510
+ // Synchronous cleanup only
511
+ for (const [, lock] of this.activeLocks.entries()){
512
+ try {
513
+ fs.unlinkSync(lock.lockPath);
514
+ } catch {}
515
+ }
516
+ });
517
+ process.on('SIGINT', async ()=>{
518
+ await cleanup();
519
+ process.exit(0);
520
+ });
521
+ process.on('SIGTERM', async ()=>{
522
+ await cleanup();
523
+ process.exit(0);
524
+ });
525
+ }
526
+ /**
527
+ * Shutdown the lock manager
528
+ */ async shutdown() {
529
+ logger.info('Shutting down file lock manager');
530
+ // Clear cleanup interval
531
+ if (this.cleanupInterval) {
532
+ clearInterval(this.cleanupInterval);
533
+ }
534
+ // Release all active locks
535
+ for (const lockId of this.activeLocks.keys()){
536
+ await this.releaseLock(lockId);
537
+ }
538
+ // Clear all queues
539
+ for (const [, queue] of this.lockQueues.entries()){
540
+ for (const entry of queue){
541
+ if (entry.timeoutTimer) {
542
+ clearTimeout(entry.timeoutTimer);
543
+ }
544
+ entry.reject(new Error('Lock manager shutting down'));
545
+ }
546
+ }
547
+ this.lockQueues.clear();
548
+ }
549
+ }
550
+ /**
551
+ * Singleton instance
552
+ */ let defaultManager = null;
553
+ /**
554
+ * Get the default file lock manager instance
555
+ */ export function getFileLockManager() {
556
+ if (!defaultManager) {
557
+ defaultManager = new FileLockManager();
558
+ }
559
+ return defaultManager;
560
+ }
561
+ /**
562
+ * Execute a function with file lock
563
+ *
564
+ * @param filePath - File to lock
565
+ * @param fn - Function to execute
566
+ * @param options - Lock options
567
+ * @returns Promise that resolves with function result
568
+ */ export async function withFileLock(filePath, fn, options = {}) {
569
+ const manager = getFileLockManager();
570
+ const lock = await manager.acquireLock(filePath, options);
571
+ try {
572
+ return await fn();
573
+ } finally{
574
+ await manager.releaseLock(lock.id);
575
+ }
576
+ }
577
+
578
+ //# sourceMappingURL=file-lock-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/file-lock-manager.ts"],"sourcesContent":["/**\r\n * File Lock Manager\r\n *\r\n * Centralized file locking system with queuing, renewal, and monitoring.\r\n * Part of Task 4.2: Centralized File Locking & Atomic Operations\r\n *\r\n * Features:\r\n * - Lock acquisition with configurable timeout (300s default)\r\n * - Waiting queue for blocked processes\r\n * - Lock renewal for long-running operations\r\n * - Force release capability for stuck locks\r\n * - Owner tracking (process ID + agent ID)\r\n * - Stale lock detection and cleanup\r\n * - Performance monitoring (<100ms acquisition target)\r\n * - Automatic lock release on process exit\r\n *\r\n * Usage:\r\n * const manager = new FileLockManager();\r\n * const lock = await manager.acquireLock('/path/to/file.txt', {\r\n * agentId: 'backend-dev-001',\r\n * timeout: 30000\r\n * });\r\n * try {\r\n * // Perform file operations\r\n * } finally {\r\n * await manager.releaseLock(lock.id);\r\n * }\r\n */\r\n\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport { promisify } from 'util';\r\nimport { randomUUID } from 'crypto';\r\nimport { createLogger } from './logging.js';\r\nimport { createError, ErrorCode, createTimeoutError } from './errors.js';\r\n\r\nconst logger = createLogger('file-lock-manager');\r\n\r\nconst fsWriteFile = promisify(fs.writeFile);\r\nconst fsReadFile = promisify(fs.readFile);\r\nconst fsUnlink = promisify(fs.unlink);\r\nconst fsStat = promisify(fs.stat);\r\nconst fsMkdir = promisify(fs.mkdir);\r\nconst fsAccess = promisify(fs.access);\r\n\r\n/**\r\n * Lock directory (defaults to /tmp/cfn-locks/)\r\n */\r\nconst LOCK_DIR = process.env.CFN_LOCK_DIR || '/tmp/cfn-locks';\r\n\r\n/**\r\n * Lock owner information\r\n */\r\nexport interface LockOwner {\r\n /** Process ID */\r\n pid: number;\r\n /** Agent ID (optional) */\r\n agentId?: string;\r\n /** Hostname (for distributed systems) */\r\n hostname: string;\r\n}\r\n\r\n/**\r\n * Lock metadata stored in lock file\r\n */\r\nexport interface LockMetadata {\r\n /** Unique lock ID */\r\n lockId: string;\r\n /** File path being locked */\r\n filePath: string;\r\n /** Lock owner information */\r\n owner: LockOwner;\r\n /** Acquisition timestamp */\r\n acquiredAt: string;\r\n /** Expiration timestamp */\r\n expiresAt: string;\r\n /** Timeout in milliseconds */\r\n timeoutMs: number;\r\n /** Last renewal timestamp */\r\n lastRenewedAt?: string;\r\n /** Number of renewals */\r\n renewalCount: number;\r\n}\r\n\r\n/**\r\n * Active lock instance\r\n */\r\nexport interface FileLock {\r\n /** Lock ID */\r\n id: string;\r\n /** File path */\r\n filePath: string;\r\n /** Lock file path */\r\n lockPath: string;\r\n /** Owner information */\r\n owner: LockOwner;\r\n /** Acquisition time */\r\n acquiredAt: Date;\r\n /** Expiration time */\r\n expiresAt: Date;\r\n /** Timeout in milliseconds */\r\n timeoutMs: number;\r\n /** Renewal count */\r\n renewalCount: number;\r\n}\r\n\r\n/**\r\n * Lock acquisition options\r\n */\r\nexport interface LockAcquisitionOptions {\r\n /** Timeout in milliseconds (default: 300000 = 5 minutes) */\r\n timeout?: number;\r\n /** Retry interval in milliseconds (default: 100) */\r\n retryInterval?: number;\r\n /** Agent ID for tracking */\r\n agentId?: string;\r\n /** Wait in queue if lock is held (default: true) */\r\n waitInQueue?: boolean;\r\n /** Stale lock detection timeout in milliseconds (default: 300000) */\r\n staleTimeout?: number;\r\n}\r\n\r\n/**\r\n * Queue entry for waiting processes\r\n */\r\ninterface QueueEntry {\r\n /** Entry ID */\r\n id: string;\r\n /** File path */\r\n filePath: string;\r\n /** Agent ID */\r\n agentId?: string;\r\n /** Process ID */\r\n pid: number;\r\n /** Queued timestamp */\r\n queuedAt: Date;\r\n /** Resolve function */\r\n resolve: (lock: FileLock) => void;\r\n /** Reject function */\r\n reject: (error: Error) => void;\r\n /** Timeout timer */\r\n timeoutTimer?: NodeJS.Timeout;\r\n}\r\n\r\n/**\r\n * Lock acquisition metrics\r\n */\r\nexport interface LockMetrics {\r\n /** Total lock acquisitions */\r\n acquisitions: number;\r\n /** Total lock releases */\r\n releases: number;\r\n /** Current active locks */\r\n activeLocks: number;\r\n /** Total lock timeouts */\r\n timeouts: number;\r\n /** Total stale locks cleaned */\r\n staleLocksRemoved: number;\r\n /** Average acquisition time (ms) */\r\n avgAcquisitionTimeMs: number;\r\n /** Total time spent acquiring locks (ms) */\r\n totalAcquisitionTimeMs: number;\r\n /** Lock renewals */\r\n renewals: number;\r\n /** Force releases */\r\n forceReleases: number;\r\n}\r\n\r\n/**\r\n * File Lock Manager\r\n *\r\n * Manages file locks with queuing, renewal, and monitoring capabilities.\r\n */\r\nexport class FileLockManager {\r\n private activeLocks: Map<string, FileLock> = new Map();\r\n private lockQueues: Map<string, QueueEntry[]> = new Map();\r\n private metrics: LockMetrics = {\r\n acquisitions: 0,\r\n releases: 0,\r\n activeLocks: 0,\r\n timeouts: 0,\r\n staleLocksRemoved: 0,\r\n avgAcquisitionTimeMs: 0,\r\n totalAcquisitionTimeMs: 0,\r\n renewals: 0,\r\n forceReleases: 0,\r\n };\r\n private cleanupInterval: NodeJS.Timeout | null = null;\r\n\r\n constructor() {\r\n this.ensureLockDirectory();\r\n this.setupCleanupInterval();\r\n this.setupProcessExitHandlers();\r\n }\r\n\r\n /**\r\n * Acquire a file lock\r\n *\r\n * @param filePath - Path to file to lock\r\n * @param options - Lock acquisition options\r\n * @returns Promise<FileLock> - Lock instance\r\n * @throws LOCK_TIMEOUT if acquisition times out\r\n */\r\n async acquireLock(\r\n filePath: string,\r\n options: LockAcquisitionOptions = {}\r\n ): Promise<FileLock> {\r\n const startTime = Date.now();\r\n const opts = {\r\n timeout: options.timeout || 300000, // 5 minutes default\r\n retryInterval: options.retryInterval || 100,\r\n agentId: options.agentId,\r\n waitInQueue: options.waitInQueue !== false,\r\n staleTimeout: options.staleTimeout || 300000,\r\n };\r\n\r\n const absolutePath = path.resolve(filePath);\r\n const lockPath = this.getLockPath(absolutePath);\r\n const lockId = randomUUID();\r\n\r\n logger.debug('Attempting lock acquisition', {\r\n filePath: absolutePath,\r\n lockId,\r\n agentId: opts.agentId,\r\n });\r\n\r\n // Try immediate acquisition\r\n const immediateLock = await this.tryAcquireLock(\r\n absolutePath,\r\n lockPath,\r\n lockId,\r\n opts\r\n );\r\n\r\n if (immediateLock) {\r\n const acquisitionTime = Date.now() - startTime;\r\n this.recordAcquisition(acquisitionTime);\r\n logger.info('Lock acquired immediately', {\r\n filePath: absolutePath,\r\n lockId,\r\n acquisitionTimeMs: acquisitionTime,\r\n });\r\n return immediateLock;\r\n }\r\n\r\n // If immediate acquisition failed and queuing is enabled, wait in queue\r\n if (opts.waitInQueue) {\r\n return this.waitInQueue(absolutePath, lockPath, lockId, opts, startTime);\r\n }\r\n\r\n throw createTimeoutError(`acquire lock on ${absolutePath}`, 0);\r\n }\r\n\r\n /**\r\n * Try to acquire lock immediately\r\n */\r\n private async tryAcquireLock(\r\n filePath: string,\r\n lockPath: string,\r\n lockId: string,\r\n options: Required<LockAcquisitionOptions>\r\n ): Promise<FileLock | null> {\r\n try {\r\n // Check if lock file exists\r\n const exists = await this.fileExists(lockPath);\r\n\r\n if (exists) {\r\n // Check if lock is stale\r\n const isStale = await this.isLockStale(lockPath, options.staleTimeout);\r\n\r\n if (isStale) {\r\n logger.warn('Removing stale lock', { lockPath });\r\n await this.forceReleaseLock(lockPath);\r\n this.metrics.staleLocksRemoved++;\r\n } else {\r\n return null; // Lock is held by another process\r\n }\r\n }\r\n\r\n // Create lock\r\n const owner: LockOwner = {\r\n pid: process.pid,\r\n agentId: options.agentId,\r\n hostname: require('os').hostname(),\r\n };\r\n\r\n const expiresAt = new Date(Date.now() + options.timeout);\r\n const metadata: LockMetadata = {\r\n lockId,\r\n filePath,\r\n owner,\r\n acquiredAt: new Date().toISOString(),\r\n expiresAt: expiresAt.toISOString(),\r\n timeoutMs: options.timeout,\r\n renewalCount: 0,\r\n };\r\n\r\n // Write lock file atomically\r\n await this.writeLockFile(lockPath, metadata);\r\n\r\n // Verify we won the race\r\n const verify = await this.readLockFile(lockPath);\r\n if (verify.lockId !== lockId) {\r\n logger.debug('Lost lock race', { lockId, winnerId: verify.lockId });\r\n return null;\r\n }\r\n\r\n // Create and store lock instance\r\n const lock: FileLock = {\r\n id: lockId,\r\n filePath,\r\n lockPath,\r\n owner,\r\n acquiredAt: new Date(),\r\n expiresAt,\r\n timeoutMs: options.timeout,\r\n renewalCount: 0,\r\n };\r\n\r\n this.activeLocks.set(lockId, lock);\r\n this.metrics.activeLocks++;\r\n\r\n return lock;\r\n } catch (error) {\r\n logger.error(\r\n 'Error during lock acquisition attempt',\r\n error instanceof Error ? error : undefined,\r\n { filePath, lockId }\r\n );\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Wait in queue for lock availability\r\n */\r\n private async waitInQueue(\r\n filePath: string,\r\n lockPath: string,\r\n lockId: string,\r\n options: Required<LockAcquisitionOptions>,\r\n startTime: number\r\n ): Promise<FileLock> {\r\n return new Promise((resolve, reject) => {\r\n const queueEntry: QueueEntry = {\r\n id: randomUUID(),\r\n filePath,\r\n agentId: options.agentId,\r\n pid: process.pid,\r\n queuedAt: new Date(),\r\n resolve,\r\n reject,\r\n };\r\n\r\n // Set timeout\r\n queueEntry.timeoutTimer = setTimeout(() => {\r\n this.removeFromQueue(filePath, queueEntry.id);\r\n this.metrics.timeouts++;\r\n reject(createTimeoutError(`acquire lock on ${filePath}`, options.timeout));\r\n }, options.timeout);\r\n\r\n // Add to queue\r\n if (!this.lockQueues.has(filePath)) {\r\n this.lockQueues.set(filePath, []);\r\n }\r\n this.lockQueues.get(filePath)!.push(queueEntry);\r\n\r\n logger.debug('Added to lock queue', {\r\n filePath,\r\n queuePosition: this.lockQueues.get(filePath)!.length,\r\n agentId: options.agentId,\r\n });\r\n\r\n // Start polling for lock availability\r\n this.pollForLock(filePath, lockPath, lockId, options, queueEntry, startTime);\r\n });\r\n }\r\n\r\n /**\r\n * Poll for lock availability\r\n */\r\n private async pollForLock(\r\n filePath: string,\r\n lockPath: string,\r\n lockId: string,\r\n options: Required<LockAcquisitionOptions>,\r\n queueEntry: QueueEntry,\r\n startTime: number\r\n ): Promise<void> {\r\n const pollInterval = setInterval(async () => {\r\n try {\r\n const lock = await this.tryAcquireLock(filePath, lockPath, lockId, options);\r\n\r\n if (lock) {\r\n clearInterval(pollInterval);\r\n if (queueEntry.timeoutTimer) {\r\n clearTimeout(queueEntry.timeoutTimer);\r\n }\r\n this.removeFromQueue(filePath, queueEntry.id);\r\n\r\n const acquisitionTime = Date.now() - startTime;\r\n this.recordAcquisition(acquisitionTime);\r\n\r\n logger.info('Lock acquired from queue', {\r\n filePath,\r\n lockId,\r\n waitTimeMs: acquisitionTime,\r\n });\r\n\r\n queueEntry.resolve(lock);\r\n }\r\n } catch (error) {\r\n clearInterval(pollInterval);\r\n if (queueEntry.timeoutTimer) {\r\n clearTimeout(queueEntry.timeoutTimer);\r\n }\r\n this.removeFromQueue(filePath, queueEntry.id);\r\n queueEntry.reject(\r\n error instanceof Error\r\n ? error\r\n : new Error(`Lock acquisition failed: ${String(error)}`)\r\n );\r\n }\r\n }, options.retryInterval);\r\n }\r\n\r\n /**\r\n * Release a lock\r\n *\r\n * @param lockId - Lock ID to release\r\n * @returns Promise that resolves when lock is released\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('Attempted to release non-existent lock', { lockId });\r\n return;\r\n }\r\n\r\n try {\r\n // Remove lock file\r\n await fsUnlink(lock.lockPath);\r\n\r\n // Remove from active locks\r\n this.activeLocks.delete(lockId);\r\n this.metrics.activeLocks--;\r\n this.metrics.releases++;\r\n\r\n logger.info('Lock released', {\r\n lockId,\r\n filePath: lock.filePath,\r\n heldDurationMs: Date.now() - lock.acquiredAt.getTime(),\r\n });\r\n } catch (error) {\r\n logger.error(\r\n 'Error releasing lock',\r\n error instanceof Error ? error : undefined,\r\n { lockId, filePath: lock.filePath }\r\n );\r\n throw createError(\r\n ErrorCode.LOCK_RELEASE_FAILED,\r\n `Failed to release lock ${lockId}`,\r\n { lockId, filePath: lock.filePath },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Renew a lock (extend expiration time)\r\n *\r\n * @param lockId - Lock ID to renew\r\n * @param extensionMs - Extension time in milliseconds\r\n * @returns Promise that resolves when lock is renewed\r\n */\r\n async renewLock(lockId: string, extensionMs: number = 300000): Promise<void> {\r\n const lock = this.activeLocks.get(lockId);\r\n\r\n if (!lock) {\r\n throw createError(ErrorCode.LOCK_NOT_FOUND, `Lock not found: ${lockId}`, {\r\n lockId,\r\n });\r\n }\r\n\r\n try {\r\n // Read current metadata\r\n const metadata = await this.readLockFile(lock.lockPath);\r\n\r\n // Verify ownership\r\n if (metadata.lockId !== lockId) {\r\n throw createError(\r\n ErrorCode.LOCK_OWNERSHIP_MISMATCH,\r\n 'Lock ownership mismatch during renewal',\r\n { lockId, actualOwnerId: metadata.lockId }\r\n );\r\n }\r\n\r\n // Update expiration\r\n const newExpiresAt = new Date(Date.now() + extensionMs);\r\n metadata.expiresAt = newExpiresAt.toISOString();\r\n metadata.lastRenewedAt = new Date().toISOString();\r\n metadata.renewalCount++;\r\n\r\n // Write updated metadata\r\n await this.writeLockFile(lock.lockPath, metadata);\r\n\r\n // Update in-memory lock\r\n lock.expiresAt = newExpiresAt;\r\n lock.renewalCount = metadata.renewalCount;\r\n\r\n this.metrics.renewals++;\r\n\r\n logger.info('Lock renewed', {\r\n lockId,\r\n filePath: lock.filePath,\r\n newExpiresAt: newExpiresAt.toISOString(),\r\n renewalCount: metadata.renewalCount,\r\n });\r\n } catch (error) {\r\n logger.error(\r\n 'Error renewing lock',\r\n error instanceof Error ? error : undefined,\r\n { lockId, filePath: lock.filePath }\r\n );\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Force release a lock (for stuck locks)\r\n *\r\n * @param lockPath - Path to lock file\r\n * @returns Promise that resolves when lock is force-released\r\n */\r\n async forceReleaseLock(lockPath: string): Promise<void> {\r\n try {\r\n const exists = await this.fileExists(lockPath);\r\n\r\n if (exists) {\r\n const metadata = await this.readLockFile(lockPath);\r\n await fsUnlink(lockPath);\r\n\r\n // Remove from active locks if present\r\n if (this.activeLocks.has(metadata.lockId)) {\r\n this.activeLocks.delete(metadata.lockId);\r\n this.metrics.activeLocks--;\r\n }\r\n\r\n this.metrics.forceReleases++;\r\n\r\n logger.warn('Lock force-released', {\r\n lockPath,\r\n lockId: metadata.lockId,\r\n owner: metadata.owner,\r\n });\r\n }\r\n } catch (error) {\r\n logger.error(\r\n 'Error force-releasing lock',\r\n error instanceof Error ? error : undefined,\r\n { lockPath }\r\n );\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Get lock metrics\r\n */\r\n getMetrics(): LockMetrics {\r\n return { ...this.metrics };\r\n }\r\n\r\n /**\r\n * Get queue status for a file\r\n */\r\n getQueueStatus(filePath: string): { position: number; total: number } | null {\r\n const absolutePath = path.resolve(filePath);\r\n const queue = this.lockQueues.get(absolutePath);\r\n\r\n if (!queue || queue.length === 0) {\r\n return null;\r\n }\r\n\r\n return {\r\n position: 1, // First in queue\r\n total: queue.length,\r\n };\r\n }\r\n\r\n /**\r\n * Helper: Get lock file path\r\n */\r\n private getLockPath(filePath: string): string {\r\n const hash = this.hashFilePath(filePath);\r\n return path.join(LOCK_DIR, `${hash}.lock`);\r\n }\r\n\r\n /**\r\n * Helper: Hash file path for lock file naming\r\n */\r\n private hashFilePath(filePath: string): string {\r\n const crypto = require('crypto');\r\n return crypto.createHash('sha256').update(filePath).digest('hex').substring(0, 16);\r\n }\r\n\r\n /**\r\n * Helper: Check if file exists\r\n */\r\n private async fileExists(filePath: string): Promise<boolean> {\r\n try {\r\n await fsAccess(filePath, fs.constants.F_OK);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Check if lock is stale\r\n */\r\n private async isLockStale(lockPath: string, staleTimeout: number): Promise<boolean> {\r\n try {\r\n const metadata = await this.readLockFile(lockPath);\r\n const expiresAt = new Date(metadata.expiresAt);\r\n const now = new Date();\r\n\r\n return now > expiresAt;\r\n } catch {\r\n // If we can't read the lock file, consider it stale\r\n return true;\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Write lock file\r\n */\r\n private async writeLockFile(lockPath: string, metadata: LockMetadata): Promise<void> {\r\n await fsWriteFile(lockPath, JSON.stringify(metadata, null, 2), 'utf8');\r\n }\r\n\r\n /**\r\n * Helper: Read lock file\r\n */\r\n private async readLockFile(lockPath: string): Promise<LockMetadata> {\r\n const content = await fsReadFile(lockPath, 'utf8');\r\n return JSON.parse(content) as LockMetadata;\r\n }\r\n\r\n /**\r\n * Helper: Remove entry from queue\r\n */\r\n private removeFromQueue(filePath: string, entryId: string): void {\r\n const queue = this.lockQueues.get(filePath);\r\n if (queue) {\r\n const index = queue.findIndex((e) => e.id === entryId);\r\n if (index !== -1) {\r\n queue.splice(index, 1);\r\n }\r\n if (queue.length === 0) {\r\n this.lockQueues.delete(filePath);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Helper: Record acquisition metrics\r\n */\r\n private recordAcquisition(acquisitionTimeMs: number): void {\r\n this.metrics.acquisitions++;\r\n this.metrics.totalAcquisitionTimeMs += acquisitionTimeMs;\r\n this.metrics.avgAcquisitionTimeMs =\r\n this.metrics.totalAcquisitionTimeMs / this.metrics.acquisitions;\r\n }\r\n\r\n /**\r\n * Ensure lock directory exists\r\n */\r\n private ensureLockDirectory(): void {\r\n try {\r\n if (!fs.existsSync(LOCK_DIR)) {\r\n fs.mkdirSync(LOCK_DIR, { recursive: true, mode: 0o755 });\r\n logger.info('Created lock directory', { directory: LOCK_DIR });\r\n }\r\n } catch (error) {\r\n logger.error(\r\n 'Failed to create lock directory',\r\n error instanceof Error ? error : undefined,\r\n { directory: LOCK_DIR }\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Setup periodic cleanup of stale locks\r\n */\r\n private setupCleanupInterval(): void {\r\n // Clean up stale locks every 60 seconds\r\n this.cleanupInterval = setInterval(async () => {\r\n await this.cleanupStaleLocks();\r\n }, 60000);\r\n }\r\n\r\n /**\r\n * Cleanup stale locks\r\n */\r\n private async cleanupStaleLocks(): Promise<void> {\r\n try {\r\n const files = fs.readdirSync(LOCK_DIR);\r\n\r\n for (const file of files) {\r\n if (file.endsWith('.lock')) {\r\n const lockPath = path.join(LOCK_DIR, file);\r\n const isStale = await this.isLockStale(lockPath, 300000);\r\n\r\n if (isStale) {\r\n await this.forceReleaseLock(lockPath);\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n logger.error(\r\n 'Error during stale lock cleanup',\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Setup process exit handlers to release locks\r\n */\r\n private setupProcessExitHandlers(): void {\r\n const cleanup = async () => {\r\n logger.info('Process exiting, releasing all locks', {\r\n activeLocksCount: this.activeLocks.size,\r\n });\r\n\r\n for (const [lockId, lock] of this.activeLocks.entries()) {\r\n try {\r\n await this.releaseLock(lockId);\r\n } catch (error) {\r\n logger.error(\r\n 'Error releasing lock on exit',\r\n error instanceof Error ? error : undefined,\r\n { lockId, filePath: lock.filePath }\r\n );\r\n }\r\n }\r\n\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n }\r\n };\r\n\r\n process.on('exit', () => {\r\n // Synchronous cleanup only\r\n for (const [, lock] of this.activeLocks.entries()) {\r\n try {\r\n fs.unlinkSync(lock.lockPath);\r\n } catch {}\r\n }\r\n });\r\n\r\n process.on('SIGINT', async () => {\r\n await cleanup();\r\n process.exit(0);\r\n });\r\n\r\n process.on('SIGTERM', async () => {\r\n await cleanup();\r\n process.exit(0);\r\n });\r\n }\r\n\r\n /**\r\n * Shutdown the lock manager\r\n */\r\n async shutdown(): Promise<void> {\r\n logger.info('Shutting down file lock manager');\r\n\r\n // Clear cleanup interval\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n }\r\n\r\n // Release all active locks\r\n for (const lockId of this.activeLocks.keys()) {\r\n await this.releaseLock(lockId);\r\n }\r\n\r\n // Clear all queues\r\n for (const [, queue] of this.lockQueues.entries()) {\r\n for (const entry of queue) {\r\n if (entry.timeoutTimer) {\r\n clearTimeout(entry.timeoutTimer);\r\n }\r\n entry.reject(new Error('Lock manager shutting down'));\r\n }\r\n }\r\n this.lockQueues.clear();\r\n }\r\n}\r\n\r\n/**\r\n * Singleton instance\r\n */\r\nlet defaultManager: FileLockManager | null = null;\r\n\r\n/**\r\n * Get the default file lock manager instance\r\n */\r\nexport function getFileLockManager(): FileLockManager {\r\n if (!defaultManager) {\r\n defaultManager = new FileLockManager();\r\n }\r\n return defaultManager;\r\n}\r\n\r\n/**\r\n * Execute a function with file lock\r\n *\r\n * @param filePath - File to lock\r\n * @param fn - Function to execute\r\n * @param options - Lock options\r\n * @returns Promise that resolves with function result\r\n */\r\nexport async function withFileLock<T>(\r\n filePath: string,\r\n fn: () => Promise<T>,\r\n options: LockAcquisitionOptions = {}\r\n): Promise<T> {\r\n const manager = getFileLockManager();\r\n const lock = await manager.acquireLock(filePath, options);\r\n\r\n try {\r\n return await fn();\r\n } finally {\r\n await manager.releaseLock(lock.id);\r\n }\r\n}\r\n"],"names":["fs","path","promisify","randomUUID","createLogger","createError","ErrorCode","createTimeoutError","logger","fsWriteFile","writeFile","fsReadFile","readFile","fsUnlink","unlink","fsStat","stat","fsMkdir","mkdir","fsAccess","access","LOCK_DIR","process","env","CFN_LOCK_DIR","FileLockManager","activeLocks","Map","lockQueues","metrics","acquisitions","releases","timeouts","staleLocksRemoved","avgAcquisitionTimeMs","totalAcquisitionTimeMs","renewals","forceReleases","cleanupInterval","ensureLockDirectory","setupCleanupInterval","setupProcessExitHandlers","acquireLock","filePath","options","startTime","Date","now","opts","timeout","retryInterval","agentId","waitInQueue","staleTimeout","absolutePath","resolve","lockPath","getLockPath","lockId","debug","immediateLock","tryAcquireLock","acquisitionTime","recordAcquisition","info","acquisitionTimeMs","exists","fileExists","isStale","isLockStale","warn","forceReleaseLock","owner","pid","hostname","require","expiresAt","metadata","acquiredAt","toISOString","timeoutMs","renewalCount","writeLockFile","verify","readLockFile","winnerId","lock","id","set","error","Error","undefined","Promise","reject","queueEntry","queuedAt","timeoutTimer","setTimeout","removeFromQueue","has","get","push","queuePosition","length","pollForLock","pollInterval","setInterval","clearInterval","clearTimeout","waitTimeMs","String","releaseLock","delete","heldDurationMs","getTime","LOCK_RELEASE_FAILED","renewLock","extensionMs","LOCK_NOT_FOUND","LOCK_OWNERSHIP_MISMATCH","actualOwnerId","newExpiresAt","lastRenewedAt","getMetrics","getQueueStatus","queue","position","total","hash","hashFilePath","join","crypto","createHash","update","digest","substring","constants","F_OK","JSON","stringify","content","parse","entryId","index","findIndex","e","splice","existsSync","mkdirSync","recursive","mode","directory","cleanupStaleLocks","files","readdirSync","file","endsWith","cleanup","activeLocksCount","size","entries","on","unlinkSync","exit","shutdown","keys","entry","clear","defaultManager","getFileLockManager","withFileLock","fn","manager"],"mappings":"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"}