claude-flow-novice 2.15.11 → 2.16.1

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 (741) hide show
  1. package/.claude/cfn-extras/agents/cfn-v3-coordinator.md +517 -0
  2. package/.claude/cfn-extras/skills/GOOGLE_SHEETS_SKILLS_README.md +1 -1
  3. package/.claude/cfn-extras/skills/google-sheets-api-coordinator/SKILL.md +1 -1
  4. package/.claude/cfn-extras/skills/google-sheets-formula-builder/SKILL.md +1 -1
  5. package/.claude/cfn-extras/skills/google-sheets-progress/SKILL.md +1 -1
  6. package/.claude/commands/CFN_LOOP_FRONTEND.md +1 -1
  7. package/.claude/commands/cfn-loop-cli.md +214 -442
  8. package/.claude/commands/cfn-loop-frontend.md +1 -1
  9. package/.claude/commands/cfn-loop-task.md +2 -2
  10. package/.claude/commands/cfn-loop-trigger.md +114 -0
  11. package/.claude/commands/deprecated/cfn-loop.md +2 -2
  12. package/.claude/hooks/cfn-invoke-post-edit-ts.sh +100 -0
  13. package/.claude/hooks/cfn-invoke-post-edit-ts.sh.backup +78 -0
  14. package/.claude/hooks/cfn-invoke-post-edit.sh +53 -5
  15. package/.claude/hooks/cfn-invoke-post-edit.sh.backup +87 -0
  16. package/.claude/hooks/cfn-invoke-pre-edit-ts.sh +116 -0
  17. package/.claude/hooks/cfn-invoke-pre-edit-ts.sh.backup +94 -0
  18. package/.claude/hooks/cfn-invoke-pre-edit.sh +22 -0
  19. package/.claude/hooks/cfn-invoke-pre-edit.sh.backup +88 -0
  20. package/.claude/hooks/cfn-post-edit.config.json +9 -2
  21. package/.claude/root-claude-distribute/CFN-CLAUDE.md +1 -1
  22. package/.claude/skills/cfn-agent-spawning/SKILL.md +48 -1
  23. package/.claude/skills/cfn-agent-spawning/SKILL.md.backup +135 -0
  24. package/.claude/skills/cfn-agent-spawning/TYPESCRIPT_MIGRATION.md +567 -0
  25. package/.claude/skills/cfn-agent-spawning/check-dependencies.sh +22 -0
  26. package/.claude/skills/{cfn-redis-coordination/check-dependencies.sh → cfn-agent-spawning/check-dependencies.sh.backup} +3 -5
  27. package/.claude/skills/cfn-agent-spawning/get-agent-provider-env.sh +22 -0
  28. package/.claude/skills/cfn-agent-spawning/get-agent-provider-env.sh.backup +127 -0
  29. package/.claude/skills/cfn-agent-spawning/parse-agent-provider.sh +22 -0
  30. package/.claude/skills/cfn-agent-spawning/parse-agent-provider.sh.backup +59 -0
  31. package/.claude/skills/cfn-agent-spawning/spawn-agent-wrapper.sh +63 -0
  32. package/.claude/skills/cfn-agent-spawning/spawn-agent-wrapper.sh.backup +41 -0
  33. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +26 -1
  34. package/.claude/skills/cfn-agent-spawning/spawn-templates.sh +22 -0
  35. package/.claude/skills/cfn-agent-spawning/spawn-templates.sh.backup +613 -0
  36. package/.claude/skills/cfn-agent-spawning/spawn-worker.sh +22 -0
  37. package/.claude/skills/cfn-agent-spawning/spawn-worker.sh.backup +176 -0
  38. package/.claude/skills/cfn-backlog-management/SKILL.md +1 -1
  39. package/.claude/skills/cfn-loop-orchestration/.backups/unknown/1763619700_33aff4a69b99159e4e849107ebc4d09f/metadata.json +8 -0
  40. package/.claude/skills/cfn-loop-orchestration/.backups/unknown/1763619700_33aff4a69b99159e4e849107ebc4d09f/original +271 -0
  41. package/.claude/skills/cfn-loop-orchestration/.backups/unknown/1763619700_33aff4a69b99159e4e849107ebc4d09f/revert.sh +7 -0
  42. package/.claude/skills/cfn-loop-orchestration/.backups/unknown/1763671642_06496e8c399a79db08167cc00ed4b31e/metadata.json +8 -0
  43. package/.claude/skills/cfn-loop-orchestration/.backups/unknown/1763671642_06496e8c399a79db08167cc00ed4b31e/original +325 -0
  44. package/.claude/skills/cfn-loop-orchestration/.backups/unknown/1763671642_06496e8c399a79db08167cc00ed4b31e/revert.sh +7 -0
  45. package/.claude/skills/cfn-loop-orchestration/CLI_IMPLEMENTATION_SUMMARY.md +330 -0
  46. package/.claude/skills/cfn-loop-orchestration/CONFIGURATION_IMPROVEMENTS.md +318 -0
  47. package/.claude/skills/cfn-loop-orchestration/CONTEXT_LOOKUP_MIGRATION.md +308 -0
  48. package/.claude/skills/cfn-loop-orchestration/CONTEXT_LOOKUP_QUICK_START.md +378 -0
  49. package/.claude/skills/cfn-loop-orchestration/E2E_VALIDATION_REPORT.md +262 -0
  50. package/.claude/skills/cfn-loop-orchestration/IMPLEMENTATION_SUMMARY.md +319 -519
  51. package/.claude/skills/cfn-loop-orchestration/NORTH_STAR_E2E_REPORT.md +299 -0
  52. package/.claude/skills/cfn-loop-orchestration/NORTH_STAR_EXECUTION_SUMMARY.md +403 -0
  53. package/.claude/skills/cfn-loop-orchestration/NORTH_STAR_INDEX.md +323 -0
  54. package/.claude/skills/cfn-loop-orchestration/SKILL.md +159 -48
  55. package/.claude/skills/cfn-loop-orchestration/SPAWN_AGENTS_IMPLEMENTATION.md +188 -0
  56. package/.claude/skills/cfn-loop-orchestration/TEST_COVERAGE_REPORT.md +335 -0
  57. package/.claude/skills/cfn-loop-orchestration/TEST_COVERAGE_SUMMARY.md +456 -0
  58. package/.claude/skills/cfn-loop-orchestration/TYPESCRIPT_INTEGRATION_REPORT.md +709 -0
  59. package/.claude/skills/cfn-loop-orchestration/TYPESCRIPT_INTEGRATION_SUMMARY.md +257 -0
  60. package/.claude/skills/cfn-loop-orchestration/VALIDATION_REPORT.md +572 -0
  61. package/.claude/skills/cfn-loop-orchestration/VALIDATION_SUMMARY.txt +196 -0
  62. package/.claude/skills/cfn-loop-orchestration/VALIDATOR_MODULE_GUIDE.md +526 -0
  63. package/.claude/skills/cfn-loop-orchestration/archive/legacy-bash/README.md +167 -0
  64. package/.claude/skills/cfn-loop-orchestration/archive/legacy-bash/orchestrate-enhanced.sh +548 -0
  65. package/.claude/skills/cfn-loop-orchestration/{orchestrate-wrapper.sh → archive/legacy-bash/orchestrate-wrapper.sh} +11 -1
  66. package/.claude/skills/cfn-loop-orchestration/archive/legacy-bash/orchestrate.sh +182 -0
  67. package/.claude/skills/cfn-loop-orchestration/e2e-validation-fixed.js +240 -0
  68. package/.claude/skills/cfn-loop-orchestration/e2e-validation.js +213 -0
  69. package/.claude/skills/cfn-loop-orchestration/package-lock.json +3 -0
  70. package/.claude/skills/cfn-loop-orchestration/package.json +4 -0
  71. package/.claude/skills/cfn-loop-orchestration/run-north-star-e2e.ts +210 -0
  72. package/.claude/skills/cfn-loop-orchestration/src/cli/orchestrator-cli.ts +396 -0
  73. package/.claude/skills/cfn-loop-orchestration/src/helpers/CONFIDENCE_AGGREGATOR.md +564 -0
  74. package/.claude/skills/cfn-loop-orchestration/src/helpers/CONFIDENCE_AGGREGATOR_QUICK_REF.md +241 -0
  75. package/.claude/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_IMPLEMENTATION.md +375 -0
  76. package/.claude/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_QUICK_REFERENCE.md +362 -0
  77. package/.claude/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_README.md +307 -0
  78. package/.claude/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_USAGE_GUIDE.md +508 -0
  79. package/.claude/skills/cfn-loop-orchestration/src/helpers/confidence-aggregator.ts +473 -0
  80. package/.claude/skills/cfn-loop-orchestration/src/helpers/consensus.ts +1 -1
  81. package/.claude/skills/cfn-loop-orchestration/src/helpers/context-injector.ts +349 -0
  82. package/.claude/skills/cfn-loop-orchestration/src/helpers/context-lookup.ts +486 -0
  83. package/.claude/skills/cfn-loop-orchestration/src/helpers/deliverable-verifier.ts +6 -2
  84. package/.claude/skills/cfn-loop-orchestration/src/helpers/gate-check.ts +1 -1
  85. package/.claude/skills/cfn-loop-orchestration/src/helpers/product-owner-decision.ts +316 -0
  86. package/.claude/skills/cfn-loop-orchestration/src/helpers/spawn-agents.ts +357 -0
  87. package/.claude/skills/cfn-loop-orchestration/src/helpers/validator.ts +276 -0
  88. package/.claude/skills/cfn-loop-orchestration/src/index.ts +2 -0
  89. package/.claude/skills/cfn-loop-orchestration/src/orchestrate.ts +743 -2
  90. package/.claude/skills/cfn-loop-orchestration/src/types.ts +56 -0
  91. package/.claude/skills/cfn-loop-orchestration/test-cli.sh +92 -0
  92. package/.claude/skills/cfn-loop-orchestration/test-typescript-integration.sh +442 -0
  93. package/.claude/skills/cfn-loop-orchestration/tests/agent-spawner.test.ts +124 -0
  94. package/.claude/skills/cfn-loop-orchestration/tests/confidence-aggregator.test.ts +604 -0
  95. package/.claude/skills/cfn-loop-orchestration/tests/context-injector.test.ts +561 -0
  96. package/.claude/skills/cfn-loop-orchestration/tests/context-lookup.test.ts +661 -0
  97. package/.claude/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +2 -2
  98. package/.claude/skills/cfn-loop-orchestration/tests/gate-check-edge-cases.test.ts +422 -0
  99. package/.claude/skills/cfn-loop-orchestration/tests/gate-checker.test.ts +276 -0
  100. package/.claude/skills/cfn-loop-orchestration/tests/logger.test.ts +291 -0
  101. package/.claude/skills/cfn-loop-orchestration/tests/north-star-e2e.test.ts +334 -0
  102. package/.claude/skills/cfn-loop-orchestration/tests/redis-coordinator.test.ts +321 -0
  103. package/.claude/skills/cfn-loop-orchestration/tests/spawn-agents.test.ts +284 -0
  104. package/.claude/skills/cfn-loop-orchestration/tests/validator.test.ts +643 -0
  105. package/.claude/skills/cfn-loop-validation/IMPLEMENTATION_SUMMARY.md +672 -0
  106. package/.claude/skills/cfn-loop-validation/INDEX.md +531 -0
  107. package/.claude/skills/cfn-loop-validation/README_TYPESCRIPT.md +454 -0
  108. package/.claude/skills/cfn-loop-validation/SKILL.md +48 -1
  109. package/.claude/skills/cfn-loop-validation/SKILL.md.backup +353 -0
  110. package/.claude/skills/cfn-loop-validation/SKILL_TYPESCRIPT.md +782 -0
  111. package/.claude/skills/cfn-loop-validation/VAPOR_DETECTION_EXAMPLES.md +598 -0
  112. package/.claude/skills/cfn-loop-validation/check-dependencies.sh +22 -0
  113. package/{claude-assets/skills/cfn-redis-coordination/check-dependencies.sh → .claude/skills/cfn-loop-validation/check-dependencies.sh.backup} +4 -5
  114. package/.claude/skills/cfn-loop-validation/detect-vapor.sh +59 -0
  115. package/.claude/skills/cfn-loop-validation/detect-vapor.sh.backup +37 -0
  116. package/.claude/skills/cfn-loop-validation/dist/.tsbuildinfo +1 -0
  117. package/.claude/skills/cfn-loop-validation/dist/cli/detect-vapor.d.ts +14 -0
  118. package/.claude/skills/cfn-loop-validation/dist/cli/detect-vapor.d.ts.map +1 -0
  119. package/.claude/skills/cfn-loop-validation/dist/cli/detect-vapor.js +185 -0
  120. package/.claude/skills/cfn-loop-validation/dist/cli/detect-vapor.js.map +1 -0
  121. package/.claude/skills/cfn-loop-validation/dist/cli/validate-deliverables.d.ts +14 -0
  122. package/.claude/skills/cfn-loop-validation/dist/cli/validate-deliverables.d.ts.map +1 -0
  123. package/.claude/skills/cfn-loop-validation/dist/cli/validate-deliverables.js +176 -0
  124. package/.claude/skills/cfn-loop-validation/dist/cli/validate-deliverables.js.map +1 -0
  125. package/.claude/skills/cfn-loop-validation/dist/cli/validate-gate.d.ts +19 -0
  126. package/.claude/skills/cfn-loop-validation/dist/cli/validate-gate.d.ts.map +1 -0
  127. package/.claude/skills/cfn-loop-validation/dist/cli/validate-gate.js +123 -0
  128. package/.claude/skills/cfn-loop-validation/dist/cli/validate-gate.js.map +1 -0
  129. package/.claude/skills/cfn-loop-validation/dist/types.d.ts +156 -0
  130. package/.claude/skills/cfn-loop-validation/dist/types.d.ts.map +1 -0
  131. package/.claude/skills/cfn-loop-validation/dist/types.js +66 -0
  132. package/.claude/skills/cfn-loop-validation/dist/types.js.map +1 -0
  133. package/.claude/skills/cfn-loop-validation/dist/validator.d.ts +85 -0
  134. package/.claude/skills/cfn-loop-validation/dist/validator.d.ts.map +1 -0
  135. package/.claude/skills/cfn-loop-validation/dist/validator.js +411 -0
  136. package/.claude/skills/cfn-loop-validation/dist/validator.js.map +1 -0
  137. package/.claude/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +22 -0
  138. package/.claude/skills/cfn-loop-validation/orchestrate-cfn-loop.sh.backup +252 -0
  139. package/.claude/skills/cfn-loop-validation/package.json +93 -0
  140. package/.claude/skills/cfn-loop-validation/src/cli/detect-vapor.ts +177 -0
  141. package/.claude/skills/cfn-loop-validation/src/cli/validate-deliverables.ts +161 -0
  142. package/.claude/skills/cfn-loop-validation/src/cli/validate-gate.ts +139 -0
  143. package/.claude/skills/cfn-loop-validation/src/types.ts +215 -0
  144. package/.claude/skills/cfn-loop-validation/src/validator.ts +503 -0
  145. package/.claude/skills/cfn-loop-validation/tests/validator.test.ts +537 -0
  146. package/.claude/skills/{cfn-redis-coordination → cfn-loop-validation}/tsconfig.json +34 -31
  147. package/.claude/skills/cfn-loop-validation/validate-deliverables.sh +59 -0
  148. package/.claude/skills/cfn-loop-validation/validate-deliverables.sh.backup +37 -0
  149. package/.claude/skills/cfn-loop-validation/validate-gate.sh +63 -0
  150. package/.claude/skills/cfn-loop-validation/validate-gate.sh.backup +41 -0
  151. package/.claude/skills/cfn-loop-validation/validate-iteration.sh +22 -0
  152. package/.claude/skills/cfn-loop-validation/validate-iteration.sh.backup +134 -0
  153. package/.claude/skills/cfn-product-owner-decision/SKILL.md +479 -147
  154. package/.claude/skills/cfn-product-owner-decision/TYPESCRIPT_IMPLEMENTATION.md +653 -0
  155. package/.claude/skills/cfn-product-owner-decision/{execute-decision.sh → archive/legacy-bash/execute-decision.sh} +24 -2
  156. package/.claude/skills/pre-edit-backup/SKILL.md +324 -0
  157. package/.claude/skills/pre-edit-backup/SKILL.md.backup +277 -0
  158. package/.claude/skills/pre-edit-backup/backup.sh +22 -0
  159. package/.claude/skills/pre-edit-backup/backup.sh.backup +107 -0
  160. package/claude-assets/agents/cfn-dev-team/analysts/root-cause-analyst.md +2 -2
  161. package/claude-assets/agents/cfn-dev-team/architecture/base-template-generator.md +1 -1
  162. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +3 -2
  163. package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +1 -0
  164. package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +2 -1
  165. package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +1 -0
  166. package/claude-assets/agents/cfn-dev-team/dev-ops/devops-engineer.md +11 -1
  167. package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +58 -35
  168. package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +2 -2
  169. package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +47 -37
  170. package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +18 -18
  171. package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +40 -58
  172. package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +19 -21
  173. package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +20 -29
  174. package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +15 -19
  175. package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +15 -10
  176. package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +16 -11
  177. package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +16 -26
  178. package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +18 -22
  179. package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +17 -21
  180. package/claude-assets/agents/cfn-dev-team/documentation/pseudocode.md +1 -1
  181. package/claude-assets/agents/cfn-dev-team/product-owners/accessibility-advocate-persona.md +1 -1
  182. package/claude-assets/agents/cfn-dev-team/product-owners/cto-agent.md +1 -1
  183. package/claude-assets/agents/cfn-dev-team/product-owners/power-user-persona.md +1 -1
  184. package/claude-assets/agents/cfn-dev-team/product-owners/product-owner.md +1 -5
  185. package/claude-assets/agents/cfn-dev-team/reviewers/code-reviewer.md +20 -51
  186. package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +22 -71
  187. package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +21 -64
  188. package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +22 -67
  189. package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +24 -68
  190. package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +8 -36
  191. package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +9 -38
  192. package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +17 -55
  193. package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
  194. package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +18 -56
  195. package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +9 -37
  196. package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +18 -56
  197. package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +18 -49
  198. package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +8 -37
  199. package/claude-assets/agents/cfn-dev-team/testers/tester.md +7 -27
  200. package/claude-assets/agents/cfn-dev-team/testers/unit/tdd-london-unit-swarm.md +1 -1
  201. package/claude-assets/agents/cfn-dev-team/utility/agent-builder.md +11 -0
  202. package/claude-assets/agents/cfn-dev-team/utility/analyst.md +13 -29
  203. package/claude-assets/agents/cfn-dev-team/utility/claude-code-expert.md +1 -1
  204. package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +13 -13
  205. package/claude-assets/agents/cfn-dev-team/utility/context-curator.md +7 -2
  206. package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +6 -11
  207. package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +121 -715
  208. package/claude-assets/agents/cfn-dev-team/utility/researcher.md +13 -22
  209. package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +147 -573
  210. package/claude-assets/agents/custom/cfn-docker-expert.md +103 -0
  211. package/claude-assets/agents/custom/cfn-loops-cli-expert.md +438 -0
  212. package/claude-assets/agents/custom/cfn-redis-operations.md +529 -529
  213. package/claude-assets/agents/custom/cfn-system-expert.md +1 -1
  214. package/claude-assets/agents/custom/trigger-dev-expert.md +369 -0
  215. package/claude-assets/agents/docker-team/micro-sprint-planner.md +747 -747
  216. package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
  217. package/claude-assets/cfn-extras/agents/cfn-v3-coordinator.md +517 -0
  218. package/claude-assets/cfn-extras/skills/GOOGLE_SHEETS_SKILLS_README.md +1 -1
  219. package/claude-assets/cfn-extras/skills/google-sheets-api-coordinator/SKILL.md +1 -1
  220. package/claude-assets/cfn-extras/skills/google-sheets-formula-builder/SKILL.md +1 -1
  221. package/claude-assets/cfn-extras/skills/google-sheets-progress/SKILL.md +1 -1
  222. package/claude-assets/commands/CFN_LOOP_FRONTEND.md +1 -1
  223. package/claude-assets/commands/cfn-loop-cli.md +214 -442
  224. package/claude-assets/commands/cfn-loop-frontend.md +1 -1
  225. package/claude-assets/commands/cfn-loop-task.md +2 -2
  226. package/claude-assets/commands/cfn-loop-trigger.md +114 -0
  227. package/claude-assets/commands/deprecated/cfn-loop.md +2 -2
  228. package/claude-assets/hooks/GIT-HOOKS-USAGE-EXAMPLES.md +116 -0
  229. package/claude-assets/hooks/README-GIT-HOOKS.md +443 -0
  230. package/claude-assets/hooks/SKILL.md +518 -0
  231. package/claude-assets/hooks/SKILL.md.backup +471 -0
  232. package/claude-assets/hooks/cfn-invoke-post-edit-ts.sh +100 -0
  233. package/claude-assets/hooks/cfn-invoke-post-edit-ts.sh.backup +78 -0
  234. package/claude-assets/hooks/cfn-invoke-post-edit.sh +53 -5
  235. package/claude-assets/hooks/cfn-invoke-post-edit.sh.backup +87 -0
  236. package/claude-assets/hooks/cfn-invoke-pre-edit-ts.sh +116 -0
  237. package/claude-assets/hooks/cfn-invoke-pre-edit-ts.sh.backup +94 -0
  238. package/claude-assets/hooks/cfn-invoke-pre-edit.sh +22 -0
  239. package/claude-assets/hooks/cfn-invoke-pre-edit.sh.backup +88 -0
  240. package/claude-assets/hooks/cfn-post-edit.config.json +9 -2
  241. package/claude-assets/hooks/install-git-hooks.sh +243 -0
  242. package/claude-assets/hooks/subagent-start.sh +98 -0
  243. package/claude-assets/hooks/subagent-stop.sh +93 -0
  244. package/claude-assets/hooks/validators/credential-scanner.sh +172 -0
  245. package/claude-assets/root-claude-distribute/CFN-CLAUDE.md +1 -1
  246. package/claude-assets/skills/cfn-agent-selection-with-fallback/DELIVERABLES.md +409 -0
  247. package/claude-assets/skills/cfn-agent-selection-with-fallback/IMPLEMENTATION_SUMMARY.md +396 -0
  248. package/claude-assets/skills/cfn-agent-selection-with-fallback/INTEGRATION_GUIDE.md +308 -0
  249. package/claude-assets/skills/cfn-agent-selection-with-fallback/QUICK_REFERENCE.md +239 -0
  250. package/claude-assets/skills/cfn-agent-selection-with-fallback/SKILL.md +107 -1
  251. package/claude-assets/skills/cfn-agent-selection-with-fallback/SKILL.md.backup +302 -0
  252. package/claude-assets/skills/cfn-agent-selection-with-fallback/TYPESCRIPT_MIGRATION.md +295 -0
  253. package/claude-assets/skills/cfn-agent-selection-with-fallback/dist/agent-selector.cjs +297 -0
  254. package/claude-assets/skills/cfn-agent-selection-with-fallback/dist/agent-selector.js +297 -0
  255. package/claude-assets/skills/cfn-agent-selection-with-fallback/dist/cli.cjs +96 -0
  256. package/claude-assets/skills/cfn-agent-selection-with-fallback/dist/cli.js +96 -0
  257. package/claude-assets/skills/cfn-agent-selection-with-fallback/select-agents-ts.sh +45 -0
  258. package/claude-assets/skills/cfn-agent-selection-with-fallback/select-agents-ts.sh.backup +23 -0
  259. package/claude-assets/skills/cfn-agent-selection-with-fallback/select-agents.sh +22 -0
  260. package/claude-assets/skills/cfn-agent-selection-with-fallback/select-agents.sh.backup +173 -0
  261. package/claude-assets/skills/cfn-agent-selection-with-fallback/src/agent-selector.test.ts +357 -0
  262. package/claude-assets/skills/cfn-agent-selection-with-fallback/src/agent-selector.ts +350 -0
  263. package/claude-assets/skills/cfn-agent-selection-with-fallback/src/cli.ts +74 -0
  264. package/claude-assets/skills/cfn-agent-selection-with-fallback/task-classifier.sh +22 -0
  265. package/claude-assets/skills/cfn-agent-selection-with-fallback/task-classifier.sh.backup +71 -0
  266. package/claude-assets/skills/cfn-agent-selection-with-fallback/tsconfig.json +18 -0
  267. package/claude-assets/skills/cfn-agent-spawning/SKILL.md +48 -1
  268. package/claude-assets/skills/cfn-agent-spawning/SKILL.md.backup +135 -0
  269. package/claude-assets/skills/cfn-agent-spawning/TYPESCRIPT_MIGRATION.md +567 -0
  270. package/claude-assets/skills/cfn-agent-spawning/check-dependencies.sh +22 -0
  271. package/claude-assets/skills/cfn-agent-spawning/check-dependencies.sh.backup +30 -0
  272. package/claude-assets/skills/cfn-agent-spawning/get-agent-provider-env.sh +22 -0
  273. package/claude-assets/skills/cfn-agent-spawning/get-agent-provider-env.sh.backup +127 -0
  274. package/claude-assets/skills/cfn-agent-spawning/parse-agent-provider.sh +22 -0
  275. package/claude-assets/skills/cfn-agent-spawning/parse-agent-provider.sh.backup +59 -0
  276. package/claude-assets/skills/cfn-agent-spawning/spawn-agent-wrapper.sh +63 -0
  277. package/claude-assets/skills/cfn-agent-spawning/spawn-agent-wrapper.sh.backup +41 -0
  278. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +26 -1
  279. package/claude-assets/skills/cfn-agent-spawning/spawn-templates.sh +22 -0
  280. package/claude-assets/skills/cfn-agent-spawning/spawn-templates.sh.backup +613 -0
  281. package/claude-assets/skills/cfn-agent-spawning/spawn-worker.sh +22 -0
  282. package/claude-assets/skills/cfn-agent-spawning/spawn-worker.sh.backup +176 -0
  283. package/claude-assets/skills/cfn-backlog-management/SKILL.md +1 -1
  284. package/claude-assets/skills/cfn-coordination/agent-completion.sh.backup +36 -0
  285. package/claude-assets/skills/cfn-coordination/coordination-signal.sh.backup +36 -0
  286. package/claude-assets/skills/cfn-coordination/coordination-wait.sh.backup +36 -0
  287. package/claude-assets/skills/cfn-dependency-ingestion/README.md +101 -0
  288. package/claude-assets/skills/cfn-dependency-ingestion/SKILL.md +397 -0
  289. package/claude-assets/skills/cfn-dependency-ingestion/build.sh +23 -0
  290. package/claude-assets/skills/cfn-dependency-ingestion/dist/ingest-dependencies.js +478 -0
  291. package/claude-assets/skills/cfn-dependency-ingestion/ingest-dependencies.sh +295 -0
  292. package/claude-assets/skills/cfn-dependency-ingestion/ingest.sh +237 -0
  293. package/claude-assets/skills/cfn-dependency-ingestion/manifests/cli-mode-dependencies.txt +73 -0
  294. package/claude-assets/skills/cfn-dependency-ingestion/manifests/shared-dependencies.txt +57 -0
  295. package/claude-assets/skills/cfn-dependency-ingestion/manifests/trigger-dev-dependencies.txt +82 -0
  296. package/claude-assets/skills/cfn-dependency-ingestion/manifests/trigger-mode-dependencies.txt +80 -0
  297. package/claude-assets/skills/cfn-dependency-ingestion/src/ingest-dependencies.ts +563 -0
  298. package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +14 -4
  299. package/claude-assets/skills/cfn-loop-orchestration/.backups/unknown/1763619700_33aff4a69b99159e4e849107ebc4d09f/metadata.json +8 -0
  300. package/claude-assets/skills/cfn-loop-orchestration/.backups/unknown/1763619700_33aff4a69b99159e4e849107ebc4d09f/original +271 -0
  301. package/claude-assets/skills/cfn-loop-orchestration/.backups/unknown/1763619700_33aff4a69b99159e4e849107ebc4d09f/revert.sh +7 -0
  302. package/claude-assets/skills/cfn-loop-orchestration/.backups/unknown/1763671642_06496e8c399a79db08167cc00ed4b31e/metadata.json +8 -0
  303. package/claude-assets/skills/cfn-loop-orchestration/.backups/unknown/1763671642_06496e8c399a79db08167cc00ed4b31e/original +325 -0
  304. package/claude-assets/skills/cfn-loop-orchestration/.backups/unknown/1763671642_06496e8c399a79db08167cc00ed4b31e/revert.sh +7 -0
  305. package/claude-assets/skills/cfn-loop-orchestration/CLI_IMPLEMENTATION_SUMMARY.md +330 -0
  306. package/claude-assets/skills/cfn-loop-orchestration/CONFIGURATION_IMPROVEMENTS.md +318 -0
  307. package/claude-assets/skills/cfn-loop-orchestration/CONTEXT_LOOKUP_MIGRATION.md +308 -0
  308. package/claude-assets/skills/cfn-loop-orchestration/CONTEXT_LOOKUP_QUICK_START.md +378 -0
  309. package/claude-assets/skills/cfn-loop-orchestration/E2E_VALIDATION_REPORT.md +262 -0
  310. package/claude-assets/skills/cfn-loop-orchestration/IMPLEMENTATION_SUMMARY.md +319 -519
  311. package/claude-assets/skills/cfn-loop-orchestration/NORTH_STAR_E2E_REPORT.md +299 -0
  312. package/claude-assets/skills/cfn-loop-orchestration/NORTH_STAR_EXECUTION_SUMMARY.md +403 -0
  313. package/claude-assets/skills/cfn-loop-orchestration/NORTH_STAR_INDEX.md +323 -0
  314. package/claude-assets/skills/cfn-loop-orchestration/SKILL.md +159 -48
  315. package/claude-assets/skills/cfn-loop-orchestration/SPAWN_AGENTS_IMPLEMENTATION.md +188 -0
  316. package/claude-assets/skills/cfn-loop-orchestration/TEST_COVERAGE_REPORT.md +335 -0
  317. package/claude-assets/skills/cfn-loop-orchestration/TEST_COVERAGE_SUMMARY.md +456 -0
  318. package/claude-assets/skills/cfn-loop-orchestration/TYPESCRIPT_INTEGRATION_REPORT.md +709 -0
  319. package/claude-assets/skills/cfn-loop-orchestration/TYPESCRIPT_INTEGRATION_SUMMARY.md +257 -0
  320. package/claude-assets/skills/cfn-loop-orchestration/VALIDATION_REPORT.md +572 -0
  321. package/claude-assets/skills/cfn-loop-orchestration/VALIDATION_SUMMARY.txt +196 -0
  322. package/claude-assets/skills/cfn-loop-orchestration/VALIDATOR_MODULE_GUIDE.md +526 -0
  323. package/claude-assets/skills/cfn-loop-orchestration/archive/legacy-bash/README.md +167 -0
  324. package/claude-assets/skills/cfn-loop-orchestration/archive/legacy-bash/orchestrate-enhanced.sh +548 -0
  325. package/claude-assets/skills/cfn-loop-orchestration/{orchestrate-wrapper.sh → archive/legacy-bash/orchestrate-wrapper.sh} +11 -1
  326. package/claude-assets/skills/cfn-loop-orchestration/archive/legacy-bash/orchestrate.sh +182 -0
  327. package/claude-assets/skills/cfn-loop-orchestration/e2e-validation-fixed.js +240 -0
  328. package/claude-assets/skills/cfn-loop-orchestration/e2e-validation.js +213 -0
  329. package/claude-assets/skills/cfn-loop-orchestration/package-lock.json +3 -0
  330. package/claude-assets/skills/cfn-loop-orchestration/package.json +4 -0
  331. package/claude-assets/skills/cfn-loop-orchestration/run-north-star-e2e.ts +210 -0
  332. package/claude-assets/skills/cfn-loop-orchestration/src/cli/orchestrator-cli.ts +396 -0
  333. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/CONFIDENCE_AGGREGATOR.md +564 -0
  334. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/CONFIDENCE_AGGREGATOR_QUICK_REF.md +241 -0
  335. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_IMPLEMENTATION.md +375 -0
  336. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_QUICK_REFERENCE.md +362 -0
  337. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_README.md +307 -0
  338. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/CONTEXT_INJECTOR_USAGE_GUIDE.md +508 -0
  339. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/confidence-aggregator.ts +473 -0
  340. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/consensus.ts +1 -1
  341. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/context-injector.ts +349 -0
  342. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/context-lookup.ts +486 -0
  343. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/deliverable-verifier.ts +6 -2
  344. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/gate-check.ts +1 -1
  345. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/product-owner-decision.ts +316 -0
  346. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/spawn-agents.ts +357 -0
  347. package/claude-assets/skills/cfn-loop-orchestration/src/helpers/validator.ts +276 -0
  348. package/claude-assets/skills/cfn-loop-orchestration/src/index.ts +2 -0
  349. package/claude-assets/skills/cfn-loop-orchestration/src/orchestrate.ts +743 -2
  350. package/claude-assets/skills/cfn-loop-orchestration/src/types.ts +56 -0
  351. package/claude-assets/skills/cfn-loop-orchestration/test-cli.sh +92 -0
  352. package/claude-assets/skills/cfn-loop-orchestration/test-typescript-integration.sh +442 -0
  353. package/claude-assets/skills/cfn-loop-orchestration/tests/agent-spawner.test.ts +124 -0
  354. package/claude-assets/skills/cfn-loop-orchestration/tests/confidence-aggregator.test.ts +604 -0
  355. package/claude-assets/skills/cfn-loop-orchestration/tests/context-injector.test.ts +561 -0
  356. package/claude-assets/skills/cfn-loop-orchestration/tests/context-lookup.test.ts +661 -0
  357. package/claude-assets/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +2 -2
  358. package/claude-assets/skills/cfn-loop-orchestration/tests/gate-check-edge-cases.test.ts +422 -0
  359. package/claude-assets/skills/cfn-loop-orchestration/tests/gate-checker.test.ts +276 -0
  360. package/claude-assets/skills/cfn-loop-orchestration/tests/logger.test.ts +291 -0
  361. package/claude-assets/skills/cfn-loop-orchestration/tests/north-star-e2e.test.ts +334 -0
  362. package/claude-assets/skills/cfn-loop-orchestration/tests/redis-coordinator.test.ts +321 -0
  363. package/claude-assets/skills/cfn-loop-orchestration/tests/spawn-agents.test.ts +284 -0
  364. package/claude-assets/skills/cfn-loop-orchestration/tests/validator.test.ts +643 -0
  365. package/claude-assets/skills/cfn-loop-output-processing/.eslintrc.json +33 -0
  366. package/claude-assets/skills/cfn-loop-output-processing/DELIVERY_SUMMARY.txt +462 -0
  367. package/claude-assets/skills/cfn-loop-output-processing/DEPRECATION_NOTICE.md +183 -0
  368. package/claude-assets/skills/cfn-loop-output-processing/EXAMPLES.md +609 -0
  369. package/claude-assets/skills/cfn-loop-output-processing/IMPLEMENTATION_SUMMARY.md +418 -0
  370. package/claude-assets/skills/cfn-loop-output-processing/INDEX.md +531 -0
  371. package/claude-assets/skills/cfn-loop-output-processing/MIGRATION.md +362 -0
  372. package/claude-assets/skills/cfn-loop-output-processing/README.md +114 -0
  373. package/claude-assets/skills/cfn-loop-output-processing/SKILL.md +633 -0
  374. package/{.claude/skills/cfn-docker-redis-coordination → claude-assets/skills/cfn-loop-output-processing}/jest.config.js +7 -15
  375. package/claude-assets/skills/cfn-loop-output-processing/package.json +50 -0
  376. package/claude-assets/skills/cfn-loop-output-processing/src/cli/process-loop2.ts +195 -0
  377. package/claude-assets/skills/cfn-loop-output-processing/src/cli/process-loop3.ts +157 -0
  378. package/claude-assets/skills/cfn-loop-output-processing/src/output-processor.ts +632 -0
  379. package/claude-assets/skills/cfn-loop-output-processing/tests/output-processor.test.ts +617 -0
  380. package/claude-assets/skills/{cfn-docker-redis-coordination → cfn-loop-output-processing}/tsconfig.json +16 -7
  381. package/claude-assets/skills/cfn-loop-validation/IMPLEMENTATION_SUMMARY.md +672 -0
  382. package/claude-assets/skills/cfn-loop-validation/INDEX.md +531 -0
  383. package/claude-assets/skills/cfn-loop-validation/README_TYPESCRIPT.md +454 -0
  384. package/claude-assets/skills/cfn-loop-validation/SKILL.md +48 -1
  385. package/claude-assets/skills/cfn-loop-validation/SKILL.md.backup +353 -0
  386. package/claude-assets/skills/cfn-loop-validation/SKILL_TYPESCRIPT.md +782 -0
  387. package/claude-assets/skills/cfn-loop-validation/VAPOR_DETECTION_EXAMPLES.md +598 -0
  388. package/claude-assets/skills/cfn-loop-validation/check-dependencies.sh +22 -0
  389. package/claude-assets/skills/cfn-loop-validation/check-dependencies.sh.backup +31 -0
  390. package/claude-assets/skills/cfn-loop-validation/detect-vapor.sh +59 -0
  391. package/claude-assets/skills/cfn-loop-validation/detect-vapor.sh.backup +37 -0
  392. package/claude-assets/skills/cfn-loop-validation/dist/.tsbuildinfo +1 -0
  393. package/claude-assets/skills/cfn-loop-validation/dist/cli/detect-vapor.d.ts +14 -0
  394. package/claude-assets/skills/cfn-loop-validation/dist/cli/detect-vapor.d.ts.map +1 -0
  395. package/claude-assets/skills/cfn-loop-validation/dist/cli/detect-vapor.js +185 -0
  396. package/claude-assets/skills/cfn-loop-validation/dist/cli/detect-vapor.js.map +1 -0
  397. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-deliverables.d.ts +14 -0
  398. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-deliverables.d.ts.map +1 -0
  399. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-deliverables.js +176 -0
  400. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-deliverables.js.map +1 -0
  401. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-gate.d.ts +19 -0
  402. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-gate.d.ts.map +1 -0
  403. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-gate.js +123 -0
  404. package/claude-assets/skills/cfn-loop-validation/dist/cli/validate-gate.js.map +1 -0
  405. package/claude-assets/skills/cfn-loop-validation/dist/types.d.ts +156 -0
  406. package/claude-assets/skills/cfn-loop-validation/dist/types.d.ts.map +1 -0
  407. package/claude-assets/skills/cfn-loop-validation/dist/types.js +66 -0
  408. package/claude-assets/skills/cfn-loop-validation/dist/types.js.map +1 -0
  409. package/claude-assets/skills/cfn-loop-validation/dist/validator.d.ts +85 -0
  410. package/claude-assets/skills/cfn-loop-validation/dist/validator.d.ts.map +1 -0
  411. package/claude-assets/skills/cfn-loop-validation/dist/validator.js +411 -0
  412. package/claude-assets/skills/cfn-loop-validation/dist/validator.js.map +1 -0
  413. package/claude-assets/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +22 -0
  414. package/claude-assets/skills/cfn-loop-validation/orchestrate-cfn-loop.sh.backup +252 -0
  415. package/claude-assets/skills/cfn-loop-validation/package.json +93 -0
  416. package/claude-assets/skills/cfn-loop-validation/src/cli/detect-vapor.ts +177 -0
  417. package/claude-assets/skills/cfn-loop-validation/src/cli/validate-deliverables.ts +161 -0
  418. package/claude-assets/skills/cfn-loop-validation/src/cli/validate-gate.ts +139 -0
  419. package/claude-assets/skills/cfn-loop-validation/src/types.ts +215 -0
  420. package/claude-assets/skills/cfn-loop-validation/src/validator.ts +503 -0
  421. package/claude-assets/skills/cfn-loop-validation/tests/validator.test.ts +537 -0
  422. package/claude-assets/skills/{cfn-redis-coordination → cfn-loop-validation}/tsconfig.json +34 -31
  423. package/claude-assets/skills/cfn-loop-validation/validate-deliverables.sh +59 -0
  424. package/claude-assets/skills/cfn-loop-validation/validate-deliverables.sh.backup +37 -0
  425. package/claude-assets/skills/cfn-loop-validation/validate-gate.sh +63 -0
  426. package/claude-assets/skills/cfn-loop-validation/validate-gate.sh.backup +41 -0
  427. package/claude-assets/skills/cfn-loop-validation/validate-iteration.sh +22 -0
  428. package/claude-assets/skills/cfn-loop-validation/validate-iteration.sh.backup +134 -0
  429. package/claude-assets/skills/cfn-product-owner-decision/SKILL.md +479 -147
  430. package/claude-assets/skills/cfn-product-owner-decision/TYPESCRIPT_IMPLEMENTATION.md +653 -0
  431. package/claude-assets/skills/cfn-product-owner-decision/{execute-decision.sh → archive/legacy-bash/execute-decision.sh} +24 -2
  432. package/claude-assets/skills/cfn-provider-routing/README.md +129 -0
  433. package/claude-assets/skills/cfn-provider-routing/SKILL.md +215 -0
  434. package/claude-assets/skills/cfn-provider-routing/resolve-provider-model.ts +223 -0
  435. package/claude-assets/skills/docker-build/build.sh +1 -1
  436. package/claude-assets/skills/pre-edit-backup/SKILL.md +324 -0
  437. package/claude-assets/skills/pre-edit-backup/SKILL.md.backup +277 -0
  438. package/claude-assets/skills/pre-edit-backup/backup.sh +22 -0
  439. package/claude-assets/skills/pre-edit-backup/backup.sh.backup +107 -0
  440. package/dist/agent/skill-mcp-selector.js +2 -1
  441. package/dist/agent/skill-mcp-selector.js.map +1 -1
  442. package/dist/api/auth-endpoints.js +415 -0
  443. package/dist/api/auth-endpoints.js.map +1 -0
  444. package/dist/api/task-endpoints.js +562 -0
  445. package/dist/api/task-endpoints.js.map +1 -0
  446. package/dist/backend/server.js +418 -0
  447. package/dist/backend/server.js.map +1 -0
  448. package/dist/cfn-loop/product-owner/decision-parser.js +356 -0
  449. package/dist/cfn-loop/product-owner/decision-parser.js.map +1 -0
  450. package/dist/cfn-loop/product-owner/index.js +1 -0
  451. package/dist/cfn-loop/product-owner/index.js.map +1 -1
  452. package/dist/cli/agent-command.js +1 -1
  453. package/dist/cli/agent-command.js.map +1 -1
  454. package/dist/cli/agent-completion.js +273 -0
  455. package/dist/cli/agent-completion.js.map +1 -0
  456. package/dist/cli/agent-executor.js +470 -26
  457. package/dist/cli/agent-executor.js.map +1 -1
  458. package/dist/cli/agent-prompt-builder.js +83 -48
  459. package/dist/cli/agent-prompt-builder.js.map +1 -1
  460. package/dist/cli/agent-spawn.js +7 -4
  461. package/dist/cli/agent-spawn.js.map +1 -1
  462. package/dist/cli/agent-spawner.js +546 -0
  463. package/dist/cli/agent-spawner.js.map +1 -0
  464. package/dist/cli/agent-token-manager.js +2 -1
  465. package/dist/cli/agent-token-manager.js.map +1 -1
  466. package/dist/cli/anthropic-client.js +127 -14
  467. package/dist/cli/anthropic-client.js.map +1 -1
  468. package/dist/cli/cfn-context.js +2 -1
  469. package/dist/cli/cfn-context.js.map +1 -1
  470. package/dist/cli/cfn-metrics.js +2 -1
  471. package/dist/cli/cfn-metrics.js.map +1 -1
  472. package/dist/cli/cfn-redis.js +2 -1
  473. package/dist/cli/cfn-redis.js.map +1 -1
  474. package/dist/cli/cli-agent-context.js +2 -0
  475. package/dist/cli/cli-agent-context.js.map +1 -1
  476. package/dist/cli/config-manager.js +90 -356
  477. package/dist/cli/config-manager.js.map +1 -1
  478. package/dist/cli/conversation-fork-cleanup.js +2 -1
  479. package/dist/cli/conversation-fork-cleanup.js.map +1 -1
  480. package/dist/cli/conversation-fork.js +2 -1
  481. package/dist/cli/conversation-fork.js.map +1 -1
  482. package/dist/cli/coordination/agent-messaging.js +415 -0
  483. package/dist/cli/coordination/agent-messaging.js.map +1 -0
  484. package/dist/cli/coordination/wait-for-threshold.js +232 -0
  485. package/dist/cli/coordination/wait-for-threshold.js.map +1 -0
  486. package/dist/cli/index.js +11 -0
  487. package/dist/cli/index.js.map +1 -1
  488. package/dist/cli/iteration-history.js +2 -1
  489. package/dist/cli/iteration-history.js.map +1 -1
  490. package/dist/cli/parse-decision-cli.js +268 -0
  491. package/dist/cli/parse-decision-cli.js.map +1 -0
  492. package/dist/cli/post-edit-hook.js +83 -0
  493. package/dist/cli/post-edit-hook.js.map +1 -0
  494. package/dist/cli/pre-edit-hook.js +77 -0
  495. package/dist/cli/pre-edit-hook.js.map +1 -0
  496. package/dist/cli/process-lifecycle.js +5 -1
  497. package/dist/cli/process-lifecycle.js.map +1 -1
  498. package/dist/cli/spawn-agent-cli.js +244 -0
  499. package/dist/cli/spawn-agent-cli.js.map +1 -0
  500. package/dist/coordination/coordination-wrapper.js +383 -0
  501. package/dist/coordination/coordination-wrapper.js.map +1 -0
  502. package/dist/coordination/redis-waiting-mode.js +4 -0
  503. package/dist/coordination/redis-waiting-mode.js.map +1 -1
  504. package/dist/coordination/store-success-criteria.js +68 -0
  505. package/dist/coordination/store-success-criteria.js.map +1 -0
  506. package/dist/coordination/store-task-context.js +65 -0
  507. package/dist/coordination/store-task-context.js.map +1 -0
  508. package/dist/hooks/backup-manager.js +273 -0
  509. package/dist/hooks/backup-manager.js.map +1 -0
  510. package/dist/hooks/post-edit-validator.js +388 -0
  511. package/dist/hooks/post-edit-validator.js.map +1 -0
  512. package/dist/integration/index.js +19 -0
  513. package/dist/integration/index.js.map +1 -0
  514. package/dist/integration/task-mode-adapter.js +297 -0
  515. package/dist/integration/task-mode-adapter.js.map +1 -0
  516. package/dist/integration/trigger-dev-client.js +253 -0
  517. package/dist/integration/trigger-dev-client.js.map +1 -0
  518. package/dist/integration/trigger-dev-webhooks.js +362 -0
  519. package/dist/integration/trigger-dev-webhooks.js.map +1 -0
  520. package/dist/lib/artifact-registry.js +4 -0
  521. package/dist/lib/artifact-registry.js.map +1 -1
  522. package/dist/lib/connection-pool.js +390 -0
  523. package/dist/lib/connection-pool.js.map +1 -0
  524. package/dist/lib/environment-contract.js +258 -0
  525. package/dist/lib/environment-contract.js.map +1 -0
  526. package/dist/lib/path-validator.js +14 -5
  527. package/dist/lib/path-validator.js.map +1 -1
  528. package/dist/lib/query-optimizer.js +388 -0
  529. package/dist/lib/query-optimizer.js.map +1 -0
  530. package/dist/lib/redis-queue-manager.js +5 -1
  531. package/dist/lib/redis-queue-manager.js.map +1 -1
  532. package/dist/lib/result-cache.js +285 -0
  533. package/dist/lib/result-cache.js.map +1 -0
  534. package/dist/mcp/auth-middleware.js +2 -1
  535. package/dist/mcp/auth-middleware.js.map +1 -1
  536. package/dist/mcp/playwright-mcp-server-auth.js +2 -1
  537. package/dist/mcp/playwright-mcp-server-auth.js.map +1 -1
  538. package/dist/middleware/authentication.js +317 -0
  539. package/dist/middleware/authentication.js.map +1 -0
  540. package/dist/services/authentication.js +669 -0
  541. package/dist/services/authentication.js.map +1 -0
  542. package/dist/services/session-management.js +436 -0
  543. package/dist/services/session-management.js.map +1 -0
  544. package/dist/services/skill-deployment.js +8 -6
  545. package/dist/services/skill-deployment.js.map +1 -1
  546. package/dist/services/user-service.js +710 -0
  547. package/dist/services/user-service.js.map +1 -0
  548. package/dist/types/trigger-dev-events.d.js +10 -0
  549. package/dist/types/trigger-dev-events.d.js.map +1 -0
  550. package/docs/README.md +240 -0
  551. package/package.json +15 -4
  552. package/scripts/build-agent-image.sh +1 -1
  553. package/scripts/compare-workflow-performance.sh +556 -0
  554. package/scripts/cost-allocation-tracker.sh +632 -0
  555. package/scripts/docker-rebuild-all-agents.sh +2 -2
  556. package/scripts/migrate-to-optimized-workflows.sh +438 -0
  557. package/scripts/organize-docs.sh +338 -0
  558. package/scripts/reorganize-tests.sh +280 -0
  559. package/scripts/trigger-dev-setup.sh +279 -0
  560. package/tests/README.md +45 -0
  561. package/.claude/commands/cost-savings-status.md +0 -34
  562. package/.claude/commands/metrics-summary.md +0 -58
  563. package/.claude/skills/cfn-docker-redis-coordination/MIGRATION_SUMMARY.md +0 -348
  564. package/.claude/skills/cfn-docker-redis-coordination/README.md +0 -294
  565. package/.claude/skills/cfn-docker-redis-coordination/SKILL.md +0 -435
  566. package/.claude/skills/cfn-docker-redis-coordination/coordinate.sh +0 -650
  567. package/.claude/skills/cfn-docker-redis-coordination/coordinate.sh.backup-1763145142 +0 -641
  568. package/.claude/skills/cfn-docker-redis-coordination/package-lock.json +0 -5259
  569. package/.claude/skills/cfn-docker-redis-coordination/package.json +0 -40
  570. package/.claude/skills/cfn-docker-redis-coordination/src/coordinator.ts +0 -801
  571. package/.claude/skills/cfn-docker-redis-coordination/src/index.ts +0 -42
  572. package/.claude/skills/cfn-docker-redis-coordination/src/types.ts +0 -351
  573. package/.claude/skills/cfn-docker-redis-coordination/tests/coordinator.test.ts +0 -1464
  574. package/.claude/skills/cfn-docker-redis-coordination/tsconfig.json +0 -30
  575. package/.claude/skills/cfn-loop-orchestration/helpers/auto-tune-timeouts.sh +0 -228
  576. package/.claude/skills/cfn-loop-orchestration/helpers/consensus-ts.sh +0 -104
  577. package/.claude/skills/cfn-loop-orchestration/helpers/consensus.sh +0 -94
  578. package/.claude/skills/cfn-loop-orchestration/helpers/context-injection.sh +0 -142
  579. package/.claude/skills/cfn-loop-orchestration/helpers/context-lookup.sh +0 -359
  580. package/.claude/skills/cfn-loop-orchestration/helpers/deliverable-verifier-ts.sh +0 -123
  581. package/.claude/skills/cfn-loop-orchestration/helpers/deliverable-verifier.sh +0 -71
  582. package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +0 -56
  583. package/.claude/skills/cfn-loop-orchestration/helpers/iteration-manager-ts.sh +0 -89
  584. package/.claude/skills/cfn-loop-orchestration/helpers/iteration-manager.sh +0 -87
  585. package/.claude/skills/cfn-loop-orchestration/helpers/orchestrate-ts.sh +0 -104
  586. package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +0 -56
  587. package/.claude/skills/cfn-loop-orchestration/helpers/spawn-agents.sh +0 -290
  588. package/.claude/skills/cfn-loop-orchestration/helpers/timeout-calculator-ts.sh +0 -47
  589. package/.claude/skills/cfn-loop-orchestration/helpers/timeout-calculator.sh +0 -51
  590. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +0 -1345
  591. package/.claude/skills/cfn-redis-coordination/AGENT_LOGGING.md +0 -280
  592. package/.claude/skills/cfn-redis-coordination/BZPOPMIN_FIX_SUMMARY.md +0 -209
  593. package/.claude/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +0 -319
  594. package/.claude/skills/cfn-redis-coordination/agent-log.sh.bak +0 -124
  595. package/.claude/skills/cfn-redis-coordination/config.json +0 -61
  596. package/.claude/skills/cfn-redis-coordination/demos/phase4-wake-queue-test-report.md +0 -82
  597. package/.claude/skills/cfn-redis-coordination/demos/test-bzpopmin-fix.sh +0 -274
  598. package/.claude/skills/cfn-redis-coordination/demos/test-cancel-swarm.sh +0 -0
  599. package/.claude/skills/cfn-redis-coordination/docs/migration/PHASE_3_REDIS_COORDINATION_COMPLETION_REPORT.md +0 -553
  600. package/.claude/skills/cfn-redis-coordination/jest.config.js +0 -23
  601. package/.claude/skills/cfn-redis-coordination/package-lock.json +0 -5272
  602. package/.claude/skills/cfn-redis-coordination/package.json +0 -45
  603. package/.claude/skills/cfn-redis-coordination/src/agent-logger.ts +0 -446
  604. package/.claude/skills/cfn-redis-coordination/src/agent-recovery.ts +0 -454
  605. package/.claude/skills/cfn-redis-coordination/src/completion-reporter.ts +0 -396
  606. package/.claude/skills/cfn-redis-coordination/src/context-manager.ts +0 -327
  607. package/.claude/skills/cfn-redis-coordination/src/index.ts +0 -82
  608. package/.claude/skills/cfn-redis-coordination/src/mode-detector.ts +0 -155
  609. package/.claude/skills/cfn-redis-coordination/src/redis/redis-client.ts +0 -305
  610. package/.claude/skills/cfn-redis-coordination/src/redis/redis-functions.ts +0 -283
  611. package/.claude/skills/cfn-redis-coordination/src/redis-client.ts +0 -654
  612. package/.claude/skills/cfn-redis-coordination/src/result-collector.ts +0 -437
  613. package/.claude/skills/cfn-redis-coordination/src/swarm-manager.ts +0 -494
  614. package/.claude/skills/cfn-redis-coordination/src/task-analyzer.ts +0 -404
  615. package/.claude/skills/cfn-redis-coordination/src/task-executor.ts +0 -423
  616. package/.claude/skills/cfn-redis-coordination/src/types.ts +0 -235
  617. package/.claude/skills/cfn-redis-coordination/src/waiting-coordinator.ts +0 -587
  618. package/.claude/skills/cfn-redis-coordination/store-success-criteria.sh +0 -85
  619. package/.claude/skills/cfn-redis-coordination/test-connection-attempts.js +0 -70
  620. package/.claude/skills/cfn-redis-coordination/test-mode-simple.js +0 -121
  621. package/.claude/skills/cfn-redis-coordination/test-redis-check.js +0 -84
  622. package/.claude/skills/cfn-redis-coordination/test-task-mode-redis.cjs +0 -391
  623. package/.claude/skills/cfn-redis-coordination/tests/coordination.test.ts +0 -788
  624. package/.claude/skills/cfn-redis-coordination/update-all-scripts.sh +0 -67
  625. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +0 -980
  626. package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +0 -759
  627. package/claude-assets/agents/custom/test-mcp-access.md +0 -24
  628. package/claude-assets/agents/typescript-specialist.md +0 -280
  629. package/claude-assets/commands/cost-savings-status.md +0 -34
  630. package/claude-assets/commands/metrics-summary.md +0 -58
  631. package/claude-assets/skills/cfn-docker-redis-coordination/MIGRATION_SUMMARY.md +0 -348
  632. package/claude-assets/skills/cfn-docker-redis-coordination/README.md +0 -294
  633. package/claude-assets/skills/cfn-docker-redis-coordination/SKILL.md +0 -435
  634. package/claude-assets/skills/cfn-docker-redis-coordination/coordinate.sh +0 -650
  635. package/claude-assets/skills/cfn-docker-redis-coordination/coordinate.sh.backup-1763145142 +0 -641
  636. package/claude-assets/skills/cfn-docker-redis-coordination/jest.config.js +0 -37
  637. package/claude-assets/skills/cfn-docker-redis-coordination/package-lock.json +0 -5259
  638. package/claude-assets/skills/cfn-docker-redis-coordination/package.json +0 -40
  639. package/claude-assets/skills/cfn-docker-redis-coordination/src/coordinator.ts +0 -801
  640. package/claude-assets/skills/cfn-docker-redis-coordination/src/index.ts +0 -42
  641. package/claude-assets/skills/cfn-docker-redis-coordination/src/types.ts +0 -351
  642. package/claude-assets/skills/cfn-docker-redis-coordination/tests/coordinator.test.ts +0 -1464
  643. package/claude-assets/skills/cfn-loop-orchestration/helpers/auto-tune-timeouts.sh +0 -228
  644. package/claude-assets/skills/cfn-loop-orchestration/helpers/consensus-ts.sh +0 -104
  645. package/claude-assets/skills/cfn-loop-orchestration/helpers/consensus.sh +0 -94
  646. package/claude-assets/skills/cfn-loop-orchestration/helpers/context-injection.sh +0 -142
  647. package/claude-assets/skills/cfn-loop-orchestration/helpers/context-lookup.sh +0 -359
  648. package/claude-assets/skills/cfn-loop-orchestration/helpers/deliverable-verifier-ts.sh +0 -123
  649. package/claude-assets/skills/cfn-loop-orchestration/helpers/deliverable-verifier.sh +0 -71
  650. package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +0 -56
  651. package/claude-assets/skills/cfn-loop-orchestration/helpers/iteration-manager-ts.sh +0 -89
  652. package/claude-assets/skills/cfn-loop-orchestration/helpers/iteration-manager.sh +0 -87
  653. package/claude-assets/skills/cfn-loop-orchestration/helpers/orchestrate-ts.sh +0 -104
  654. package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +0 -56
  655. package/claude-assets/skills/cfn-loop-orchestration/helpers/spawn-agents.sh +0 -290
  656. package/claude-assets/skills/cfn-loop-orchestration/helpers/timeout-calculator-ts.sh +0 -47
  657. package/claude-assets/skills/cfn-loop-orchestration/helpers/timeout-calculator.sh +0 -51
  658. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +0 -1345
  659. package/claude-assets/skills/cfn-redis-cleanup/cleanup-redis.sh +0 -130
  660. package/claude-assets/skills/cfn-redis-coordination/AGENT_LOGGING.md +0 -280
  661. package/claude-assets/skills/cfn-redis-coordination/BZPOPMIN_FIX_SUMMARY.md +0 -209
  662. package/claude-assets/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +0 -319
  663. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh.bak +0 -124
  664. package/claude-assets/skills/cfn-redis-coordination/config.json +0 -61
  665. package/claude-assets/skills/cfn-redis-coordination/demos/phase4-wake-queue-test-report.md +0 -82
  666. package/claude-assets/skills/cfn-redis-coordination/demos/test-bzpopmin-fix.sh +0 -274
  667. package/claude-assets/skills/cfn-redis-coordination/demos/test-cancel-swarm.sh +0 -0
  668. package/claude-assets/skills/cfn-redis-coordination/docs/migration/PHASE_3_REDIS_COORDINATION_COMPLETION_REPORT.md +0 -553
  669. package/claude-assets/skills/cfn-redis-coordination/jest.config.js +0 -23
  670. package/claude-assets/skills/cfn-redis-coordination/package-lock.json +0 -5272
  671. package/claude-assets/skills/cfn-redis-coordination/package.json +0 -45
  672. package/claude-assets/skills/cfn-redis-coordination/src/agent-logger.ts +0 -446
  673. package/claude-assets/skills/cfn-redis-coordination/src/agent-recovery.ts +0 -454
  674. package/claude-assets/skills/cfn-redis-coordination/src/completion-reporter.ts +0 -396
  675. package/claude-assets/skills/cfn-redis-coordination/src/context-manager.ts +0 -327
  676. package/claude-assets/skills/cfn-redis-coordination/src/index.ts +0 -82
  677. package/claude-assets/skills/cfn-redis-coordination/src/mode-detector.ts +0 -155
  678. package/claude-assets/skills/cfn-redis-coordination/src/redis/redis-client.ts +0 -305
  679. package/claude-assets/skills/cfn-redis-coordination/src/redis/redis-functions.ts +0 -283
  680. package/claude-assets/skills/cfn-redis-coordination/src/redis-client.ts +0 -654
  681. package/claude-assets/skills/cfn-redis-coordination/src/result-collector.ts +0 -437
  682. package/claude-assets/skills/cfn-redis-coordination/src/swarm-manager.ts +0 -494
  683. package/claude-assets/skills/cfn-redis-coordination/src/task-analyzer.ts +0 -404
  684. package/claude-assets/skills/cfn-redis-coordination/src/task-executor.ts +0 -423
  685. package/claude-assets/skills/cfn-redis-coordination/src/types.ts +0 -235
  686. package/claude-assets/skills/cfn-redis-coordination/src/waiting-coordinator.ts +0 -587
  687. package/claude-assets/skills/cfn-redis-coordination/store-success-criteria.sh +0 -85
  688. package/claude-assets/skills/cfn-redis-coordination/test-connection-attempts.js +0 -70
  689. package/claude-assets/skills/cfn-redis-coordination/test-mode-simple.js +0 -121
  690. package/claude-assets/skills/cfn-redis-coordination/test-redis-check.js +0 -84
  691. package/claude-assets/skills/cfn-redis-coordination/test-task-mode-redis.cjs +0 -391
  692. package/claude-assets/skills/cfn-redis-coordination/tests/coordination.test.ts +0 -788
  693. package/claude-assets/skills/cfn-redis-coordination/update-all-scripts.sh +0 -67
  694. package/claude-assets/skills/cfn-redis-data-extraction/SKILL.md +0 -442
  695. package/claude-assets/skills/cfn-redis-data-extraction/extract.sh +0 -306
  696. package/dist/coordination/index.js +0 -25
  697. package/dist/coordination/index.js.map +0 -1
  698. package/docs/BUG_19_MEMORY_LEAK_TASK_MODE.md +0 -405
  699. package/docs/MEMORY_CLEANUP_GUIDE.md +0 -358
  700. package/docs/MEMORY_LEAK_FIX_SUMMARY.md +0 -322
  701. package/docs/REDIS_CLEANUP_EXECUTIVE_SUMMARY.md +0 -319
  702. package/docs/REDIS_CLEANUP_VERIFICATION_REPORT.md +0 -574
  703. package/tests/test-memory-leak-task-mode.sh +0 -435
  704. /package/.claude/skills/cfn-loop-orchestration/{inject-loop-context.sh → archive/legacy-bash/inject-loop-context.sh} +0 -0
  705. /package/.claude/skills/cfn-loop-orchestration/{monitor-execution.sh → archive/legacy-bash/monitor-execution.sh} +0 -0
  706. /package/.claude/skills/cfn-redis-coordination/{agent-log.sh → agent-log.sh.backup} +0 -0
  707. /package/.claude/skills/cfn-redis-coordination/{agent-recovery.sh → agent-recovery.sh.backup} +0 -0
  708. /package/.claude/skills/cfn-redis-coordination/{analyze-task-complexity.sh → analyze-task-complexity.sh.backup} +0 -0
  709. /package/.claude/skills/cfn-redis-coordination/bash-wrappers/{store-context.sh → store-context.sh.backup} +0 -0
  710. /package/.claude/skills/cfn-redis-coordination/{cancel-swarm.sh → cancel-swarm.sh.backup} +0 -0
  711. /package/.claude/skills/cfn-redis-coordination/{cfn-loop-exec.sh → cfn-loop-exec.sh.backup} +0 -0
  712. /package/.claude/skills/cfn-redis-coordination/{cfn-loop-relaunch.sh → cfn-loop-relaunch.sh.backup} +0 -0
  713. /package/.claude/skills/cfn-redis-coordination/{collect-confidence-scores.sh → collect-confidence-scores.sh.backup} +0 -0
  714. /package/.claude/skills/cfn-redis-coordination/{collect-results.sh → collect-results.sh.backup} +0 -0
  715. /package/.claude/skills/cfn-redis-coordination/{complete-swarm.sh → complete-swarm.sh.backup} +0 -0
  716. /package/.claude/skills/cfn-redis-coordination/{get-context.sh → get-context.sh.backup} +0 -0
  717. /package/.claude/skills/cfn-redis-coordination/{get-success-criteria.sh → get-success-criteria.sh.backup} +0 -0
  718. /package/.claude/skills/cfn-redis-coordination/{invoke-waiting-mode.sh → invoke-waiting-mode.sh.backup} +0 -0
  719. /package/.claude/skills/cfn-redis-coordination/{redis-cli-wrapper.sh → redis-cli-wrapper.sh.backup} +0 -0
  720. /package/.claude/skills/cfn-redis-coordination/{redis-functions.sh → redis-functions.sh.backup} +0 -0
  721. /package/.claude/skills/cfn-redis-coordination/{report-completion.sh → report-completion.sh.backup} +0 -0
  722. /package/.claude/skills/cfn-redis-coordination/{store-context.sh → store-context.sh.backup} +0 -0
  723. /package/claude-assets/skills/cfn-loop-orchestration/{inject-loop-context.sh → archive/legacy-bash/inject-loop-context.sh} +0 -0
  724. /package/claude-assets/skills/cfn-loop-orchestration/{monitor-execution.sh → archive/legacy-bash/monitor-execution.sh} +0 -0
  725. /package/claude-assets/skills/cfn-redis-coordination/{agent-log.sh → agent-log.sh.backup} +0 -0
  726. /package/claude-assets/skills/cfn-redis-coordination/{agent-recovery.sh → agent-recovery.sh.backup} +0 -0
  727. /package/claude-assets/skills/cfn-redis-coordination/{analyze-task-complexity.sh → analyze-task-complexity.sh.backup} +0 -0
  728. /package/claude-assets/skills/cfn-redis-coordination/bash-wrappers/{store-context.sh → store-context.sh.backup} +0 -0
  729. /package/claude-assets/skills/cfn-redis-coordination/{cancel-swarm.sh → cancel-swarm.sh.backup} +0 -0
  730. /package/claude-assets/skills/cfn-redis-coordination/{cfn-loop-exec.sh → cfn-loop-exec.sh.backup} +0 -0
  731. /package/claude-assets/skills/cfn-redis-coordination/{cfn-loop-relaunch.sh → cfn-loop-relaunch.sh.backup} +0 -0
  732. /package/claude-assets/skills/cfn-redis-coordination/{collect-confidence-scores.sh → collect-confidence-scores.sh.backup} +0 -0
  733. /package/claude-assets/skills/cfn-redis-coordination/{collect-results.sh → collect-results.sh.backup} +0 -0
  734. /package/claude-assets/skills/cfn-redis-coordination/{complete-swarm.sh → complete-swarm.sh.backup} +0 -0
  735. /package/claude-assets/skills/cfn-redis-coordination/{get-context.sh → get-context.sh.backup} +0 -0
  736. /package/claude-assets/skills/cfn-redis-coordination/{get-success-criteria.sh → get-success-criteria.sh.backup} +0 -0
  737. /package/claude-assets/skills/cfn-redis-coordination/{invoke-waiting-mode.sh → invoke-waiting-mode.sh.backup} +0 -0
  738. /package/claude-assets/skills/cfn-redis-coordination/{redis-cli-wrapper.sh → redis-cli-wrapper.sh.backup} +0 -0
  739. /package/claude-assets/skills/cfn-redis-coordination/{redis-functions.sh → redis-functions.sh.backup} +0 -0
  740. /package/claude-assets/skills/cfn-redis-coordination/{report-completion.sh → report-completion.sh.backup} +0 -0
  741. /package/claude-assets/skills/cfn-redis-coordination/{store-context.sh → store-context.sh.backup} +0 -0
@@ -0,0 +1,388 @@
1
+ /**
2
+ * Query Optimizer
3
+ *
4
+ * Implements database query optimizations including:
5
+ * - Index management for agents table
6
+ * - Materialized views for cost aggregation
7
+ * - Query pattern optimization
8
+ * - Expected: 10-20x query speedup
9
+ *
10
+ * Features:
11
+ * - Automated index creation
12
+ * - Materialized view management
13
+ * - Query rewriting for optimal execution
14
+ * - Performance monitoring
15
+ */ export class QueryOptimizer {
16
+ pool;
17
+ refreshInterval;
18
+ refreshTimer = null;
19
+ constructor(config){
20
+ this.pool = config.pool;
21
+ this.refreshInterval = config.refreshInterval || 3600000; // 1 hour default
22
+ }
23
+ /**
24
+ * Initialize all query optimizations
25
+ */ async initialize() {
26
+ console.log('Initializing query optimizer...');
27
+ await this.createIndexes();
28
+ await this.createMaterializedViews();
29
+ await this.startMaterializedViewRefresh();
30
+ console.log('Query optimizer initialized successfully');
31
+ }
32
+ /**
33
+ * Create indexes on agents table for performance
34
+ * Indexes: team_id, status, spawned_at
35
+ */ async createIndexes() {
36
+ const indexes = [
37
+ {
38
+ name: 'idx_agents_team_id',
39
+ table: 'agents',
40
+ columns: [
41
+ 'team_id'
42
+ ],
43
+ description: 'Index for team-based queries'
44
+ },
45
+ {
46
+ name: 'idx_agents_status',
47
+ table: 'agents',
48
+ columns: [
49
+ 'status'
50
+ ],
51
+ description: 'Index for status filtering'
52
+ },
53
+ {
54
+ name: 'idx_agents_spawned_at',
55
+ table: 'agents',
56
+ columns: [
57
+ 'spawned_at'
58
+ ],
59
+ description: 'Index for time-based queries'
60
+ },
61
+ {
62
+ name: 'idx_agents_team_status',
63
+ table: 'agents',
64
+ columns: [
65
+ 'team_id',
66
+ 'status'
67
+ ],
68
+ description: 'Composite index for team + status queries'
69
+ },
70
+ {
71
+ name: 'idx_agents_status_spawned',
72
+ table: 'agents',
73
+ columns: [
74
+ 'status',
75
+ 'spawned_at'
76
+ ],
77
+ description: 'Composite index for status + time queries'
78
+ },
79
+ {
80
+ name: 'idx_agents_cost_query',
81
+ table: 'agents',
82
+ columns: [
83
+ 'team_id',
84
+ 'spawned_at',
85
+ 'status'
86
+ ],
87
+ description: 'Composite index for cost aggregation queries'
88
+ }
89
+ ];
90
+ const client = await this.pool.connect();
91
+ try {
92
+ for (const index of indexes){
93
+ const query = `
94
+ CREATE INDEX IF NOT EXISTS ${index.name}
95
+ ON ${index.table} (${index.columns.join(', ')})
96
+ `;
97
+ await client.query(query);
98
+ console.log(`Created index: ${index.name} - ${index.description}`);
99
+ }
100
+ } finally{
101
+ client.release();
102
+ }
103
+ }
104
+ /**
105
+ * Create materialized views for cost aggregation queries
106
+ */ async createMaterializedViews() {
107
+ const client = await this.pool.connect();
108
+ try {
109
+ // Drop existing views if they exist
110
+ await client.query('DROP MATERIALIZED VIEW IF EXISTS mv_cost_by_team CASCADE');
111
+ await client.query('DROP MATERIALIZED VIEW IF EXISTS mv_cost_by_agent_type CASCADE');
112
+ await client.query('DROP MATERIALIZED VIEW IF EXISTS mv_daily_cost_summary CASCADE');
113
+ // Create materialized view for cost by team
114
+ await client.query(`
115
+ CREATE MATERIALIZED VIEW mv_cost_by_team AS
116
+ SELECT
117
+ team_id,
118
+ COUNT(*) as agent_count,
119
+ SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count,
120
+ SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_count,
121
+ AVG(confidence) as avg_confidence,
122
+ SUM(COALESCE(metadata::json->>'cost', '0')::numeric) as total_cost,
123
+ MIN(spawned_at) as first_spawn,
124
+ MAX(spawned_at) as last_spawn
125
+ FROM agents
126
+ WHERE team_id IS NOT NULL
127
+ GROUP BY team_id
128
+ `);
129
+ console.log('Created materialized view: mv_cost_by_team');
130
+ // Create materialized view for cost by agent type
131
+ await client.query(`
132
+ CREATE MATERIALIZED VIEW mv_cost_by_agent_type AS
133
+ SELECT
134
+ type as agent_type,
135
+ COUNT(*) as agent_count,
136
+ SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count,
137
+ SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_count,
138
+ AVG(confidence) as avg_confidence,
139
+ SUM(COALESCE(metadata::json->>'cost', '0')::numeric) as total_cost,
140
+ AVG(EXTRACT(EPOCH FROM (completed_at - spawned_at))) as avg_duration_seconds
141
+ FROM agents
142
+ WHERE type IS NOT NULL
143
+ GROUP BY type
144
+ `);
145
+ console.log('Created materialized view: mv_cost_by_agent_type');
146
+ // Create materialized view for daily cost summary
147
+ await client.query(`
148
+ CREATE MATERIALIZED VIEW mv_daily_cost_summary AS
149
+ SELECT
150
+ DATE(spawned_at) as date,
151
+ COUNT(*) as total_agents,
152
+ SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count,
153
+ SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_count,
154
+ SUM(COALESCE(metadata::json->>'cost', '0')::numeric) as total_cost,
155
+ AVG(confidence) as avg_confidence
156
+ FROM agents
157
+ WHERE spawned_at IS NOT NULL
158
+ GROUP BY DATE(spawned_at)
159
+ ORDER BY date DESC
160
+ `);
161
+ console.log('Created materialized view: mv_daily_cost_summary');
162
+ // Create UNIQUE indexes on materialized views (required for CONCURRENT refresh)
163
+ await client.query('CREATE UNIQUE INDEX idx_mv_cost_by_team_team_id ON mv_cost_by_team (team_id)');
164
+ await client.query('CREATE UNIQUE INDEX idx_mv_cost_by_agent_type_type ON mv_cost_by_agent_type (agent_type)');
165
+ await client.query('CREATE UNIQUE INDEX idx_mv_daily_cost_summary_date ON mv_daily_cost_summary (date)');
166
+ console.log('Created UNIQUE indexes on materialized views for concurrent refresh');
167
+ } finally{
168
+ client.release();
169
+ }
170
+ }
171
+ /**
172
+ * Refresh materialized views
173
+ */ async refreshMaterializedViews() {
174
+ const client = await this.pool.connect();
175
+ try {
176
+ console.log('Refreshing materialized views...');
177
+ await client.query('REFRESH MATERIALIZED VIEW CONCURRENTLY mv_cost_by_team');
178
+ await client.query('REFRESH MATERIALIZED VIEW CONCURRENTLY mv_cost_by_agent_type');
179
+ await client.query('REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_cost_summary');
180
+ console.log('Materialized views refreshed successfully');
181
+ } catch (err) {
182
+ console.error('Error refreshing materialized views:', err);
183
+ throw err;
184
+ } finally{
185
+ client.release();
186
+ }
187
+ }
188
+ /**
189
+ * Start automatic materialized view refresh
190
+ */ startMaterializedViewRefresh() {
191
+ if (this.refreshTimer) {
192
+ clearInterval(this.refreshTimer);
193
+ }
194
+ // Initial refresh
195
+ this.refreshMaterializedViews().catch(console.error);
196
+ // Schedule periodic refresh
197
+ this.refreshTimer = setInterval(()=>{
198
+ this.refreshMaterializedViews().catch(console.error);
199
+ }, this.refreshInterval);
200
+ console.log(`Started materialized view auto-refresh (interval: ${this.refreshInterval / 1000}s)`);
201
+ }
202
+ /**
203
+ * Stop automatic materialized view refresh
204
+ */ stopMaterializedViewRefresh() {
205
+ if (this.refreshTimer) {
206
+ clearInterval(this.refreshTimer);
207
+ this.refreshTimer = null;
208
+ console.log('Stopped materialized view auto-refresh');
209
+ }
210
+ }
211
+ /**
212
+ * Optimized query: Get cost by team
213
+ */ async getCostByTeam(teamId) {
214
+ const client = await this.pool.connect();
215
+ try {
216
+ let query = 'SELECT * FROM mv_cost_by_team';
217
+ const params = [];
218
+ if (teamId) {
219
+ query += ' WHERE team_id = $1';
220
+ params.push(teamId);
221
+ }
222
+ query += ' ORDER BY total_cost DESC';
223
+ const result = await client.query(query, params);
224
+ return result.rows;
225
+ } finally{
226
+ client.release();
227
+ }
228
+ }
229
+ /**
230
+ * Optimized query: Get cost by agent type
231
+ */ async getCostByAgentType(agentType) {
232
+ const client = await this.pool.connect();
233
+ try {
234
+ let query = 'SELECT * FROM mv_cost_by_agent_type';
235
+ const params = [];
236
+ if (agentType) {
237
+ query += ' WHERE agent_type = $1';
238
+ params.push(agentType);
239
+ }
240
+ query += ' ORDER BY total_cost DESC';
241
+ const result = await client.query(query, params);
242
+ return result.rows;
243
+ } finally{
244
+ client.release();
245
+ }
246
+ }
247
+ /**
248
+ * Optimized query: Get daily cost summary
249
+ */ async getDailyCostSummary(startDate, endDate) {
250
+ const client = await this.pool.connect();
251
+ try {
252
+ let query = 'SELECT * FROM mv_daily_cost_summary';
253
+ const params = [];
254
+ const conditions = [];
255
+ if (startDate) {
256
+ params.push(startDate);
257
+ conditions.push(`date >= $${params.length}`);
258
+ }
259
+ if (endDate) {
260
+ params.push(endDate);
261
+ conditions.push(`date <= $${params.length}`);
262
+ }
263
+ if (conditions.length > 0) {
264
+ query += ' WHERE ' + conditions.join(' AND ');
265
+ }
266
+ query += ' ORDER BY date DESC';
267
+ const result = await client.query(query, params);
268
+ return result.rows;
269
+ } finally{
270
+ client.release();
271
+ }
272
+ }
273
+ /**
274
+ * Optimized query: Get agents by team and status
275
+ * Uses composite index idx_agents_team_status
276
+ */ async getAgentsByTeamAndStatus(teamId, status) {
277
+ const client = await this.pool.connect();
278
+ try {
279
+ const query = `
280
+ SELECT *
281
+ FROM agents
282
+ WHERE team_id = $1 AND status = $2
283
+ ORDER BY spawned_at DESC
284
+ `;
285
+ const result = await client.query(query, [
286
+ teamId,
287
+ status
288
+ ]);
289
+ return result.rows;
290
+ } finally{
291
+ client.release();
292
+ }
293
+ }
294
+ /**
295
+ * Optimized query: Get agents by status and time range
296
+ * Uses composite index idx_agents_status_spawned
297
+ */ async getAgentsByStatusAndTimeRange(status, startDate, endDate) {
298
+ const client = await this.pool.connect();
299
+ try {
300
+ const query = `
301
+ SELECT *
302
+ FROM agents
303
+ WHERE status = $1
304
+ AND spawned_at >= $2
305
+ AND spawned_at <= $3
306
+ ORDER BY spawned_at DESC
307
+ `;
308
+ const result = await client.query(query, [
309
+ status,
310
+ startDate,
311
+ endDate
312
+ ]);
313
+ return result.rows;
314
+ } finally{
315
+ client.release();
316
+ }
317
+ }
318
+ /**
319
+ * Analyze query performance
320
+ */ async analyzeQuery(query, params) {
321
+ const client = await this.pool.connect();
322
+ try {
323
+ const explainQuery = `EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) ${query}`;
324
+ const result = await client.query(explainQuery, params);
325
+ return result.rows[0]['QUERY PLAN'][0];
326
+ } finally{
327
+ client.release();
328
+ }
329
+ }
330
+ /**
331
+ * Get index usage statistics
332
+ */ async getIndexUsageStats() {
333
+ const client = await this.pool.connect();
334
+ try {
335
+ const query = `
336
+ SELECT
337
+ schemaname,
338
+ tablename,
339
+ indexname,
340
+ idx_scan as index_scans,
341
+ idx_tup_read as tuples_read,
342
+ idx_tup_fetch as tuples_fetched
343
+ FROM pg_stat_user_indexes
344
+ WHERE schemaname = 'public'
345
+ ORDER BY idx_scan DESC
346
+ `;
347
+ const result = await client.query(query);
348
+ return result.rows;
349
+ } finally{
350
+ client.release();
351
+ }
352
+ }
353
+ /**
354
+ * Shutdown query optimizer
355
+ */ async shutdown() {
356
+ this.stopMaterializedViewRefresh();
357
+ console.log('Query optimizer shutdown complete');
358
+ }
359
+ }
360
+ // Singleton instance
361
+ let queryOptimizerInstance = null;
362
+ /**
363
+ * Initialize singleton query optimizer
364
+ */ export async function initQueryOptimizer(config) {
365
+ if (!queryOptimizerInstance) {
366
+ queryOptimizerInstance = new QueryOptimizer(config);
367
+ await queryOptimizerInstance.initialize();
368
+ }
369
+ return queryOptimizerInstance;
370
+ }
371
+ /**
372
+ * Get singleton query optimizer instance
373
+ */ export function getQueryOptimizer() {
374
+ if (!queryOptimizerInstance) {
375
+ throw new Error('Query optimizer not initialized. Call initQueryOptimizer first.');
376
+ }
377
+ return queryOptimizerInstance;
378
+ }
379
+ /**
380
+ * Shutdown singleton query optimizer
381
+ */ export async function shutdownQueryOptimizer() {
382
+ if (queryOptimizerInstance) {
383
+ await queryOptimizerInstance.shutdown();
384
+ queryOptimizerInstance = null;
385
+ }
386
+ }
387
+
388
+ //# sourceMappingURL=query-optimizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/query-optimizer.ts"],"sourcesContent":["/**\r\n * Query Optimizer\r\n *\r\n * Implements database query optimizations including:\r\n * - Index management for agents table\r\n * - Materialized views for cost aggregation\r\n * - Query pattern optimization\r\n * - Expected: 10-20x query speedup\r\n *\r\n * Features:\r\n * - Automated index creation\r\n * - Materialized view management\r\n * - Query rewriting for optimal execution\r\n * - Performance monitoring\r\n */\r\n\r\nimport { Pool, PoolClient } from 'pg';\r\n\r\nexport interface QueryOptimizerConfig {\r\n pool: Pool;\r\n refreshInterval?: number; // Materialized view refresh interval in ms (default: 1 hour)\r\n}\r\n\r\nexport interface CostByTeam {\r\n team_id: string;\r\n agent_count: number;\r\n completed_count: number;\r\n failed_count: number;\r\n avg_confidence: number | null;\r\n total_cost: number;\r\n first_spawn: Date;\r\n last_spawn: Date;\r\n}\r\n\r\nexport interface CostByAgentType {\r\n agent_type: string;\r\n agent_count: number;\r\n completed_count: number;\r\n failed_count: number;\r\n avg_confidence: number | null;\r\n total_cost: number;\r\n avg_duration_seconds: number | null;\r\n}\r\n\r\nexport interface DailyCostSummary {\r\n date: Date;\r\n total_agents: number;\r\n completed_count: number;\r\n failed_count: number;\r\n total_cost: number;\r\n avg_confidence: number | null;\r\n}\r\n\r\nexport interface AgentRecord {\r\n id: string;\r\n team_id: string | null;\r\n type: string;\r\n status: string;\r\n spawned_at: Date;\r\n completed_at: Date | null;\r\n confidence: number | null;\r\n metadata: Record<string, unknown> | null;\r\n}\r\n\r\nexport interface IndexUsageStats {\r\n schemaname: string;\r\n tablename: string;\r\n indexname: string;\r\n index_scans: number;\r\n tuples_read: number;\r\n tuples_fetched: number;\r\n}\r\n\r\nexport interface QueryPlan {\r\n 'Plan': Record<string, unknown>;\r\n 'Planning Time': number;\r\n 'Execution Time': number;\r\n}\r\n\r\nexport class QueryOptimizer {\r\n private pool: Pool;\r\n private refreshInterval: number;\r\n private refreshTimer: NodeJS.Timeout | null = null;\r\n\r\n constructor(config: QueryOptimizerConfig) {\r\n this.pool = config.pool;\r\n this.refreshInterval = config.refreshInterval || 3600000; // 1 hour default\r\n }\r\n\r\n /**\r\n * Initialize all query optimizations\r\n */\r\n async initialize(): Promise<void> {\r\n console.log('Initializing query optimizer...');\r\n\r\n await this.createIndexes();\r\n await this.createMaterializedViews();\r\n await this.startMaterializedViewRefresh();\r\n\r\n console.log('Query optimizer initialized successfully');\r\n }\r\n\r\n /**\r\n * Create indexes on agents table for performance\r\n * Indexes: team_id, status, spawned_at\r\n */\r\n async createIndexes(): Promise<void> {\r\n const indexes = [\r\n {\r\n name: 'idx_agents_team_id',\r\n table: 'agents',\r\n columns: ['team_id'],\r\n description: 'Index for team-based queries',\r\n },\r\n {\r\n name: 'idx_agents_status',\r\n table: 'agents',\r\n columns: ['status'],\r\n description: 'Index for status filtering',\r\n },\r\n {\r\n name: 'idx_agents_spawned_at',\r\n table: 'agents',\r\n columns: ['spawned_at'],\r\n description: 'Index for time-based queries',\r\n },\r\n {\r\n name: 'idx_agents_team_status',\r\n table: 'agents',\r\n columns: ['team_id', 'status'],\r\n description: 'Composite index for team + status queries',\r\n },\r\n {\r\n name: 'idx_agents_status_spawned',\r\n table: 'agents',\r\n columns: ['status', 'spawned_at'],\r\n description: 'Composite index for status + time queries',\r\n },\r\n {\r\n name: 'idx_agents_cost_query',\r\n table: 'agents',\r\n columns: ['team_id', 'spawned_at', 'status'],\r\n description: 'Composite index for cost aggregation queries',\r\n },\r\n ];\r\n\r\n const client = await this.pool.connect();\r\n try {\r\n for (const index of indexes) {\r\n const query = `\r\n CREATE INDEX IF NOT EXISTS ${index.name}\r\n ON ${index.table} (${index.columns.join(', ')})\r\n `;\r\n\r\n await client.query(query);\r\n console.log(`Created index: ${index.name} - ${index.description}`);\r\n }\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Create materialized views for cost aggregation queries\r\n */\r\n async createMaterializedViews(): Promise<void> {\r\n const client = await this.pool.connect();\r\n try {\r\n // Drop existing views if they exist\r\n await client.query('DROP MATERIALIZED VIEW IF EXISTS mv_cost_by_team CASCADE');\r\n await client.query('DROP MATERIALIZED VIEW IF EXISTS mv_cost_by_agent_type CASCADE');\r\n await client.query('DROP MATERIALIZED VIEW IF EXISTS mv_daily_cost_summary CASCADE');\r\n\r\n // Create materialized view for cost by team\r\n await client.query(`\r\n CREATE MATERIALIZED VIEW mv_cost_by_team AS\r\n SELECT\r\n team_id,\r\n COUNT(*) as agent_count,\r\n SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count,\r\n SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_count,\r\n AVG(confidence) as avg_confidence,\r\n SUM(COALESCE(metadata::json->>'cost', '0')::numeric) as total_cost,\r\n MIN(spawned_at) as first_spawn,\r\n MAX(spawned_at) as last_spawn\r\n FROM agents\r\n WHERE team_id IS NOT NULL\r\n GROUP BY team_id\r\n `);\r\n console.log('Created materialized view: mv_cost_by_team');\r\n\r\n // Create materialized view for cost by agent type\r\n await client.query(`\r\n CREATE MATERIALIZED VIEW mv_cost_by_agent_type AS\r\n SELECT\r\n type as agent_type,\r\n COUNT(*) as agent_count,\r\n SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count,\r\n SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_count,\r\n AVG(confidence) as avg_confidence,\r\n SUM(COALESCE(metadata::json->>'cost', '0')::numeric) as total_cost,\r\n AVG(EXTRACT(EPOCH FROM (completed_at - spawned_at))) as avg_duration_seconds\r\n FROM agents\r\n WHERE type IS NOT NULL\r\n GROUP BY type\r\n `);\r\n console.log('Created materialized view: mv_cost_by_agent_type');\r\n\r\n // Create materialized view for daily cost summary\r\n await client.query(`\r\n CREATE MATERIALIZED VIEW mv_daily_cost_summary AS\r\n SELECT\r\n DATE(spawned_at) as date,\r\n COUNT(*) as total_agents,\r\n SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count,\r\n SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed_count,\r\n SUM(COALESCE(metadata::json->>'cost', '0')::numeric) as total_cost,\r\n AVG(confidence) as avg_confidence\r\n FROM agents\r\n WHERE spawned_at IS NOT NULL\r\n GROUP BY DATE(spawned_at)\r\n ORDER BY date DESC\r\n `);\r\n console.log('Created materialized view: mv_daily_cost_summary');\r\n\r\n // Create UNIQUE indexes on materialized views (required for CONCURRENT refresh)\r\n await client.query('CREATE UNIQUE INDEX idx_mv_cost_by_team_team_id ON mv_cost_by_team (team_id)');\r\n await client.query('CREATE UNIQUE INDEX idx_mv_cost_by_agent_type_type ON mv_cost_by_agent_type (agent_type)');\r\n await client.query('CREATE UNIQUE INDEX idx_mv_daily_cost_summary_date ON mv_daily_cost_summary (date)');\r\n\r\n console.log('Created UNIQUE indexes on materialized views for concurrent refresh');\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Refresh materialized views\r\n */\r\n async refreshMaterializedViews(): Promise<void> {\r\n const client = await this.pool.connect();\r\n try {\r\n console.log('Refreshing materialized views...');\r\n\r\n await client.query('REFRESH MATERIALIZED VIEW CONCURRENTLY mv_cost_by_team');\r\n await client.query('REFRESH MATERIALIZED VIEW CONCURRENTLY mv_cost_by_agent_type');\r\n await client.query('REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_cost_summary');\r\n\r\n console.log('Materialized views refreshed successfully');\r\n } catch (err) {\r\n console.error('Error refreshing materialized views:', err);\r\n throw err;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Start automatic materialized view refresh\r\n */\r\n startMaterializedViewRefresh(): void {\r\n if (this.refreshTimer) {\r\n clearInterval(this.refreshTimer);\r\n }\r\n\r\n // Initial refresh\r\n this.refreshMaterializedViews().catch(console.error);\r\n\r\n // Schedule periodic refresh\r\n this.refreshTimer = setInterval(() => {\r\n this.refreshMaterializedViews().catch(console.error);\r\n }, this.refreshInterval);\r\n\r\n console.log(\r\n `Started materialized view auto-refresh (interval: ${this.refreshInterval / 1000}s)`\r\n );\r\n }\r\n\r\n /**\r\n * Stop automatic materialized view refresh\r\n */\r\n stopMaterializedViewRefresh(): void {\r\n if (this.refreshTimer) {\r\n clearInterval(this.refreshTimer);\r\n this.refreshTimer = null;\r\n console.log('Stopped materialized view auto-refresh');\r\n }\r\n }\r\n\r\n /**\r\n * Optimized query: Get cost by team\r\n */\r\n async getCostByTeam(teamId?: string): Promise<CostByTeam[]> {\r\n const client = await this.pool.connect();\r\n try {\r\n let query = 'SELECT * FROM mv_cost_by_team';\r\n const params: unknown[] = [];\r\n\r\n if (teamId) {\r\n query += ' WHERE team_id = $1';\r\n params.push(teamId);\r\n }\r\n\r\n query += ' ORDER BY total_cost DESC';\r\n\r\n const result = await client.query(query, params);\r\n return result.rows;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Optimized query: Get cost by agent type\r\n */\r\n async getCostByAgentType(agentType?: string): Promise<CostByAgentType[]> {\r\n const client = await this.pool.connect();\r\n try {\r\n let query = 'SELECT * FROM mv_cost_by_agent_type';\r\n const params: unknown[] = [];\r\n\r\n if (agentType) {\r\n query += ' WHERE agent_type = $1';\r\n params.push(agentType);\r\n }\r\n\r\n query += ' ORDER BY total_cost DESC';\r\n\r\n const result = await client.query(query, params);\r\n return result.rows;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Optimized query: Get daily cost summary\r\n */\r\n async getDailyCostSummary(\r\n startDate?: Date,\r\n endDate?: Date\r\n ): Promise<DailyCostSummary[]> {\r\n const client = await this.pool.connect();\r\n try {\r\n let query = 'SELECT * FROM mv_daily_cost_summary';\r\n const params: unknown[] = [];\r\n\r\n const conditions: string[] = [];\r\n if (startDate) {\r\n params.push(startDate);\r\n conditions.push(`date >= $${params.length}`);\r\n }\r\n if (endDate) {\r\n params.push(endDate);\r\n conditions.push(`date <= $${params.length}`);\r\n }\r\n\r\n if (conditions.length > 0) {\r\n query += ' WHERE ' + conditions.join(' AND ');\r\n }\r\n\r\n query += ' ORDER BY date DESC';\r\n\r\n const result = await client.query(query, params);\r\n return result.rows;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Optimized query: Get agents by team and status\r\n * Uses composite index idx_agents_team_status\r\n */\r\n async getAgentsByTeamAndStatus(\r\n teamId: string,\r\n status: string\r\n ): Promise<AgentRecord[]> {\r\n const client = await this.pool.connect();\r\n try {\r\n const query = `\r\n SELECT *\r\n FROM agents\r\n WHERE team_id = $1 AND status = $2\r\n ORDER BY spawned_at DESC\r\n `;\r\n\r\n const result = await client.query(query, [teamId, status]);\r\n return result.rows;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Optimized query: Get agents by status and time range\r\n * Uses composite index idx_agents_status_spawned\r\n */\r\n async getAgentsByStatusAndTimeRange(\r\n status: string,\r\n startDate: Date,\r\n endDate: Date\r\n ): Promise<AgentRecord[]> {\r\n const client = await this.pool.connect();\r\n try {\r\n const query = `\r\n SELECT *\r\n FROM agents\r\n WHERE status = $1\r\n AND spawned_at >= $2\r\n AND spawned_at <= $3\r\n ORDER BY spawned_at DESC\r\n `;\r\n\r\n const result = await client.query(query, [status, startDate, endDate]);\r\n return result.rows;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Analyze query performance\r\n */\r\n async analyzeQuery(query: string, params?: unknown[]): Promise<QueryPlan> {\r\n const client = await this.pool.connect();\r\n try {\r\n const explainQuery = `EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) ${query}`;\r\n const result = await client.query(explainQuery, params);\r\n return result.rows[0]['QUERY PLAN'][0] as QueryPlan;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Get index usage statistics\r\n */\r\n async getIndexUsageStats(): Promise<IndexUsageStats[]> {\r\n const client = await this.pool.connect();\r\n try {\r\n const query = `\r\n SELECT\r\n schemaname,\r\n tablename,\r\n indexname,\r\n idx_scan as index_scans,\r\n idx_tup_read as tuples_read,\r\n idx_tup_fetch as tuples_fetched\r\n FROM pg_stat_user_indexes\r\n WHERE schemaname = 'public'\r\n ORDER BY idx_scan DESC\r\n `;\r\n\r\n const result = await client.query(query);\r\n return result.rows;\r\n } finally {\r\n client.release();\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown query optimizer\r\n */\r\n async shutdown(): Promise<void> {\r\n this.stopMaterializedViewRefresh();\r\n console.log('Query optimizer shutdown complete');\r\n }\r\n}\r\n\r\n// Singleton instance\r\nlet queryOptimizerInstance: QueryOptimizer | null = null;\r\n\r\n/**\r\n * Initialize singleton query optimizer\r\n */\r\nexport async function initQueryOptimizer(\r\n config: QueryOptimizerConfig\r\n): Promise<QueryOptimizer> {\r\n if (!queryOptimizerInstance) {\r\n queryOptimizerInstance = new QueryOptimizer(config);\r\n await queryOptimizerInstance.initialize();\r\n }\r\n\r\n return queryOptimizerInstance;\r\n}\r\n\r\n/**\r\n * Get singleton query optimizer instance\r\n */\r\nexport function getQueryOptimizer(): QueryOptimizer {\r\n if (!queryOptimizerInstance) {\r\n throw new Error(\r\n 'Query optimizer not initialized. Call initQueryOptimizer first.'\r\n );\r\n }\r\n return queryOptimizerInstance;\r\n}\r\n\r\n/**\r\n * Shutdown singleton query optimizer\r\n */\r\nexport async function shutdownQueryOptimizer(): Promise<void> {\r\n if (queryOptimizerInstance) {\r\n await queryOptimizerInstance.shutdown();\r\n queryOptimizerInstance = null;\r\n }\r\n}\r\n"],"names":["QueryOptimizer","pool","refreshInterval","refreshTimer","config","initialize","console","log","createIndexes","createMaterializedViews","startMaterializedViewRefresh","indexes","name","table","columns","description","client","connect","index","query","join","release","refreshMaterializedViews","err","error","clearInterval","catch","setInterval","stopMaterializedViewRefresh","getCostByTeam","teamId","params","push","result","rows","getCostByAgentType","agentType","getDailyCostSummary","startDate","endDate","conditions","length","getAgentsByTeamAndStatus","status","getAgentsByStatusAndTimeRange","analyzeQuery","explainQuery","getIndexUsageStats","shutdown","queryOptimizerInstance","initQueryOptimizer","getQueryOptimizer","Error","shutdownQueryOptimizer"],"mappings":"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"}
@@ -33,7 +33,7 @@
33
33
  * }
34
34
  */ import { v4 as uuidv4 } from 'uuid';
35
35
  import { createLogger } from './logging.js';
36
- import { createError, ErrorCode, isRetryableError } from './errors.js';
36
+ import { createError, ErrorCode, isRetryableError, StandardError } from './errors.js';
37
37
  import { withRetry } from './retry.js';
38
38
  import { MessageDeduplicator } from './message-deduplicator.js';
39
39
  const logger = createLogger('redis-queue-manager');
@@ -137,6 +137,10 @@ const DEFAULT_DEQUEUE_OPTIONS = {
137
137
  }
138
138
  return message.id;
139
139
  } catch (error) {
140
+ // Re-throw duplicate errors without wrapping
141
+ if (error instanceof StandardError && error.code === ErrorCode.DB_DUPLICATE_KEY) {
142
+ throw error;
143
+ }
140
144
  logger.error('Failed to enqueue message', error instanceof Error ? error : new Error(String(error)), {
141
145
  queue
142
146
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/redis-queue-manager.ts"],"sourcesContent":["/**\r\n * Redis Queue Manager\r\n *\r\n * Provides reliable queue operations with idempotency, acknowledgment protocol,\r\n * and message visibility timeout for Docker agent ↔ Redis communication.\r\n * Part of Task 3.4: Redis Queue Consistency & Recovery (Integration Standardization Sprint 3)\r\n *\r\n * Features:\r\n * - Enqueue with idempotency (prevents duplicate messages)\r\n * - Dequeue with acknowledgment protocol\r\n * - Message visibility timeout\r\n * - Queue monitoring (depth, age, throughput)\r\n * - Multiple queue support (task, result, coordination)\r\n * - Performance: <100ms per operation\r\n *\r\n * Usage:\r\n * const queueManager = new RedisQueueManager(redisClient);\r\n *\r\n * // Producer\r\n * await queueManager.enqueue('task-queue', {\r\n * taskId: 'task-001',\r\n * agentType: 'backend-developer',\r\n * payload: { ... }\r\n * });\r\n *\r\n * // Consumer\r\n * const message = await queueManager.dequeue('task-queue', { timeout: 30000 });\r\n * try {\r\n * await processTask(message.payload);\r\n * await queueManager.acknowledge(message.id);\r\n * } catch (error) {\r\n * await queueManager.reject(message.id, { retry: true });\r\n * }\r\n */\r\n\r\nimport { RedisClientType } from 'redis';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport { createLogger } from './logging.js';\r\nimport { createError, ErrorCode, isRetryableError } from './errors.js';\r\nimport { withRetry } from './retry.js';\r\nimport { MessageDeduplicator } from './message-deduplicator.js';\r\n\r\nconst logger = createLogger('redis-queue-manager');\r\n\r\n/**\r\n * Queue message\r\n */\r\nexport interface QueueMessage<T = any> {\r\n /** Unique message ID */\r\n id: string;\r\n /** Queue name */\r\n queue: string;\r\n /** Message payload */\r\n payload: T;\r\n /** Message creation timestamp */\r\n createdAt: Date;\r\n /** Message enqueue timestamp */\r\n enqueuedAt: Date;\r\n /** Message dequeue timestamp (if dequeued) */\r\n dequeuedAt?: Date;\r\n /** Number of delivery attempts */\r\n deliveryAttempts: number;\r\n /** Message visibility timeout (milliseconds) */\r\n visibilityTimeout?: number;\r\n /** Message metadata */\r\n metadata?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Enqueue options\r\n */\r\nexport interface EnqueueOptions {\r\n /** Enable deduplication (default: true) */\r\n deduplicate?: boolean;\r\n /** Message metadata */\r\n metadata?: Record<string, any>;\r\n /** Message visibility timeout in milliseconds (default: 30000) */\r\n visibilityTimeout?: number;\r\n}\r\n\r\n/**\r\n * Dequeue options\r\n */\r\nexport interface DequeueOptions {\r\n /** Maximum wait time in milliseconds (default: 0 - no wait) */\r\n timeout?: number;\r\n /** Message visibility timeout in milliseconds (default: 30000) */\r\n visibilityTimeout?: number;\r\n /** Number of messages to dequeue (default: 1) */\r\n count?: number;\r\n}\r\n\r\n/**\r\n * Reject options\r\n */\r\nexport interface RejectOptions {\r\n /** Retry message (re-enqueue) (default: false) */\r\n retry?: boolean;\r\n /** Error message */\r\n error?: string;\r\n /** Metadata to attach */\r\n metadata?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Queue statistics\r\n */\r\nexport interface QueueStats {\r\n /** Queue name */\r\n queue: string;\r\n /** Number of messages in queue */\r\n depth: number;\r\n /** Number of messages in processing (invisible) */\r\n inFlight: number;\r\n /** Age of oldest message in seconds */\r\n oldestMessageAge: number;\r\n /** Total messages enqueued */\r\n totalEnqueued: number;\r\n /** Total messages dequeued */\r\n totalDequeued: number;\r\n /** Total messages acknowledged */\r\n totalAcknowledged: number;\r\n /** Total messages rejected */\r\n totalRejected: number;\r\n /** Throughput (messages per second) */\r\n throughput: number;\r\n}\r\n\r\n/**\r\n * Default queue options\r\n */\r\nconst DEFAULT_ENQUEUE_OPTIONS: Required<EnqueueOptions> = {\r\n deduplicate: true,\r\n metadata: {},\r\n visibilityTimeout: 30000, // 30 seconds\r\n};\r\n\r\nconst DEFAULT_DEQUEUE_OPTIONS: Required<DequeueOptions> = {\r\n timeout: 0,\r\n visibilityTimeout: 30000, // 30 seconds\r\n count: 1,\r\n};\r\n\r\n/**\r\n * Redis Queue Manager\r\n *\r\n * Provides reliable queue operations with at-least-once delivery guarantees.\r\n */\r\nexport class RedisQueueManager {\r\n private redis: RedisClientType;\r\n private deduplicator: MessageDeduplicator;\r\n private stats: Map<string, {\r\n enqueued: number;\r\n dequeued: number;\r\n acknowledged: number;\r\n rejected: number;\r\n startTime: Date;\r\n }> = new Map();\r\n\r\n /**\r\n * Create a new RedisQueueManager instance\r\n *\r\n * @param redis - Redis client instance\r\n * @param deduplicator - Optional custom deduplicator instance\r\n */\r\n constructor(redis: RedisClientType, deduplicator?: MessageDeduplicator) {\r\n this.redis = redis;\r\n this.deduplicator = deduplicator || new MessageDeduplicator(redis);\r\n\r\n logger.info('RedisQueueManager initialized');\r\n }\r\n\r\n /**\r\n * Enqueue a message to a queue\r\n *\r\n * @param queue - Queue name\r\n * @param payload - Message payload\r\n * @param options - Enqueue options\r\n * @returns Message ID\r\n */\r\n public async enqueue<T = any>(\r\n queue: string,\r\n payload: T,\r\n options: EnqueueOptions = {}\r\n ): Promise<string> {\r\n const opts = { ...DEFAULT_ENQUEUE_OPTIONS, ...options };\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Check for duplicates if enabled\r\n if (opts.deduplicate) {\r\n const isDuplicate = await this.deduplicator.isDuplicate(payload);\r\n\r\n if (isDuplicate) {\r\n logger.warn('Duplicate message detected, skipping enqueue', {\r\n queue,\r\n payloadHash: this.deduplicator.createFingerprint(payload).substring(0, 16) + '...',\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_DUPLICATE_KEY,\r\n 'Duplicate message detected',\r\n { queue }\r\n );\r\n }\r\n }\r\n\r\n // Create message\r\n const message: QueueMessage<T> = {\r\n id: uuidv4(),\r\n queue,\r\n payload,\r\n createdAt: new Date(),\r\n enqueuedAt: new Date(),\r\n deliveryAttempts: 0,\r\n visibilityTimeout: opts.visibilityTimeout,\r\n metadata: opts.metadata,\r\n };\r\n\r\n // Push to queue (RPUSH for FIFO)\r\n await withRetry(\r\n async () => {\r\n const queueKey = this.getQueueKey(queue);\r\n await this.redis.rPush(queueKey, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n // Mark as processed in deduplicator if enabled\r\n if (opts.deduplicate) {\r\n await this.deduplicator.markProcessed(payload, {\r\n messageId: message.id,\r\n queue,\r\n });\r\n }\r\n\r\n // Update stats\r\n this.updateStats(queue, 'enqueued');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message enqueued', {\r\n queue,\r\n messageId: message.id,\r\n durationMs: duration,\r\n });\r\n\r\n // Validate performance requirement (<100ms)\r\n if (duration > 100) {\r\n logger.warn('Enqueue operation exceeded 100ms target', {\r\n queue,\r\n durationMs: duration,\r\n });\r\n }\r\n\r\n return message.id;\r\n } catch (error) {\r\n logger.error('Failed to enqueue message', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to enqueue message',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Dequeue a message from a queue\r\n *\r\n * @param queue - Queue name\r\n * @param options - Dequeue options\r\n * @returns Message or null if queue is empty\r\n */\r\n public async dequeue<T = any>(\r\n queue: string,\r\n options: DequeueOptions = {}\r\n ): Promise<QueueMessage<T> | null> {\r\n const opts = { ...DEFAULT_DEQUEUE_OPTIONS, ...options };\r\n const startTime = Date.now();\r\n\r\n try {\r\n const queueKey = this.getQueueKey(queue);\r\n const processingKey = this.getProcessingKey(queue);\r\n\r\n let messageData: string | null = null;\r\n\r\n // Use blocking pop if timeout specified\r\n if (opts.timeout > 0) {\r\n const result = await withRetry(\r\n async () => {\r\n // BLMOVE atomically moves from queue to processing set with timeout\r\n return await this.redis.blMove(\r\n queueKey,\r\n processingKey,\r\n 'LEFT',\r\n 'RIGHT',\r\n opts.timeout / 1000 // Convert to seconds\r\n );\r\n },\r\n { maxAttempts: 1 } // Don't retry blocking operations\r\n );\r\n\r\n messageData = result;\r\n } else {\r\n // Non-blocking pop\r\n messageData = await withRetry(\r\n async () => {\r\n return await this.redis.lMove(\r\n queueKey,\r\n processingKey,\r\n 'LEFT',\r\n 'RIGHT'\r\n );\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n }\r\n\r\n if (!messageData) {\r\n return null;\r\n }\r\n\r\n // Parse message\r\n const message = JSON.parse(messageData) as QueueMessage<T>;\r\n\r\n // Convert date strings back to Date objects\r\n message.createdAt = new Date(message.createdAt);\r\n message.enqueuedAt = new Date(message.enqueuedAt);\r\n message.dequeuedAt = new Date();\r\n message.deliveryAttempts++;\r\n\r\n // Store message with visibility timeout\r\n await this.storeInFlight(message, opts.visibilityTimeout);\r\n\r\n // Update stats\r\n this.updateStats(queue, 'dequeued');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message dequeued', {\r\n queue,\r\n messageId: message.id,\r\n deliveryAttempts: message.deliveryAttempts,\r\n durationMs: duration,\r\n });\r\n\r\n // Validate performance requirement (<100ms)\r\n if (duration > 100) {\r\n logger.warn('Dequeue operation exceeded 100ms target', {\r\n queue,\r\n durationMs: duration,\r\n });\r\n }\r\n\r\n return message;\r\n } catch (error) {\r\n logger.error('Failed to dequeue message', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to dequeue message',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Acknowledge successful message processing\r\n *\r\n * @param messageId - Message ID to acknowledge\r\n */\r\n public async acknowledge(messageId: string): Promise<void> {\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Remove from in-flight storage\r\n const message = await this.getInFlight(messageId);\r\n\r\n if (!message) {\r\n logger.warn('Message not found for acknowledgment', { messageId });\r\n return;\r\n }\r\n\r\n // Remove from processing set\r\n const processingKey = this.getProcessingKey(message.queue);\r\n await withRetry(\r\n async () => {\r\n await this.redis.lRem(processingKey, 1, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n // Remove from in-flight storage\r\n await this.removeInFlight(messageId);\r\n\r\n // Update stats\r\n this.updateStats(message.queue, 'acknowledged');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message acknowledged', {\r\n queue: message.queue,\r\n messageId,\r\n durationMs: duration,\r\n });\r\n } catch (error) {\r\n logger.error('Failed to acknowledge message', error instanceof Error ? error : new Error(String(error)), {\r\n messageId,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to acknowledge message',\r\n { messageId },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Reject message processing (with optional retry)\r\n *\r\n * @param messageId - Message ID to reject\r\n * @param options - Reject options\r\n */\r\n public async reject(messageId: string, options: RejectOptions = {}): Promise<void> {\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Get message from in-flight storage\r\n const message = await this.getInFlight(messageId);\r\n\r\n if (!message) {\r\n logger.warn('Message not found for rejection', { messageId });\r\n return;\r\n }\r\n\r\n // Remove from processing set\r\n const processingKey = this.getProcessingKey(message.queue);\r\n await withRetry(\r\n async () => {\r\n await this.redis.lRem(processingKey, 1, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n // Remove from in-flight storage\r\n await this.removeInFlight(messageId);\r\n\r\n if (options.retry) {\r\n // Re-enqueue message\r\n message.metadata = {\r\n ...message.metadata,\r\n ...options.metadata,\r\n rejectedAt: new Date().toISOString(),\r\n rejectionReason: options.error,\r\n };\r\n\r\n const queueKey = this.getQueueKey(message.queue);\r\n await withRetry(\r\n async () => {\r\n await this.redis.rPush(queueKey, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n logger.debug('Message rejected and re-enqueued', {\r\n queue: message.queue,\r\n messageId,\r\n deliveryAttempts: message.deliveryAttempts,\r\n });\r\n } else {\r\n logger.debug('Message rejected without retry', {\r\n queue: message.queue,\r\n messageId,\r\n });\r\n }\r\n\r\n // Update stats\r\n this.updateStats(message.queue, 'rejected');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message rejected', {\r\n queue: message.queue,\r\n messageId,\r\n retry: options.retry,\r\n durationMs: duration,\r\n });\r\n } catch (error) {\r\n logger.error('Failed to reject message', error instanceof Error ? error : new Error(String(error)), {\r\n messageId,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to reject message',\r\n { messageId },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Get queue statistics\r\n *\r\n * @param queue - Queue name\r\n * @returns Queue statistics\r\n */\r\n public async getStats(queue: string): Promise<QueueStats> {\r\n try {\r\n const queueKey = this.getQueueKey(queue);\r\n const processingKey = this.getProcessingKey(queue);\r\n\r\n // Get queue depth\r\n const depth = await this.redis.lLen(queueKey);\r\n\r\n // Get in-flight count\r\n const inFlight = await this.redis.lLen(processingKey);\r\n\r\n // Get oldest message age\r\n let oldestMessageAge = 0;\r\n const oldestMessage = await this.redis.lIndex(queueKey, 0);\r\n\r\n if (oldestMessage) {\r\n const message = JSON.parse(oldestMessage) as QueueMessage;\r\n const age = Date.now() - new Date(message.enqueuedAt).getTime();\r\n oldestMessageAge = Math.floor(age / 1000); // Convert to seconds\r\n }\r\n\r\n // Get stats from tracking\r\n const stats = this.stats.get(queue) || {\r\n enqueued: 0,\r\n dequeued: 0,\r\n acknowledged: 0,\r\n rejected: 0,\r\n startTime: new Date(),\r\n };\r\n\r\n // Calculate throughput (messages per second)\r\n const elapsed = (Date.now() - stats.startTime.getTime()) / 1000;\r\n const throughput = elapsed > 0 ? stats.dequeued / elapsed : 0;\r\n\r\n return {\r\n queue,\r\n depth,\r\n inFlight,\r\n oldestMessageAge,\r\n totalEnqueued: stats.enqueued,\r\n totalDequeued: stats.dequeued,\r\n totalAcknowledged: stats.acknowledged,\r\n totalRejected: stats.rejected,\r\n throughput,\r\n };\r\n } catch (error) {\r\n logger.error('Failed to get queue stats', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to get queue stats',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Purge all messages from a queue\r\n *\r\n * @param queue - Queue name\r\n * @returns Number of messages purged\r\n */\r\n public async purge(queue: string): Promise<number> {\r\n try {\r\n const queueKey = this.getQueueKey(queue);\r\n\r\n const count = await withRetry(\r\n async () => {\r\n const len = await this.redis.lLen(queueKey);\r\n await this.redis.del(queueKey);\r\n return len;\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n logger.info('Queue purged', {\r\n queue,\r\n messagesPurged: count,\r\n });\r\n\r\n return count;\r\n } catch (error) {\r\n logger.error('Failed to purge queue', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to purge queue',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Get all queue names\r\n *\r\n * @returns Array of queue names\r\n */\r\n public async getQueues(): Promise<string[]> {\r\n try {\r\n const pattern = 'queue:*';\r\n const keys = await this.redis.keys(pattern);\r\n\r\n const queues = keys\r\n .filter(key => !key.includes(':processing'))\r\n .map(key => key.replace('queue:', ''));\r\n\r\n return queues;\r\n } catch (error) {\r\n logger.error('Failed to get queues', error instanceof Error ? error : new Error(String(error)));\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to get queues',\r\n {},\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown queue manager (cleanup resources)\r\n */\r\n public shutdown(): void {\r\n this.deduplicator.shutdown();\r\n logger.info('RedisQueueManager shutdown');\r\n }\r\n\r\n /**\r\n * Get Redis key for queue\r\n */\r\n private getQueueKey(queue: string): string {\r\n return `queue:${queue}`;\r\n }\r\n\r\n /**\r\n * Get Redis key for processing set\r\n */\r\n private getProcessingKey(queue: string): string {\r\n return `queue:${queue}:processing`;\r\n }\r\n\r\n /**\r\n * Get Redis key for in-flight message storage\r\n */\r\n private getInFlightKey(messageId: string): string {\r\n return `inflight:${messageId}`;\r\n }\r\n\r\n /**\r\n * Store message in in-flight storage with TTL\r\n */\r\n private async storeInFlight<T = any>(\r\n message: QueueMessage<T>,\r\n visibilityTimeout: number\r\n ): Promise<void> {\r\n const key = this.getInFlightKey(message.id);\r\n\r\n await withRetry(\r\n async () => {\r\n await this.redis.set(\r\n key,\r\n JSON.stringify(message),\r\n { PX: visibilityTimeout }\r\n );\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n }\r\n\r\n /**\r\n * Get message from in-flight storage\r\n */\r\n private async getInFlight<T = any>(messageId: string): Promise<QueueMessage<T> | null> {\r\n const key = this.getInFlightKey(messageId);\r\n\r\n const data = await withRetry(\r\n async () => await this.redis.get(key),\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n if (!data) {\r\n return null;\r\n }\r\n\r\n const message = JSON.parse(data) as QueueMessage<T>;\r\n\r\n // Convert date strings back to Date objects\r\n message.createdAt = new Date(message.createdAt);\r\n message.enqueuedAt = new Date(message.enqueuedAt);\r\n if (message.dequeuedAt) {\r\n message.dequeuedAt = new Date(message.dequeuedAt);\r\n }\r\n\r\n return message;\r\n }\r\n\r\n /**\r\n * Remove message from in-flight storage\r\n */\r\n private async removeInFlight(messageId: string): Promise<void> {\r\n const key = this.getInFlightKey(messageId);\r\n\r\n await withRetry(\r\n async () => await this.redis.del(key),\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n }\r\n\r\n /**\r\n * Update queue statistics\r\n */\r\n private updateStats(queue: string, operation: 'enqueued' | 'dequeued' | 'acknowledged' | 'rejected'): void {\r\n let stats = this.stats.get(queue);\r\n\r\n if (!stats) {\r\n stats = {\r\n enqueued: 0,\r\n dequeued: 0,\r\n acknowledged: 0,\r\n rejected: 0,\r\n startTime: new Date(),\r\n };\r\n this.stats.set(queue, stats);\r\n }\r\n\r\n stats[operation]++;\r\n }\r\n}\r\n"],"names":["v4","uuidv4","createLogger","createError","ErrorCode","isRetryableError","withRetry","MessageDeduplicator","logger","DEFAULT_ENQUEUE_OPTIONS","deduplicate","metadata","visibilityTimeout","DEFAULT_DEQUEUE_OPTIONS","timeout","count","RedisQueueManager","redis","deduplicator","stats","Map","info","enqueue","queue","payload","options","opts","startTime","Date","now","isDuplicate","warn","payloadHash","createFingerprint","substring","DB_DUPLICATE_KEY","message","id","createdAt","enqueuedAt","deliveryAttempts","queueKey","getQueueKey","rPush","JSON","stringify","maxAttempts","shouldRetry","markProcessed","messageId","updateStats","duration","debug","durationMs","error","Error","String","DB_QUERY_FAILED","undefined","dequeue","processingKey","getProcessingKey","messageData","result","blMove","lMove","parse","dequeuedAt","storeInFlight","acknowledge","getInFlight","lRem","removeInFlight","reject","retry","rejectedAt","toISOString","rejectionReason","getStats","depth","lLen","inFlight","oldestMessageAge","oldestMessage","lIndex","age","getTime","Math","floor","get","enqueued","dequeued","acknowledged","rejected","elapsed","throughput","totalEnqueued","totalDequeued","totalAcknowledged","totalRejected","purge","len","del","messagesPurged","getQueues","pattern","keys","queues","filter","key","includes","map","replace","shutdown","getInFlightKey","set","PX","data","operation"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/lib/redis-queue-manager.ts"],"sourcesContent":["/**\r\n * Redis Queue Manager\r\n *\r\n * Provides reliable queue operations with idempotency, acknowledgment protocol,\r\n * and message visibility timeout for Docker agent ↔ Redis communication.\r\n * Part of Task 3.4: Redis Queue Consistency & Recovery (Integration Standardization Sprint 3)\r\n *\r\n * Features:\r\n * - Enqueue with idempotency (prevents duplicate messages)\r\n * - Dequeue with acknowledgment protocol\r\n * - Message visibility timeout\r\n * - Queue monitoring (depth, age, throughput)\r\n * - Multiple queue support (task, result, coordination)\r\n * - Performance: <100ms per operation\r\n *\r\n * Usage:\r\n * const queueManager = new RedisQueueManager(redisClient);\r\n *\r\n * // Producer\r\n * await queueManager.enqueue('task-queue', {\r\n * taskId: 'task-001',\r\n * agentType: 'backend-developer',\r\n * payload: { ... }\r\n * });\r\n *\r\n * // Consumer\r\n * const message = await queueManager.dequeue('task-queue', { timeout: 30000 });\r\n * try {\r\n * await processTask(message.payload);\r\n * await queueManager.acknowledge(message.id);\r\n * } catch (error) {\r\n * await queueManager.reject(message.id, { retry: true });\r\n * }\r\n */\r\n\r\nimport { RedisClientType } from 'redis';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport { createLogger } from './logging.js';\r\nimport { createError, ErrorCode, isRetryableError, StandardError } from './errors.js';\r\nimport { withRetry } from './retry.js';\r\nimport { MessageDeduplicator } from './message-deduplicator.js';\r\n\r\nconst logger = createLogger('redis-queue-manager');\r\n\r\n/**\r\n * Queue message\r\n */\r\nexport interface QueueMessage<T = any> {\r\n /** Unique message ID */\r\n id: string;\r\n /** Queue name */\r\n queue: string;\r\n /** Message payload */\r\n payload: T;\r\n /** Message creation timestamp */\r\n createdAt: Date;\r\n /** Message enqueue timestamp */\r\n enqueuedAt: Date;\r\n /** Message dequeue timestamp (if dequeued) */\r\n dequeuedAt?: Date;\r\n /** Number of delivery attempts */\r\n deliveryAttempts: number;\r\n /** Message visibility timeout (milliseconds) */\r\n visibilityTimeout?: number;\r\n /** Message metadata */\r\n metadata?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Enqueue options\r\n */\r\nexport interface EnqueueOptions {\r\n /** Enable deduplication (default: true) */\r\n deduplicate?: boolean;\r\n /** Message metadata */\r\n metadata?: Record<string, any>;\r\n /** Message visibility timeout in milliseconds (default: 30000) */\r\n visibilityTimeout?: number;\r\n}\r\n\r\n/**\r\n * Dequeue options\r\n */\r\nexport interface DequeueOptions {\r\n /** Maximum wait time in milliseconds (default: 0 - no wait) */\r\n timeout?: number;\r\n /** Message visibility timeout in milliseconds (default: 30000) */\r\n visibilityTimeout?: number;\r\n /** Number of messages to dequeue (default: 1) */\r\n count?: number;\r\n}\r\n\r\n/**\r\n * Reject options\r\n */\r\nexport interface RejectOptions {\r\n /** Retry message (re-enqueue) (default: false) */\r\n retry?: boolean;\r\n /** Error message */\r\n error?: string;\r\n /** Metadata to attach */\r\n metadata?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Queue statistics\r\n */\r\nexport interface QueueStats {\r\n /** Queue name */\r\n queue: string;\r\n /** Number of messages in queue */\r\n depth: number;\r\n /** Number of messages in processing (invisible) */\r\n inFlight: number;\r\n /** Age of oldest message in seconds */\r\n oldestMessageAge: number;\r\n /** Total messages enqueued */\r\n totalEnqueued: number;\r\n /** Total messages dequeued */\r\n totalDequeued: number;\r\n /** Total messages acknowledged */\r\n totalAcknowledged: number;\r\n /** Total messages rejected */\r\n totalRejected: number;\r\n /** Throughput (messages per second) */\r\n throughput: number;\r\n}\r\n\r\n/**\r\n * Default queue options\r\n */\r\nconst DEFAULT_ENQUEUE_OPTIONS: Required<EnqueueOptions> = {\r\n deduplicate: true,\r\n metadata: {},\r\n visibilityTimeout: 30000, // 30 seconds\r\n};\r\n\r\nconst DEFAULT_DEQUEUE_OPTIONS: Required<DequeueOptions> = {\r\n timeout: 0,\r\n visibilityTimeout: 30000, // 30 seconds\r\n count: 1,\r\n};\r\n\r\n/**\r\n * Redis Queue Manager\r\n *\r\n * Provides reliable queue operations with at-least-once delivery guarantees.\r\n */\r\nexport class RedisQueueManager {\r\n private redis: RedisClientType;\r\n private deduplicator: MessageDeduplicator;\r\n private stats: Map<string, {\r\n enqueued: number;\r\n dequeued: number;\r\n acknowledged: number;\r\n rejected: number;\r\n startTime: Date;\r\n }> = new Map();\r\n\r\n /**\r\n * Create a new RedisQueueManager instance\r\n *\r\n * @param redis - Redis client instance\r\n * @param deduplicator - Optional custom deduplicator instance\r\n */\r\n constructor(redis: RedisClientType, deduplicator?: MessageDeduplicator) {\r\n this.redis = redis;\r\n this.deduplicator = deduplicator || new MessageDeduplicator(redis);\r\n\r\n logger.info('RedisQueueManager initialized');\r\n }\r\n\r\n /**\r\n * Enqueue a message to a queue\r\n *\r\n * @param queue - Queue name\r\n * @param payload - Message payload\r\n * @param options - Enqueue options\r\n * @returns Message ID\r\n */\r\n public async enqueue<T = any>(\r\n queue: string,\r\n payload: T,\r\n options: EnqueueOptions = {}\r\n ): Promise<string> {\r\n const opts = { ...DEFAULT_ENQUEUE_OPTIONS, ...options };\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Check for duplicates if enabled\r\n if (opts.deduplicate) {\r\n const isDuplicate = await this.deduplicator.isDuplicate(payload);\r\n\r\n if (isDuplicate) {\r\n logger.warn('Duplicate message detected, skipping enqueue', {\r\n queue,\r\n payloadHash: this.deduplicator.createFingerprint(payload).substring(0, 16) + '...',\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_DUPLICATE_KEY,\r\n 'Duplicate message detected',\r\n { queue }\r\n );\r\n }\r\n }\r\n\r\n // Create message\r\n const message: QueueMessage<T> = {\r\n id: uuidv4(),\r\n queue,\r\n payload,\r\n createdAt: new Date(),\r\n enqueuedAt: new Date(),\r\n deliveryAttempts: 0,\r\n visibilityTimeout: opts.visibilityTimeout,\r\n metadata: opts.metadata,\r\n };\r\n\r\n // Push to queue (RPUSH for FIFO)\r\n await withRetry(\r\n async () => {\r\n const queueKey = this.getQueueKey(queue);\r\n await this.redis.rPush(queueKey, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n // Mark as processed in deduplicator if enabled\r\n if (opts.deduplicate) {\r\n await this.deduplicator.markProcessed(payload, {\r\n messageId: message.id,\r\n queue,\r\n });\r\n }\r\n\r\n // Update stats\r\n this.updateStats(queue, 'enqueued');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message enqueued', {\r\n queue,\r\n messageId: message.id,\r\n durationMs: duration,\r\n });\r\n\r\n // Validate performance requirement (<100ms)\r\n if (duration > 100) {\r\n logger.warn('Enqueue operation exceeded 100ms target', {\r\n queue,\r\n durationMs: duration,\r\n });\r\n }\r\n\r\n return message.id;\r\n } catch (error) {\r\n // Re-throw duplicate errors without wrapping\r\n if (error instanceof StandardError && error.code === ErrorCode.DB_DUPLICATE_KEY) {\r\n throw error;\r\n }\r\n\r\n logger.error('Failed to enqueue message', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to enqueue message',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Dequeue a message from a queue\r\n *\r\n * @param queue - Queue name\r\n * @param options - Dequeue options\r\n * @returns Message or null if queue is empty\r\n */\r\n public async dequeue<T = any>(\r\n queue: string,\r\n options: DequeueOptions = {}\r\n ): Promise<QueueMessage<T> | null> {\r\n const opts = { ...DEFAULT_DEQUEUE_OPTIONS, ...options };\r\n const startTime = Date.now();\r\n\r\n try {\r\n const queueKey = this.getQueueKey(queue);\r\n const processingKey = this.getProcessingKey(queue);\r\n\r\n let messageData: string | null = null;\r\n\r\n // Use blocking pop if timeout specified\r\n if (opts.timeout > 0) {\r\n const result = await withRetry(\r\n async () => {\r\n // BLMOVE atomically moves from queue to processing set with timeout\r\n return await this.redis.blMove(\r\n queueKey,\r\n processingKey,\r\n 'LEFT',\r\n 'RIGHT',\r\n opts.timeout / 1000 // Convert to seconds\r\n );\r\n },\r\n { maxAttempts: 1 } // Don't retry blocking operations\r\n );\r\n\r\n messageData = result;\r\n } else {\r\n // Non-blocking pop\r\n messageData = await withRetry(\r\n async () => {\r\n return await this.redis.lMove(\r\n queueKey,\r\n processingKey,\r\n 'LEFT',\r\n 'RIGHT'\r\n );\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n }\r\n\r\n if (!messageData) {\r\n return null;\r\n }\r\n\r\n // Parse message\r\n const message = JSON.parse(messageData) as QueueMessage<T>;\r\n\r\n // Convert date strings back to Date objects\r\n message.createdAt = new Date(message.createdAt);\r\n message.enqueuedAt = new Date(message.enqueuedAt);\r\n message.dequeuedAt = new Date();\r\n message.deliveryAttempts++;\r\n\r\n // Store message with visibility timeout\r\n await this.storeInFlight(message, opts.visibilityTimeout);\r\n\r\n // Update stats\r\n this.updateStats(queue, 'dequeued');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message dequeued', {\r\n queue,\r\n messageId: message.id,\r\n deliveryAttempts: message.deliveryAttempts,\r\n durationMs: duration,\r\n });\r\n\r\n // Validate performance requirement (<100ms)\r\n if (duration > 100) {\r\n logger.warn('Dequeue operation exceeded 100ms target', {\r\n queue,\r\n durationMs: duration,\r\n });\r\n }\r\n\r\n return message;\r\n } catch (error) {\r\n logger.error('Failed to dequeue message', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to dequeue message',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Acknowledge successful message processing\r\n *\r\n * @param messageId - Message ID to acknowledge\r\n */\r\n public async acknowledge(messageId: string): Promise<void> {\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Remove from in-flight storage\r\n const message = await this.getInFlight(messageId);\r\n\r\n if (!message) {\r\n logger.warn('Message not found for acknowledgment', { messageId });\r\n return;\r\n }\r\n\r\n // Remove from processing set\r\n const processingKey = this.getProcessingKey(message.queue);\r\n await withRetry(\r\n async () => {\r\n await this.redis.lRem(processingKey, 1, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n // Remove from in-flight storage\r\n await this.removeInFlight(messageId);\r\n\r\n // Update stats\r\n this.updateStats(message.queue, 'acknowledged');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message acknowledged', {\r\n queue: message.queue,\r\n messageId,\r\n durationMs: duration,\r\n });\r\n } catch (error) {\r\n logger.error('Failed to acknowledge message', error instanceof Error ? error : new Error(String(error)), {\r\n messageId,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to acknowledge message',\r\n { messageId },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Reject message processing (with optional retry)\r\n *\r\n * @param messageId - Message ID to reject\r\n * @param options - Reject options\r\n */\r\n public async reject(messageId: string, options: RejectOptions = {}): Promise<void> {\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Get message from in-flight storage\r\n const message = await this.getInFlight(messageId);\r\n\r\n if (!message) {\r\n logger.warn('Message not found for rejection', { messageId });\r\n return;\r\n }\r\n\r\n // Remove from processing set\r\n const processingKey = this.getProcessingKey(message.queue);\r\n await withRetry(\r\n async () => {\r\n await this.redis.lRem(processingKey, 1, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n // Remove from in-flight storage\r\n await this.removeInFlight(messageId);\r\n\r\n if (options.retry) {\r\n // Re-enqueue message\r\n message.metadata = {\r\n ...message.metadata,\r\n ...options.metadata,\r\n rejectedAt: new Date().toISOString(),\r\n rejectionReason: options.error,\r\n };\r\n\r\n const queueKey = this.getQueueKey(message.queue);\r\n await withRetry(\r\n async () => {\r\n await this.redis.rPush(queueKey, JSON.stringify(message));\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n logger.debug('Message rejected and re-enqueued', {\r\n queue: message.queue,\r\n messageId,\r\n deliveryAttempts: message.deliveryAttempts,\r\n });\r\n } else {\r\n logger.debug('Message rejected without retry', {\r\n queue: message.queue,\r\n messageId,\r\n });\r\n }\r\n\r\n // Update stats\r\n this.updateStats(message.queue, 'rejected');\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n logger.debug('Message rejected', {\r\n queue: message.queue,\r\n messageId,\r\n retry: options.retry,\r\n durationMs: duration,\r\n });\r\n } catch (error) {\r\n logger.error('Failed to reject message', error instanceof Error ? error : new Error(String(error)), {\r\n messageId,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to reject message',\r\n { messageId },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Get queue statistics\r\n *\r\n * @param queue - Queue name\r\n * @returns Queue statistics\r\n */\r\n public async getStats(queue: string): Promise<QueueStats> {\r\n try {\r\n const queueKey = this.getQueueKey(queue);\r\n const processingKey = this.getProcessingKey(queue);\r\n\r\n // Get queue depth\r\n const depth = await this.redis.lLen(queueKey);\r\n\r\n // Get in-flight count\r\n const inFlight = await this.redis.lLen(processingKey);\r\n\r\n // Get oldest message age\r\n let oldestMessageAge = 0;\r\n const oldestMessage = await this.redis.lIndex(queueKey, 0);\r\n\r\n if (oldestMessage) {\r\n const message = JSON.parse(oldestMessage) as QueueMessage;\r\n const age = Date.now() - new Date(message.enqueuedAt).getTime();\r\n oldestMessageAge = Math.floor(age / 1000); // Convert to seconds\r\n }\r\n\r\n // Get stats from tracking\r\n const stats = this.stats.get(queue) || {\r\n enqueued: 0,\r\n dequeued: 0,\r\n acknowledged: 0,\r\n rejected: 0,\r\n startTime: new Date(),\r\n };\r\n\r\n // Calculate throughput (messages per second)\r\n const elapsed = (Date.now() - stats.startTime.getTime()) / 1000;\r\n const throughput = elapsed > 0 ? stats.dequeued / elapsed : 0;\r\n\r\n return {\r\n queue,\r\n depth,\r\n inFlight,\r\n oldestMessageAge,\r\n totalEnqueued: stats.enqueued,\r\n totalDequeued: stats.dequeued,\r\n totalAcknowledged: stats.acknowledged,\r\n totalRejected: stats.rejected,\r\n throughput,\r\n };\r\n } catch (error) {\r\n logger.error('Failed to get queue stats', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to get queue stats',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Purge all messages from a queue\r\n *\r\n * @param queue - Queue name\r\n * @returns Number of messages purged\r\n */\r\n public async purge(queue: string): Promise<number> {\r\n try {\r\n const queueKey = this.getQueueKey(queue);\r\n\r\n const count = await withRetry(\r\n async () => {\r\n const len = await this.redis.lLen(queueKey);\r\n await this.redis.del(queueKey);\r\n return len;\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n logger.info('Queue purged', {\r\n queue,\r\n messagesPurged: count,\r\n });\r\n\r\n return count;\r\n } catch (error) {\r\n logger.error('Failed to purge queue', error instanceof Error ? error : new Error(String(error)), {\r\n queue,\r\n });\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to purge queue',\r\n { queue },\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Get all queue names\r\n *\r\n * @returns Array of queue names\r\n */\r\n public async getQueues(): Promise<string[]> {\r\n try {\r\n const pattern = 'queue:*';\r\n const keys = await this.redis.keys(pattern);\r\n\r\n const queues = keys\r\n .filter(key => !key.includes(':processing'))\r\n .map(key => key.replace('queue:', ''));\r\n\r\n return queues;\r\n } catch (error) {\r\n logger.error('Failed to get queues', error instanceof Error ? error : new Error(String(error)));\r\n\r\n throw createError(\r\n ErrorCode.DB_QUERY_FAILED,\r\n 'Failed to get queues',\r\n {},\r\n error instanceof Error ? error : undefined\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown queue manager (cleanup resources)\r\n */\r\n public shutdown(): void {\r\n this.deduplicator.shutdown();\r\n logger.info('RedisQueueManager shutdown');\r\n }\r\n\r\n /**\r\n * Get Redis key for queue\r\n */\r\n private getQueueKey(queue: string): string {\r\n return `queue:${queue}`;\r\n }\r\n\r\n /**\r\n * Get Redis key for processing set\r\n */\r\n private getProcessingKey(queue: string): string {\r\n return `queue:${queue}:processing`;\r\n }\r\n\r\n /**\r\n * Get Redis key for in-flight message storage\r\n */\r\n private getInFlightKey(messageId: string): string {\r\n return `inflight:${messageId}`;\r\n }\r\n\r\n /**\r\n * Store message in in-flight storage with TTL\r\n */\r\n private async storeInFlight<T = any>(\r\n message: QueueMessage<T>,\r\n visibilityTimeout: number\r\n ): Promise<void> {\r\n const key = this.getInFlightKey(message.id);\r\n\r\n await withRetry(\r\n async () => {\r\n await this.redis.set(\r\n key,\r\n JSON.stringify(message),\r\n { PX: visibilityTimeout }\r\n );\r\n },\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n }\r\n\r\n /**\r\n * Get message from in-flight storage\r\n */\r\n private async getInFlight<T = any>(messageId: string): Promise<QueueMessage<T> | null> {\r\n const key = this.getInFlightKey(messageId);\r\n\r\n const data = await withRetry(\r\n async () => await this.redis.get(key),\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n\r\n if (!data) {\r\n return null;\r\n }\r\n\r\n const message = JSON.parse(data) as QueueMessage<T>;\r\n\r\n // Convert date strings back to Date objects\r\n message.createdAt = new Date(message.createdAt);\r\n message.enqueuedAt = new Date(message.enqueuedAt);\r\n if (message.dequeuedAt) {\r\n message.dequeuedAt = new Date(message.dequeuedAt);\r\n }\r\n\r\n return message;\r\n }\r\n\r\n /**\r\n * Remove message from in-flight storage\r\n */\r\n private async removeInFlight(messageId: string): Promise<void> {\r\n const key = this.getInFlightKey(messageId);\r\n\r\n await withRetry(\r\n async () => await this.redis.del(key),\r\n { maxAttempts: 3, shouldRetry: isRetryableError }\r\n );\r\n }\r\n\r\n /**\r\n * Update queue statistics\r\n */\r\n private updateStats(queue: string, operation: 'enqueued' | 'dequeued' | 'acknowledged' | 'rejected'): void {\r\n let stats = this.stats.get(queue);\r\n\r\n if (!stats) {\r\n stats = {\r\n enqueued: 0,\r\n dequeued: 0,\r\n acknowledged: 0,\r\n rejected: 0,\r\n startTime: new Date(),\r\n };\r\n this.stats.set(queue, stats);\r\n }\r\n\r\n stats[operation]++;\r\n }\r\n}\r\n"],"names":["v4","uuidv4","createLogger","createError","ErrorCode","isRetryableError","StandardError","withRetry","MessageDeduplicator","logger","DEFAULT_ENQUEUE_OPTIONS","deduplicate","metadata","visibilityTimeout","DEFAULT_DEQUEUE_OPTIONS","timeout","count","RedisQueueManager","redis","deduplicator","stats","Map","info","enqueue","queue","payload","options","opts","startTime","Date","now","isDuplicate","warn","payloadHash","createFingerprint","substring","DB_DUPLICATE_KEY","message","id","createdAt","enqueuedAt","deliveryAttempts","queueKey","getQueueKey","rPush","JSON","stringify","maxAttempts","shouldRetry","markProcessed","messageId","updateStats","duration","debug","durationMs","error","code","Error","String","DB_QUERY_FAILED","undefined","dequeue","processingKey","getProcessingKey","messageData","result","blMove","lMove","parse","dequeuedAt","storeInFlight","acknowledge","getInFlight","lRem","removeInFlight","reject","retry","rejectedAt","toISOString","rejectionReason","getStats","depth","lLen","inFlight","oldestMessageAge","oldestMessage","lIndex","age","getTime","Math","floor","get","enqueued","dequeued","acknowledged","rejected","elapsed","throughput","totalEnqueued","totalDequeued","totalAcknowledged","totalRejected","purge","len","del","messagesPurged","getQueues","pattern","keys","queues","filter","key","includes","map","replace","shutdown","getInFlightKey","set","PX","data","operation"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCC,GAGD,SAASA,MAAMC,MAAM,QAAQ,OAAO;AACpC,SAASC,YAAY,QAAQ,eAAe;AAC5C,SAASC,WAAW,EAAEC,SAAS,EAAEC,gBAAgB,EAAEC,aAAa,QAAQ,cAAc;AACtF,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,mBAAmB,QAAQ,4BAA4B;AAEhE,MAAMC,SAASP,aAAa;AAsF5B;;CAEC,GACD,MAAMQ,0BAAoD;IACxDC,aAAa;IACbC,UAAU,CAAC;IACXC,mBAAmB;AACrB;AAEA,MAAMC,0BAAoD;IACxDC,SAAS;IACTF,mBAAmB;IACnBG,OAAO;AACT;AAEA;;;;CAIC,GACD,OAAO,MAAMC;IACHC,MAAuB;IACvBC,aAAkC;IAClCC,QAMH,IAAIC,MAAM;IAEf;;;;;GAKC,GACD,YAAYH,KAAsB,EAAEC,YAAkC,CAAE;QACtE,IAAI,CAACD,KAAK,GAAGA;QACb,IAAI,CAACC,YAAY,GAAGA,gBAAgB,IAAIX,oBAAoBU;QAE5DT,OAAOa,IAAI,CAAC;IACd;IAEA;;;;;;;GAOC,GACD,MAAaC,QACXC,KAAa,EACbC,OAAU,EACVC,UAA0B,CAAC,CAAC,EACX;QACjB,MAAMC,OAAO;YAAE,GAAGjB,uBAAuB;YAAE,GAAGgB,OAAO;QAAC;QACtD,MAAME,YAAYC,KAAKC,GAAG;QAE1B,IAAI;YACF,kCAAkC;YAClC,IAAIH,KAAKhB,WAAW,EAAE;gBACpB,MAAMoB,cAAc,MAAM,IAAI,CAACZ,YAAY,CAACY,WAAW,CAACN;gBAExD,IAAIM,aAAa;oBACftB,OAAOuB,IAAI,CAAC,gDAAgD;wBAC1DR;wBACAS,aAAa,IAAI,CAACd,YAAY,CAACe,iBAAiB,CAACT,SAASU,SAAS,CAAC,GAAG,MAAM;oBAC/E;oBAEA,MAAMhC,YACJC,UAAUgC,gBAAgB,EAC1B,8BACA;wBAAEZ;oBAAM;gBAEZ;YACF;YAEA,iBAAiB;YACjB,MAAMa,UAA2B;gBAC/BC,IAAIrC;gBACJuB;gBACAC;gBACAc,WAAW,IAAIV;gBACfW,YAAY,IAAIX;gBAChBY,kBAAkB;gBAClB5B,mBAAmBc,KAAKd,iBAAiB;gBACzCD,UAAUe,KAAKf,QAAQ;YACzB;YAEA,iCAAiC;YACjC,MAAML,UACJ;gBACE,MAAMmC,WAAW,IAAI,CAACC,WAAW,CAACnB;gBAClC,MAAM,IAAI,CAACN,KAAK,CAAC0B,KAAK,CAACF,UAAUG,KAAKC,SAAS,CAACT;YAClD,GACA;gBAAEU,aAAa;gBAAGC,aAAa3C;YAAiB;YAGlD,+CAA+C;YAC/C,IAAIsB,KAAKhB,WAAW,EAAE;gBACpB,MAAM,IAAI,CAACQ,YAAY,CAAC8B,aAAa,CAACxB,SAAS;oBAC7CyB,WAAWb,QAAQC,EAAE;oBACrBd;gBACF;YACF;YAEA,eAAe;YACf,IAAI,CAAC2B,WAAW,CAAC3B,OAAO;YAExB,MAAM4B,WAAWvB,KAAKC,GAAG,KAAKF;YAE9BnB,OAAO4C,KAAK,CAAC,oBAAoB;gBAC/B7B;gBACA0B,WAAWb,QAAQC,EAAE;gBACrBgB,YAAYF;YACd;YAEA,4CAA4C;YAC5C,IAAIA,WAAW,KAAK;gBAClB3C,OAAOuB,IAAI,CAAC,2CAA2C;oBACrDR;oBACA8B,YAAYF;gBACd;YACF;YAEA,OAAOf,QAAQC,EAAE;QACnB,EAAE,OAAOiB,OAAO;YACd,6CAA6C;YAC7C,IAAIA,iBAAiBjD,iBAAiBiD,MAAMC,IAAI,KAAKpD,UAAUgC,gBAAgB,EAAE;gBAC/E,MAAMmB;YACR;YAEA9C,OAAO8C,KAAK,CAAC,6BAA6BA,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH,SAAS;gBACnG/B;YACF;YAEA,MAAMrB,YACJC,UAAUuD,eAAe,EACzB,6BACA;gBAAEnC;YAAM,GACR+B,iBAAiBE,QAAQF,QAAQK;QAErC;IACF;IAEA;;;;;;GAMC,GACD,MAAaC,QACXrC,KAAa,EACbE,UAA0B,CAAC,CAAC,EACK;QACjC,MAAMC,OAAO;YAAE,GAAGb,uBAAuB;YAAE,GAAGY,OAAO;QAAC;QACtD,MAAME,YAAYC,KAAKC,GAAG;QAE1B,IAAI;YACF,MAAMY,WAAW,IAAI,CAACC,WAAW,CAACnB;YAClC,MAAMsC,gBAAgB,IAAI,CAACC,gBAAgB,CAACvC;YAE5C,IAAIwC,cAA6B;YAEjC,wCAAwC;YACxC,IAAIrC,KAAKZ,OAAO,GAAG,GAAG;gBACpB,MAAMkD,SAAS,MAAM1D,UACnB;oBACE,oEAAoE;oBACpE,OAAO,MAAM,IAAI,CAACW,KAAK,CAACgD,MAAM,CAC5BxB,UACAoB,eACA,QACA,SACAnC,KAAKZ,OAAO,GAAG,KAAK,qBAAqB;;gBAE7C,GACA;oBAAEgC,aAAa;gBAAE,EAAE,kCAAkC;;gBAGvDiB,cAAcC;YAChB,OAAO;gBACL,mBAAmB;gBACnBD,cAAc,MAAMzD,UAClB;oBACE,OAAO,MAAM,IAAI,CAACW,KAAK,CAACiD,KAAK,CAC3BzB,UACAoB,eACA,QACA;gBAEJ,GACA;oBAAEf,aAAa;oBAAGC,aAAa3C;gBAAiB;YAEpD;YAEA,IAAI,CAAC2D,aAAa;gBAChB,OAAO;YACT;YAEA,gBAAgB;YAChB,MAAM3B,UAAUQ,KAAKuB,KAAK,CAACJ;YAE3B,4CAA4C;YAC5C3B,QAAQE,SAAS,GAAG,IAAIV,KAAKQ,QAAQE,SAAS;YAC9CF,QAAQG,UAAU,GAAG,IAAIX,KAAKQ,QAAQG,UAAU;YAChDH,QAAQgC,UAAU,GAAG,IAAIxC;YACzBQ,QAAQI,gBAAgB;YAExB,wCAAwC;YACxC,MAAM,IAAI,CAAC6B,aAAa,CAACjC,SAASV,KAAKd,iBAAiB;YAExD,eAAe;YACf,IAAI,CAACsC,WAAW,CAAC3B,OAAO;YAExB,MAAM4B,WAAWvB,KAAKC,GAAG,KAAKF;YAE9BnB,OAAO4C,KAAK,CAAC,oBAAoB;gBAC/B7B;gBACA0B,WAAWb,QAAQC,EAAE;gBACrBG,kBAAkBJ,QAAQI,gBAAgB;gBAC1Ca,YAAYF;YACd;YAEA,4CAA4C;YAC5C,IAAIA,WAAW,KAAK;gBAClB3C,OAAOuB,IAAI,CAAC,2CAA2C;oBACrDR;oBACA8B,YAAYF;gBACd;YACF;YAEA,OAAOf;QACT,EAAE,OAAOkB,OAAO;YACd9C,OAAO8C,KAAK,CAAC,6BAA6BA,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH,SAAS;gBACnG/B;YACF;YAEA,MAAMrB,YACJC,UAAUuD,eAAe,EACzB,6BACA;gBAAEnC;YAAM,GACR+B,iBAAiBE,QAAQF,QAAQK;QAErC;IACF;IAEA;;;;GAIC,GACD,MAAaW,YAAYrB,SAAiB,EAAiB;QACzD,MAAMtB,YAAYC,KAAKC,GAAG;QAE1B,IAAI;YACF,gCAAgC;YAChC,MAAMO,UAAU,MAAM,IAAI,CAACmC,WAAW,CAACtB;YAEvC,IAAI,CAACb,SAAS;gBACZ5B,OAAOuB,IAAI,CAAC,wCAAwC;oBAAEkB;gBAAU;gBAChE;YACF;YAEA,6BAA6B;YAC7B,MAAMY,gBAAgB,IAAI,CAACC,gBAAgB,CAAC1B,QAAQb,KAAK;YACzD,MAAMjB,UACJ;gBACE,MAAM,IAAI,CAACW,KAAK,CAACuD,IAAI,CAACX,eAAe,GAAGjB,KAAKC,SAAS,CAACT;YACzD,GACA;gBAAEU,aAAa;gBAAGC,aAAa3C;YAAiB;YAGlD,gCAAgC;YAChC,MAAM,IAAI,CAACqE,cAAc,CAACxB;YAE1B,eAAe;YACf,IAAI,CAACC,WAAW,CAACd,QAAQb,KAAK,EAAE;YAEhC,MAAM4B,WAAWvB,KAAKC,GAAG,KAAKF;YAE9BnB,OAAO4C,KAAK,CAAC,wBAAwB;gBACnC7B,OAAOa,QAAQb,KAAK;gBACpB0B;gBACAI,YAAYF;YACd;QACF,EAAE,OAAOG,OAAO;YACd9C,OAAO8C,KAAK,CAAC,iCAAiCA,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH,SAAS;gBACvGL;YACF;YAEA,MAAM/C,YACJC,UAAUuD,eAAe,EACzB,iCACA;gBAAET;YAAU,GACZK,iBAAiBE,QAAQF,QAAQK;QAErC;IACF;IAEA;;;;;GAKC,GACD,MAAae,OAAOzB,SAAiB,EAAExB,UAAyB,CAAC,CAAC,EAAiB;QACjF,MAAME,YAAYC,KAAKC,GAAG;QAE1B,IAAI;YACF,qCAAqC;YACrC,MAAMO,UAAU,MAAM,IAAI,CAACmC,WAAW,CAACtB;YAEvC,IAAI,CAACb,SAAS;gBACZ5B,OAAOuB,IAAI,CAAC,mCAAmC;oBAAEkB;gBAAU;gBAC3D;YACF;YAEA,6BAA6B;YAC7B,MAAMY,gBAAgB,IAAI,CAACC,gBAAgB,CAAC1B,QAAQb,KAAK;YACzD,MAAMjB,UACJ;gBACE,MAAM,IAAI,CAACW,KAAK,CAACuD,IAAI,CAACX,eAAe,GAAGjB,KAAKC,SAAS,CAACT;YACzD,GACA;gBAAEU,aAAa;gBAAGC,aAAa3C;YAAiB;YAGlD,gCAAgC;YAChC,MAAM,IAAI,CAACqE,cAAc,CAACxB;YAE1B,IAAIxB,QAAQkD,KAAK,EAAE;gBACjB,qBAAqB;gBACrBvC,QAAQzB,QAAQ,GAAG;oBACjB,GAAGyB,QAAQzB,QAAQ;oBACnB,GAAGc,QAAQd,QAAQ;oBACnBiE,YAAY,IAAIhD,OAAOiD,WAAW;oBAClCC,iBAAiBrD,QAAQ6B,KAAK;gBAChC;gBAEA,MAAMb,WAAW,IAAI,CAACC,WAAW,CAACN,QAAQb,KAAK;gBAC/C,MAAMjB,UACJ;oBACE,MAAM,IAAI,CAACW,KAAK,CAAC0B,KAAK,CAACF,UAAUG,KAAKC,SAAS,CAACT;gBAClD,GACA;oBAAEU,aAAa;oBAAGC,aAAa3C;gBAAiB;gBAGlDI,OAAO4C,KAAK,CAAC,oCAAoC;oBAC/C7B,OAAOa,QAAQb,KAAK;oBACpB0B;oBACAT,kBAAkBJ,QAAQI,gBAAgB;gBAC5C;YACF,OAAO;gBACLhC,OAAO4C,KAAK,CAAC,kCAAkC;oBAC7C7B,OAAOa,QAAQb,KAAK;oBACpB0B;gBACF;YACF;YAEA,eAAe;YACf,IAAI,CAACC,WAAW,CAACd,QAAQb,KAAK,EAAE;YAEhC,MAAM4B,WAAWvB,KAAKC,GAAG,KAAKF;YAE9BnB,OAAO4C,KAAK,CAAC,oBAAoB;gBAC/B7B,OAAOa,QAAQb,KAAK;gBACpB0B;gBACA0B,OAAOlD,QAAQkD,KAAK;gBACpBtB,YAAYF;YACd;QACF,EAAE,OAAOG,OAAO;YACd9C,OAAO8C,KAAK,CAAC,4BAA4BA,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH,SAAS;gBAClGL;YACF;YAEA,MAAM/C,YACJC,UAAUuD,eAAe,EACzB,4BACA;gBAAET;YAAU,GACZK,iBAAiBE,QAAQF,QAAQK;QAErC;IACF;IAEA;;;;;GAKC,GACD,MAAaoB,SAASxD,KAAa,EAAuB;QACxD,IAAI;YACF,MAAMkB,WAAW,IAAI,CAACC,WAAW,CAACnB;YAClC,MAAMsC,gBAAgB,IAAI,CAACC,gBAAgB,CAACvC;YAE5C,kBAAkB;YAClB,MAAMyD,QAAQ,MAAM,IAAI,CAAC/D,KAAK,CAACgE,IAAI,CAACxC;YAEpC,sBAAsB;YACtB,MAAMyC,WAAW,MAAM,IAAI,CAACjE,KAAK,CAACgE,IAAI,CAACpB;YAEvC,yBAAyB;YACzB,IAAIsB,mBAAmB;YACvB,MAAMC,gBAAgB,MAAM,IAAI,CAACnE,KAAK,CAACoE,MAAM,CAAC5C,UAAU;YAExD,IAAI2C,eAAe;gBACjB,MAAMhD,UAAUQ,KAAKuB,KAAK,CAACiB;gBAC3B,MAAME,MAAM1D,KAAKC,GAAG,KAAK,IAAID,KAAKQ,QAAQG,UAAU,EAAEgD,OAAO;gBAC7DJ,mBAAmBK,KAAKC,KAAK,CAACH,MAAM,OAAO,qBAAqB;YAClE;YAEA,0BAA0B;YAC1B,MAAMnE,QAAQ,IAAI,CAACA,KAAK,CAACuE,GAAG,CAACnE,UAAU;gBACrCoE,UAAU;gBACVC,UAAU;gBACVC,cAAc;gBACdC,UAAU;gBACVnE,WAAW,IAAIC;YACjB;YAEA,6CAA6C;YAC7C,MAAMmE,UAAU,AAACnE,CAAAA,KAAKC,GAAG,KAAKV,MAAMQ,SAAS,CAAC4D,OAAO,EAAC,IAAK;YAC3D,MAAMS,aAAaD,UAAU,IAAI5E,MAAMyE,QAAQ,GAAGG,UAAU;YAE5D,OAAO;gBACLxE;gBACAyD;gBACAE;gBACAC;gBACAc,eAAe9E,MAAMwE,QAAQ;gBAC7BO,eAAe/E,MAAMyE,QAAQ;gBAC7BO,mBAAmBhF,MAAM0E,YAAY;gBACrCO,eAAejF,MAAM2E,QAAQ;gBAC7BE;YACF;QACF,EAAE,OAAO1C,OAAO;YACd9C,OAAO8C,KAAK,CAAC,6BAA6BA,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH,SAAS;gBACnG/B;YACF;YAEA,MAAMrB,YACJC,UAAUuD,eAAe,EACzB,6BACA;gBAAEnC;YAAM,GACR+B,iBAAiBE,QAAQF,QAAQK;QAErC;IACF;IAEA;;;;;GAKC,GACD,MAAa0C,MAAM9E,KAAa,EAAmB;QACjD,IAAI;YACF,MAAMkB,WAAW,IAAI,CAACC,WAAW,CAACnB;YAElC,MAAMR,QAAQ,MAAMT,UAClB;gBACE,MAAMgG,MAAM,MAAM,IAAI,CAACrF,KAAK,CAACgE,IAAI,CAACxC;gBAClC,MAAM,IAAI,CAACxB,KAAK,CAACsF,GAAG,CAAC9D;gBACrB,OAAO6D;YACT,GACA;gBAAExD,aAAa;gBAAGC,aAAa3C;YAAiB;YAGlDI,OAAOa,IAAI,CAAC,gBAAgB;gBAC1BE;gBACAiF,gBAAgBzF;YAClB;YAEA,OAAOA;QACT,EAAE,OAAOuC,OAAO;YACd9C,OAAO8C,KAAK,CAAC,yBAAyBA,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH,SAAS;gBAC/F/B;YACF;YAEA,MAAMrB,YACJC,UAAUuD,eAAe,EACzB,yBACA;gBAAEnC;YAAM,GACR+B,iBAAiBE,QAAQF,QAAQK;QAErC;IACF;IAEA;;;;GAIC,GACD,MAAa8C,YAA+B;QAC1C,IAAI;YACF,MAAMC,UAAU;YAChB,MAAMC,OAAO,MAAM,IAAI,CAAC1F,KAAK,CAAC0F,IAAI,CAACD;YAEnC,MAAME,SAASD,KACZE,MAAM,CAACC,CAAAA,MAAO,CAACA,IAAIC,QAAQ,CAAC,gBAC5BC,GAAG,CAACF,CAAAA,MAAOA,IAAIG,OAAO,CAAC,UAAU;YAEpC,OAAOL;QACT,EAAE,OAAOtD,OAAO;YACd9C,OAAO8C,KAAK,CAAC,wBAAwBA,iBAAiBE,QAAQF,QAAQ,IAAIE,MAAMC,OAAOH;YAEvF,MAAMpD,YACJC,UAAUuD,eAAe,EACzB,wBACA,CAAC,GACDJ,iBAAiBE,QAAQF,QAAQK;QAErC;IACF;IAEA;;GAEC,GACD,AAAOuD,WAAiB;QACtB,IAAI,CAAChG,YAAY,CAACgG,QAAQ;QAC1B1G,OAAOa,IAAI,CAAC;IACd;IAEA;;GAEC,GACD,AAAQqB,YAAYnB,KAAa,EAAU;QACzC,OAAO,CAAC,MAAM,EAAEA,OAAO;IACzB;IAEA;;GAEC,GACD,AAAQuC,iBAAiBvC,KAAa,EAAU;QAC9C,OAAO,CAAC,MAAM,EAAEA,MAAM,WAAW,CAAC;IACpC;IAEA;;GAEC,GACD,AAAQ4F,eAAelE,SAAiB,EAAU;QAChD,OAAO,CAAC,SAAS,EAAEA,WAAW;IAChC;IAEA;;GAEC,GACD,MAAcoB,cACZjC,OAAwB,EACxBxB,iBAAyB,EACV;QACf,MAAMkG,MAAM,IAAI,CAACK,cAAc,CAAC/E,QAAQC,EAAE;QAE1C,MAAM/B,UACJ;YACE,MAAM,IAAI,CAACW,KAAK,CAACmG,GAAG,CAClBN,KACAlE,KAAKC,SAAS,CAACT,UACf;gBAAEiF,IAAIzG;YAAkB;QAE5B,GACA;YAAEkC,aAAa;YAAGC,aAAa3C;QAAiB;IAEpD;IAEA;;GAEC,GACD,MAAcmE,YAAqBtB,SAAiB,EAAmC;QACrF,MAAM6D,MAAM,IAAI,CAACK,cAAc,CAAClE;QAEhC,MAAMqE,OAAO,MAAMhH,UACjB,UAAY,MAAM,IAAI,CAACW,KAAK,CAACyE,GAAG,CAACoB,MACjC;YAAEhE,aAAa;YAAGC,aAAa3C;QAAiB;QAGlD,IAAI,CAACkH,MAAM;YACT,OAAO;QACT;QAEA,MAAMlF,UAAUQ,KAAKuB,KAAK,CAACmD;QAE3B,4CAA4C;QAC5ClF,QAAQE,SAAS,GAAG,IAAIV,KAAKQ,QAAQE,SAAS;QAC9CF,QAAQG,UAAU,GAAG,IAAIX,KAAKQ,QAAQG,UAAU;QAChD,IAAIH,QAAQgC,UAAU,EAAE;YACtBhC,QAAQgC,UAAU,GAAG,IAAIxC,KAAKQ,QAAQgC,UAAU;QAClD;QAEA,OAAOhC;IACT;IAEA;;GAEC,GACD,MAAcqC,eAAexB,SAAiB,EAAiB;QAC7D,MAAM6D,MAAM,IAAI,CAACK,cAAc,CAAClE;QAEhC,MAAM3C,UACJ,UAAY,MAAM,IAAI,CAACW,KAAK,CAACsF,GAAG,CAACO,MACjC;YAAEhE,aAAa;YAAGC,aAAa3C;QAAiB;IAEpD;IAEA;;GAEC,GACD,AAAQ8C,YAAY3B,KAAa,EAAEgG,SAAgE,EAAQ;QACzG,IAAIpG,QAAQ,IAAI,CAACA,KAAK,CAACuE,GAAG,CAACnE;QAE3B,IAAI,CAACJ,OAAO;YACVA,QAAQ;gBACNwE,UAAU;gBACVC,UAAU;gBACVC,cAAc;gBACdC,UAAU;gBACVnE,WAAW,IAAIC;YACjB;YACA,IAAI,CAACT,KAAK,CAACiG,GAAG,CAAC7F,OAAOJ;QACxB;QAEAA,KAAK,CAACoG,UAAU;IAClB;AACF"}