claude-flow-novice 2.15.3 → 2.15.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. package/.claude/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
  2. package/.claude/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
  3. package/.claude/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
  4. package/.claude/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
  5. package/.claude/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
  6. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
  7. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
  8. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
  9. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
  10. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
  11. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
  12. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
  13. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
  14. package/.claude/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
  15. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
  16. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
  17. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
  18. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
  19. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
  20. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
  21. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
  22. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
  23. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
  24. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
  25. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
  26. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
  27. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
  28. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
  29. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
  30. package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
  31. package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
  32. package/.claude/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
  33. package/.claude/commands/cfn-loop-cli.md +29 -6
  34. package/.claude/commands/switch-api.md +31 -10
  35. package/.claude/hooks/cfn-lint-sql-injection.sh +61 -0
  36. package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
  37. package/.claude/hooks/cfn-pre-edit-security-warning.sh +40 -0
  38. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  39. package/.claude/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  40. package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  41. package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  42. package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  43. package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  44. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
  45. package/.claude/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  46. package/.claude/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  47. package/.claude/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  48. package/.claude/skills/cfn-redis-coordination/agent-log.sh +4 -0
  49. package/.claude/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  50. package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
  51. package/.claude/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  52. package/.claude/skills/cfn-redis-coordination/get-context.sh +33 -0
  53. package/.claude/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  54. package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
  55. package/.claude/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  56. package/.claude/skills/cfn-redis-coordination/redis-functions.sh +34 -0
  57. package/.claude/skills/cfn-redis-coordination/report-completion.sh +24 -31
  58. package/.claude/skills/cfn-redis-coordination/store-context.sh +4 -0
  59. package/.claude/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  60. package/.claude/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  61. package/.claude/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  62. package/.claude/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  63. package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
  64. package/README.md +116 -475
  65. package/claude-assets/agents/cfn-dev-team/README.md +103 -0
  66. package/claude-assets/agents/cfn-dev-team/architecture/goal-planner.md +1 -1
  67. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +77 -15
  68. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +355 -6
  69. package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +82 -1
  70. package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +82 -1
  71. package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +77 -15
  72. package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +99 -12
  73. package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +1 -1
  74. package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +97 -0
  75. package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +20 -1
  76. package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +97 -0
  77. package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +110 -13
  78. package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +106 -15
  79. package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +115 -11
  80. package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +94 -7
  81. package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +87 -9
  82. package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +85 -7
  83. package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +160 -28
  84. package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +101 -19
  85. package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +108 -14
  86. package/claude-assets/agents/cfn-dev-team/reviewers/{reviewer.md → code-reviewer.md} +95 -8
  87. package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +107 -7
  88. package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +98 -7
  89. package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +95 -7
  90. package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +136 -9
  91. package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +108 -1
  92. package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +107 -13
  93. package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +737 -0
  94. package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
  95. package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +828 -0
  96. package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +106 -7
  97. package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +77 -0
  98. package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +684 -0
  99. package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +110 -1
  100. package/claude-assets/agents/cfn-dev-team/testers/tester.md +94 -7
  101. package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +1 -3
  102. package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +87 -13
  103. package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +103 -7
  104. package/claude-assets/agents/cfn-dev-team/utility/researcher.md +1 -3
  105. package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +94 -7
  106. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +46 -0
  107. package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
  108. package/claude-assets/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
  109. package/claude-assets/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
  110. package/claude-assets/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
  111. package/claude-assets/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
  112. package/claude-assets/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
  113. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
  114. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
  115. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
  116. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
  117. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
  118. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
  119. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
  120. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
  121. package/claude-assets/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
  122. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
  123. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
  124. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
  125. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
  126. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
  127. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
  128. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
  129. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
  130. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
  131. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
  132. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
  133. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
  134. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
  135. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
  136. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
  137. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
  138. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
  139. package/claude-assets/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
  140. package/claude-assets/commands/cfn-loop-cli.md +29 -6
  141. package/claude-assets/commands/switch-api.md +31 -10
  142. package/claude-assets/hooks/cfn-lint-sql-injection.sh +61 -0
  143. package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
  144. package/claude-assets/hooks/cfn-pre-edit-security-warning.sh +40 -0
  145. package/claude-assets/hooks/detect-hardcoded-credentials.sh +212 -0
  146. package/claude-assets/skills/SKILL_TEMPLATE.md +774 -0
  147. package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +84 -113
  148. package/claude-assets/skills/agent-lifecycle/simple-audit.sh +33 -6
  149. package/claude-assets/skills/agent-template-generator/SKILL.md +440 -0
  150. package/claude-assets/skills/agent-template-generator/generate-agent.sh +405 -0
  151. package/claude-assets/skills/agent-validation-linter/SKILL.md +589 -0
  152. package/claude-assets/skills/agent-validation-linter/lint-agents.sh +271 -0
  153. package/claude-assets/skills/bootstrap/bash-fundamentals.md +786 -0
  154. package/claude-assets/skills/bootstrap/database-connection.md +464 -0
  155. package/claude-assets/skills/bootstrap/error-handling.md +580 -0
  156. package/claude-assets/skills/bootstrap/file-operations.md +699 -0
  157. package/claude-assets/skills/bootstrap/skill-loader.md +616 -0
  158. package/claude-assets/skills/bootstrap/sqlite-params.sh +287 -0
  159. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  160. package/claude-assets/skills/cfn-automatic-memory-persistence/test-memory-persistence.sh +17 -16
  161. package/claude-assets/skills/cfn-deployment/SKILL.md +293 -0
  162. package/claude-assets/skills/cfn-deployment/execute.sh +21 -0
  163. package/claude-assets/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  164. package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  165. package/claude-assets/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  166. package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +38 -0
  167. package/claude-assets/skills/cfn-error-batching-strategy/lib/core-functions.sh +47 -47
  168. package/claude-assets/skills/cfn-file-operations/SKILL.md +290 -0
  169. package/claude-assets/skills/cfn-file-operations/execute.sh +129 -0
  170. package/claude-assets/skills/cfn-file-operations/lib/atomic-write.sh +294 -0
  171. package/claude-assets/skills/cfn-file-operations/lib/lock.sh +361 -0
  172. package/claude-assets/skills/cfn-file-operations/test.sh +369 -0
  173. package/claude-assets/skills/cfn-log-operations/SKILL.md +308 -0
  174. package/claude-assets/skills/cfn-log-operations/execute.sh +420 -0
  175. package/claude-assets/skills/cfn-log-operations/lib/rotate.sh +406 -0
  176. package/claude-assets/skills/cfn-log-operations/lib/search.sh +448 -0
  177. package/claude-assets/skills/cfn-log-operations/test.sh +394 -0
  178. package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  179. package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  180. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
  181. package/claude-assets/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  182. package/claude-assets/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  183. package/claude-assets/skills/cfn-parameterized-queries/SKILL.md +339 -0
  184. package/claude-assets/skills/cfn-playbook/query-playbook.sh +19 -15
  185. package/claude-assets/skills/cfn-playbook/update-playbook.sh +25 -14
  186. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +44 -0
  187. package/claude-assets/skills/cfn-promotion/SKILL.md +305 -0
  188. package/claude-assets/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  189. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh +4 -0
  190. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  191. package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
  192. package/claude-assets/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  193. package/claude-assets/skills/cfn-redis-coordination/get-context.sh +33 -0
  194. package/claude-assets/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  195. package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
  196. package/claude-assets/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  197. package/claude-assets/skills/cfn-redis-coordination/redis-functions.sh +34 -0
  198. package/claude-assets/skills/cfn-redis-coordination/report-completion.sh +24 -31
  199. package/claude-assets/skills/cfn-redis-coordination/store-context.sh +4 -0
  200. package/claude-assets/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  201. package/claude-assets/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  202. package/claude-assets/skills/cfn-skill-loader/SKILL.md +466 -0
  203. package/claude-assets/skills/cfn-skill-loader/execute.sh +344 -0
  204. package/claude-assets/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  205. package/claude-assets/skills/cfn-task-audit/get-audit-data.sh +42 -21
  206. package/claude-assets/skills/cfn-task-audit/store-task-audit.sh +17 -10
  207. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh +17 -14
  208. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh.backup-1763392821 +55 -0
  209. package/claude-assets/skills/cfn-test-runner/store-benchmarks.sh +17 -19
  210. package/claude-assets/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  211. package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
  212. package/claude-assets/skills/cfn-utilities/SKILL.md +237 -0
  213. package/claude-assets/skills/cfn-utilities/execute.sh +32 -0
  214. package/claude-assets/skills/cfn-utilities/lib/errors.sh +56 -0
  215. package/claude-assets/skills/cfn-utilities/lib/file-ops.sh +164 -0
  216. package/claude-assets/skills/cfn-utilities/lib/logging.sh +77 -0
  217. package/claude-assets/skills/cfn-utilities/lib/retry.sh +127 -0
  218. package/claude-assets/skills/cfn-utilities/test.sh +317 -0
  219. package/claude-assets/skills/integration/agent-handoff.sh +62 -64
  220. package/claude-assets/skills/json-validation/SKILL.md +431 -0
  221. package/claude-assets/skills/json-validation/test-validate-success-criteria.sh +421 -0
  222. package/claude-assets/skills/json-validation/validate-success-criteria.sh +197 -0
  223. package/claude-assets/skills/redis-coordination/validate-parameters.sh +34 -0
  224. package/claude-assets/skills/workflow-codification/DEPLOY_QUICK_REFERENCE.md +106 -0
  225. package/claude-assets/skills/workflow-codification/PROPAGATE_UPDATE_QUICK_REFERENCE.md +366 -0
  226. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh +481 -0
  227. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh.backup-1763392820 +512 -0
  228. package/claude-assets/skills/workflow-codification/lib/security-utils.sh +204 -0
  229. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh +648 -0
  230. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh.backup-1763392820 +664 -0
  231. package/claude-assets/skills/workflow-codification/test-integration.sh +15 -0
  232. package/claude-assets/skills/workflow-codification/test-metadata-update.sh +350 -0
  233. package/claude-assets/skills/workflow-codification/track-cost-savings.sh +55 -14
  234. package/claude-assets/skills/workflow-codification/track-cost-savings.sh.backup-1763392821 +445 -0
  235. package/claude-assets/skills/workflow-codification/track-edge-case.sh +27 -60
  236. package/claude-assets/skills/workflow-codification/workflow-codification.db +0 -0
  237. package/dist/ace/ace-curator.js +10 -2
  238. package/dist/ace/ace-curator.js.map +1 -1
  239. package/dist/ace/ace-generator.js +4 -0
  240. package/dist/ace/ace-generator.js.map +1 -1
  241. package/dist/ace/ace-reflector.js +1 -1
  242. package/dist/ace/ace-reflector.js.map +1 -1
  243. package/dist/ace/context-injection.js +24 -2
  244. package/dist/ace/context-injection.js.map +1 -1
  245. package/dist/agents/task-agent-integration.js +1 -1
  246. package/dist/agents/task-agent-integration.js.map +1 -1
  247. package/dist/api/health-endpoints.js +390 -0
  248. package/dist/api/health-endpoints.js.map +1 -0
  249. package/dist/cli/agent-executor.js +4 -1
  250. package/dist/cli/agent-executor.js.map +1 -1
  251. package/dist/cli/agent-prompt-builder.js +89 -1
  252. package/dist/cli/agent-prompt-builder.js.map +1 -1
  253. package/dist/cli/agent-spawn.js +130 -37
  254. package/dist/cli/agent-spawn.js.map +1 -1
  255. package/dist/cli/config-manager.js +109 -91
  256. package/dist/cli/config-manager.js.map +1 -1
  257. package/dist/cli/conversation-fork-cleanup.js +201 -0
  258. package/dist/cli/conversation-fork-cleanup.js.map +1 -0
  259. package/dist/cli/conversation-fork.js +16 -3
  260. package/dist/cli/conversation-fork.js.map +1 -1
  261. package/dist/cli/skill-cache-validator.js +412 -0
  262. package/dist/cli/skill-cache-validator.js.map +1 -0
  263. package/dist/cli/skill-cli.js +991 -0
  264. package/dist/cli/skill-cli.js.map +1 -0
  265. package/dist/cli/skill-execution-logger.js +284 -0
  266. package/dist/cli/skill-execution-logger.js.map +1 -0
  267. package/dist/cli/skill-loader.js +457 -0
  268. package/dist/cli/skill-loader.js.map +1 -0
  269. package/dist/coordination/event-bus.js +2 -2
  270. package/dist/coordination/event-bus.js.map +1 -1
  271. package/dist/coordination/fleet-manager.js +1 -1
  272. package/dist/coordination/fleet-manager.js.map +1 -1
  273. package/dist/coordination/index.js +23 -9
  274. package/dist/coordination/index.js.map +1 -1
  275. package/dist/coordination/types/fleet-manager.types.js.map +1 -1
  276. package/dist/db/migration-manager.js +483 -0
  277. package/dist/db/migration-manager.js.map +1 -0
  278. package/dist/db/skills-query.js +535 -0
  279. package/dist/db/skills-query.js.map +1 -0
  280. package/dist/integration/DatabaseHandoff.js +1 -1
  281. package/dist/integration/DatabaseHandoff.js.map +1 -1
  282. package/dist/jobs/edge-case-analyzer.js +367 -0
  283. package/dist/jobs/edge-case-analyzer.js.map +1 -0
  284. package/dist/jobs/promotion-sla-enforcer.js +288 -0
  285. package/dist/jobs/promotion-sla-enforcer.js.map +1 -0
  286. package/dist/lib/agent-output-parser.js.map +1 -1
  287. package/dist/lib/agent-output-validator.js.map +1 -1
  288. package/dist/lib/agent-workspace.js +281 -0
  289. package/dist/lib/agent-workspace.js.map +1 -0
  290. package/dist/lib/atomic-file-writer.js +377 -0
  291. package/dist/lib/atomic-file-writer.js.map +1 -0
  292. package/dist/lib/backup-manager.js +779 -0
  293. package/dist/lib/backup-manager.js.map +1 -0
  294. package/dist/lib/checkpoint-manager.js +837 -0
  295. package/dist/lib/checkpoint-manager.js.map +1 -0
  296. package/dist/lib/circuit-breaker.js +340 -0
  297. package/dist/lib/circuit-breaker.js.map +1 -0
  298. package/dist/lib/completion-signal-handler.js +243 -0
  299. package/dist/lib/completion-signal-handler.js.map +1 -0
  300. package/dist/lib/config-manager.js +312 -0
  301. package/dist/lib/config-manager.js.map +1 -0
  302. package/dist/lib/config-migrator.js +386 -0
  303. package/dist/lib/config-migrator.js.map +1 -0
  304. package/dist/lib/config-validator.js.map +1 -1
  305. package/dist/lib/correlation-cache.js +311 -0
  306. package/dist/lib/correlation-cache.js.map +1 -0
  307. package/dist/lib/correlation.js +263 -0
  308. package/dist/lib/correlation.js.map +1 -0
  309. package/dist/lib/database-service/connection-pool-manager.js +520 -0
  310. package/dist/lib/database-service/connection-pool-manager.js.map +1 -0
  311. package/dist/lib/database-service/correlation.js +329 -0
  312. package/dist/lib/database-service/correlation.js.map +1 -0
  313. package/dist/lib/database-service/errors.js +120 -0
  314. package/dist/lib/database-service/errors.js.map +1 -0
  315. package/dist/lib/database-service/index.js +168 -0
  316. package/dist/lib/database-service/index.js.map +1 -0
  317. package/dist/lib/database-service/postgres-adapter.js +526 -0
  318. package/dist/lib/database-service/postgres-adapter.js.map +1 -0
  319. package/dist/lib/database-service/redis-adapter.js +360 -0
  320. package/dist/lib/database-service/redis-adapter.js.map +1 -0
  321. package/dist/lib/database-service/sqlite-adapter.js +544 -0
  322. package/dist/lib/database-service/sqlite-adapter.js.map +1 -0
  323. package/dist/lib/database-service/transaction-manager.js +773 -0
  324. package/dist/lib/database-service/transaction-manager.js.map +1 -0
  325. package/dist/lib/database-service/types.js +23 -0
  326. package/dist/lib/database-service/types.js.map +1 -0
  327. package/dist/lib/deadlock-resolver.js +292 -0
  328. package/dist/lib/deadlock-resolver.js.map +1 -0
  329. package/dist/lib/distributed-lock.js +451 -0
  330. package/dist/lib/distributed-lock.js.map +1 -0
  331. package/dist/lib/edge-case-deduplicator.js +227 -0
  332. package/dist/lib/edge-case-deduplicator.js.map +1 -0
  333. package/dist/lib/encryption-manager.js +322 -0
  334. package/dist/lib/encryption-manager.js.map +1 -0
  335. package/dist/lib/error-aggregator.js +234 -0
  336. package/dist/lib/error-aggregator.js.map +1 -0
  337. package/dist/lib/errors.js +287 -0
  338. package/dist/lib/errors.js.map +1 -0
  339. package/dist/lib/file-lock-manager.js +578 -0
  340. package/dist/lib/file-lock-manager.js.map +1 -0
  341. package/dist/lib/file-operations.js +367 -0
  342. package/dist/lib/file-operations.js.map +1 -0
  343. package/dist/lib/idempotent-write.js +237 -0
  344. package/dist/lib/idempotent-write.js.map +1 -0
  345. package/dist/lib/integration-schema-validator.js +522 -0
  346. package/dist/lib/integration-schema-validator.js.map +1 -0
  347. package/dist/lib/lock-health-monitor.js +298 -0
  348. package/dist/lib/lock-health-monitor.js.map +1 -0
  349. package/dist/lib/log-shipper.js +422 -0
  350. package/dist/lib/log-shipper.js.map +1 -0
  351. package/dist/lib/logging.js +146 -0
  352. package/dist/lib/logging.js.map +1 -0
  353. package/dist/lib/message-deduplicator.js +439 -0
  354. package/dist/lib/message-deduplicator.js.map +1 -0
  355. package/dist/lib/multi-system-query.js +604 -0
  356. package/dist/lib/multi-system-query.js.map +1 -0
  357. package/dist/lib/orphan-detector.js +332 -0
  358. package/dist/lib/orphan-detector.js.map +1 -0
  359. package/dist/lib/password-generator.js +166 -0
  360. package/dist/lib/password-generator.js.map +1 -0
  361. package/dist/lib/path-validator.js +429 -0
  362. package/dist/lib/path-validator.js.map +1 -0
  363. package/dist/lib/query-translator.js +905 -0
  364. package/dist/lib/query-translator.js.map +1 -0
  365. package/dist/lib/queue-recovery.js +469 -0
  366. package/dist/lib/queue-recovery.js.map +1 -0
  367. package/dist/lib/redis-queue-manager.js +512 -0
  368. package/dist/lib/redis-queue-manager.js.map +1 -0
  369. package/dist/lib/reflection-archiver.js +272 -0
  370. package/dist/lib/reflection-archiver.js.map +1 -0
  371. package/dist/lib/retry-manager.js +453 -0
  372. package/dist/lib/retry-manager.js.map +1 -0
  373. package/dist/lib/retry.js +262 -0
  374. package/dist/lib/retry.js.map +1 -0
  375. package/dist/lib/schema-transform.js +695 -0
  376. package/dist/lib/schema-transform.js.map +1 -0
  377. package/dist/lib/schema-validator.js +491 -0
  378. package/dist/lib/schema-validator.js.map +1 -0
  379. package/dist/lib/skill-cache.js +297 -0
  380. package/dist/lib/skill-cache.js.map +1 -0
  381. package/dist/lib/skill-content-manager.js +337 -0
  382. package/dist/lib/skill-content-manager.js.map +1 -0
  383. package/dist/lib/skill-frontmatter-parser.js +237 -0
  384. package/dist/lib/skill-frontmatter-parser.js.map +1 -0
  385. package/dist/lib/skill-git-integration.js +275 -0
  386. package/dist/lib/skill-git-integration.js.map +1 -0
  387. package/dist/lib/skill-markdown-validator.js +396 -0
  388. package/dist/lib/skill-markdown-validator.js.map +1 -0
  389. package/dist/lib/skill-output-parser.js +312 -0
  390. package/dist/lib/skill-output-parser.js.map +1 -0
  391. package/dist/lib/unified-query-api.js +467 -0
  392. package/dist/lib/unified-query-api.js.map +1 -0
  393. package/dist/middleware/auth-middleware.js +350 -0
  394. package/dist/middleware/auth-middleware.js.map +1 -0
  395. package/dist/middleware/schema-validation.js +347 -0
  396. package/dist/middleware/schema-validation.js.map +1 -0
  397. package/dist/providers/anthropic-provider.js +1 -1
  398. package/dist/providers/anthropic-provider.js.map +1 -1
  399. package/dist/providers/provider-factory.js +2 -2
  400. package/dist/providers/provider-factory.js.map +1 -1
  401. package/dist/services/edge-case-analyzer.js +321 -0
  402. package/dist/services/edge-case-analyzer.js.map +1 -0
  403. package/dist/services/edge-case-deduplicator.js +266 -0
  404. package/dist/services/edge-case-deduplicator.js.map +1 -0
  405. package/dist/services/edge-case-detector.js +337 -0
  406. package/dist/services/edge-case-detector.js.map +1 -0
  407. package/dist/services/edge-case-tracker.js +547 -0
  408. package/dist/services/edge-case-tracker.js.map +1 -0
  409. package/dist/services/health-check-system.js +586 -0
  410. package/dist/services/health-check-system.js.map +1 -0
  411. package/dist/services/metrics-logger.js +412 -0
  412. package/dist/services/metrics-logger.js.map +1 -0
  413. package/dist/services/patch-generator.js +378 -0
  414. package/dist/services/patch-generator.js.map +1 -0
  415. package/dist/services/patch-validator.js +337 -0
  416. package/dist/services/patch-validator.js.map +1 -0
  417. package/dist/services/performance-monitor.js +811 -0
  418. package/dist/services/performance-monitor.js.map +1 -0
  419. package/dist/services/promotion-pipeline.js +918 -0
  420. package/dist/services/promotion-pipeline.js.map +1 -0
  421. package/dist/services/promotion-validator.js +394 -0
  422. package/dist/services/promotion-validator.js.map +1 -0
  423. package/dist/services/reflection-logger.js +388 -0
  424. package/dist/services/reflection-logger.js.map +1 -0
  425. package/dist/services/skill-deployment.js +472 -0
  426. package/dist/services/skill-deployment.js.map +1 -0
  427. package/dist/services/skill-loader.js +427 -0
  428. package/dist/services/skill-loader.js.map +1 -0
  429. package/dist/services/skill-promotion.js +372 -0
  430. package/dist/services/skill-promotion.js.map +1 -0
  431. package/dist/services/skill-validator.js +454 -0
  432. package/dist/services/skill-validator.js.map +1 -0
  433. package/dist/services/skill-versioning.js +244 -0
  434. package/dist/services/skill-versioning.js.map +1 -0
  435. package/dist/services/workspace-supervisor.js +597 -0
  436. package/dist/services/workspace-supervisor.js.map +1 -0
  437. package/dist/types/edge-case.js +45 -0
  438. package/dist/types/edge-case.js.map +1 -0
  439. package/docs/BUG_19_MEMORY_LEAK_TASK_MODE.md +405 -0
  440. package/docs/MEMORY_CLEANUP_GUIDE.md +358 -0
  441. package/docs/MEMORY_LEAK_FIX_SUMMARY.md +322 -0
  442. package/docs/REDIS_CLEANUP_EXECUTIVE_SUMMARY.md +319 -0
  443. package/docs/REDIS_CLEANUP_VERIFICATION_REPORT.md +574 -0
  444. package/package.json +35 -4
  445. package/readme/README.md +53 -5
  446. package/scripts/backup-cleanup.sh +627 -0
  447. package/scripts/cleanup-workspaces.sh +412 -0
  448. package/scripts/cleanup-yaml-configs.sh +141 -0
  449. package/scripts/deploy-approved-skills.sh +263 -0
  450. package/scripts/health-check.sh +447 -0
  451. package/scripts/log-aggregator.sh +554 -0
  452. package/scripts/log-monitor.sh +629 -0
  453. package/scripts/manage-agent-workspaces.sh +434 -0
  454. package/scripts/migrate-schema.sh +533 -0
  455. package/scripts/promote-staged-skills.sh +423 -0
  456. package/scripts/verify-no-secrets.sh +88 -35
  457. package/scripts/verify-redis-cleanup.sh +173 -0
  458. package/tests/README.md +84 -0
  459. package/tests/test-memory-leak-task-mode.sh +435 -0
  460. package/.claude/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  461. package/.claude/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  462. package/.claude/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  463. package/.claude/skills/agent-lifecycle/SKILL.md +0 -60
  464. package/.claude/skills/agent-lifecycle/execute-lifecycle-hook.sh +0 -573
  465. package/.claude/skills/agent-lifecycle/simple-audit.sh +0 -31
  466. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  467. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
  468. package/README.md.backup_before_replace +0 -781
  469. package/claude-assets/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  470. package/claude-assets/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  471. package/claude-assets/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  472. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  473. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/idempotent-write.ts"],"sourcesContent":["/**\r\n * Idempotent Write Utility\r\n *\r\n * Provides content-based deduplication for metrics logging using SHA256 hashing.\r\n * Part of Task 2.3: Unified Metrics and Execution Logging\r\n *\r\n * Features:\r\n * - Content-based idempotency keys (prevents duplicate metrics)\r\n * - TTL-based cleanup (24-hour retention)\r\n * - Atomic write tracking across databases\r\n */\r\n\r\nimport * as crypto from 'crypto';\r\nimport { IDatabaseAdapter, OperationResult } from './database-service/types.js';\r\nimport { createLogger } from './logging.js';\r\n\r\nconst logger = createLogger('idempotent-write');\r\n\r\n/**\r\n * Execution metrics interface (must match ExecutionMetrics in metrics-logger.ts)\r\n */\r\nexport interface ExecutionMetrics {\r\n id?: string;\r\n timestamp: Date;\r\n agent_id: string;\r\n skill_id?: string;\r\n task_id: string;\r\n duration_ms: number;\r\n tokens_used: number;\r\n cost_usd: number;\r\n status: 'success' | 'failure' | 'timeout' | 'cancelled';\r\n error_message?: string;\r\n metadata?: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Idempotency key record\r\n */\r\nexport interface IdempotencyKey {\r\n key: string;\r\n metrics_id?: string;\r\n written_at: Date;\r\n expires_at: Date;\r\n}\r\n\r\n/**\r\n * Default TTL for idempotency keys (24 hours)\r\n */\r\nconst DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;\r\n\r\n/**\r\n * Create idempotency key from execution metrics\r\n *\r\n * Key is based on: agent_id + task_id + timestamp + duration_ms\r\n * This combination ensures uniqueness while allowing retries to be detected\r\n *\r\n * @param metrics - Execution metrics to create key from\r\n * @returns SHA256 hash as idempotency key\r\n */\r\nexport function createIdempotentKey(metrics: ExecutionMetrics): string {\r\n // Normalize timestamp to ISO string for consistent hashing\r\n const timestampStr = metrics.timestamp instanceof Date\r\n ? metrics.timestamp.toISOString()\r\n : new Date(metrics.timestamp).toISOString();\r\n\r\n // Build content string for hashing\r\n const content = [\r\n metrics.agent_id,\r\n metrics.task_id,\r\n timestampStr,\r\n metrics.duration_ms.toString(),\r\n metrics.status,\r\n ].join(':');\r\n\r\n // Generate SHA256 hash\r\n const hash = crypto.createHash('sha256').update(content).digest('hex');\r\n\r\n logger.debug('Created idempotency key', {\r\n agent_id: metrics.agent_id,\r\n task_id: metrics.task_id,\r\n key: hash.substring(0, 16) + '...', // Log truncated key\r\n });\r\n\r\n return hash;\r\n}\r\n\r\n/**\r\n * Check if metrics have already been written\r\n *\r\n * @param key - Idempotency key to check\r\n * @param db - Database adapter\r\n * @returns True if already written, false otherwise\r\n */\r\nexport async function hasBeenWritten(\r\n key: string,\r\n db: IDatabaseAdapter\r\n): Promise<boolean> {\r\n try {\r\n // Query idempotency_keys table\r\n const result = await db.get<IdempotencyKey>(`idempotency_keys:${key}`);\r\n\r\n if (!result) {\r\n logger.debug('Idempotency key not found', { key: key.substring(0, 16) + '...' });\r\n return false;\r\n }\r\n\r\n // Check if key has expired\r\n const expiresAt = new Date(result.expires_at);\r\n const now = new Date();\r\n\r\n if (expiresAt < now) {\r\n logger.debug('Idempotency key expired', {\r\n key: key.substring(0, 16) + '...',\r\n expired_at: expiresAt.toISOString(),\r\n });\r\n return false;\r\n }\r\n\r\n logger.debug('Idempotency key found', {\r\n key: key.substring(0, 16) + '...',\r\n written_at: result.written_at,\r\n });\r\n\r\n return true;\r\n } catch (error) {\r\n logger.error('Failed to check idempotency key', {\r\n key: key.substring(0, 16) + '...',\r\n error: error instanceof Error ? error.message : String(error),\r\n });\r\n\r\n // On error, assume not written to allow retry\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Mark metrics as written\r\n *\r\n * @param key - Idempotency key\r\n * @param db - Database adapter\r\n * @param metricsId - Optional metrics ID to link\r\n * @param ttlMs - Time-to-live in milliseconds (default: 24 hours)\r\n */\r\nexport async function markWritten(\r\n key: string,\r\n db: IDatabaseAdapter,\r\n metricsId?: string,\r\n ttlMs: number = DEFAULT_TTL_MS\r\n): Promise<void> {\r\n try {\r\n const now = new Date();\r\n const expiresAt = new Date(now.getTime() + ttlMs);\r\n\r\n const idempotencyRecord: IdempotencyKey = {\r\n key,\r\n metrics_id: metricsId,\r\n written_at: now,\r\n expires_at: expiresAt,\r\n };\r\n\r\n // Insert into idempotency_keys table\r\n await db.insert('idempotency_keys', idempotencyRecord);\r\n\r\n logger.debug('Marked idempotency key as written', {\r\n key: key.substring(0, 16) + '...',\r\n metrics_id: metricsId,\r\n expires_at: expiresAt.toISOString(),\r\n });\r\n } catch (error) {\r\n logger.error('Failed to mark idempotency key', {\r\n key: key.substring(0, 16) + '...',\r\n error: error instanceof Error ? error.message : String(error),\r\n });\r\n\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Batch check for written metrics\r\n *\r\n * @param keys - Array of idempotency keys\r\n * @param db - Database adapter\r\n * @returns Map of key -> boolean (written status)\r\n */\r\nexport async function batchCheckWritten(\r\n keys: string[],\r\n db: IDatabaseAdapter\r\n): Promise<Map<string, boolean>> {\r\n const results = new Map<string, boolean>();\r\n\r\n try {\r\n // Check all keys in parallel\r\n const checks = keys.map(async (key) => {\r\n const written = await hasBeenWritten(key, db);\r\n return { key, written };\r\n });\r\n\r\n const checkResults = await Promise.all(checks);\r\n\r\n // Build result map\r\n checkResults.forEach(({ key, written }) => {\r\n results.set(key, written);\r\n });\r\n\r\n logger.debug('Batch idempotency check complete', {\r\n total_keys: keys.length,\r\n already_written: Array.from(results.values()).filter(v => v).length,\r\n });\r\n\r\n return results;\r\n } catch (error) {\r\n logger.error('Failed to batch check idempotency keys', {\r\n total_keys: keys.length,\r\n error: error instanceof Error ? error.message : String(error),\r\n });\r\n\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Batch mark metrics as written\r\n *\r\n * @param entries - Array of { key, metricsId? } entries\r\n * @param db - Database adapter\r\n * @param ttlMs - Time-to-live in milliseconds (default: 24 hours)\r\n */\r\nexport async function batchMarkWritten(\r\n entries: Array<{ key: string; metricsId?: string }>,\r\n db: IDatabaseAdapter,\r\n ttlMs: number = DEFAULT_TTL_MS\r\n): Promise<void> {\r\n try {\r\n const now = new Date();\r\n const expiresAt = new Date(now.getTime() + ttlMs);\r\n\r\n const records: IdempotencyKey[] = entries.map(({ key, metricsId }) => ({\r\n key,\r\n metrics_id: metricsId,\r\n written_at: now,\r\n expires_at: expiresAt,\r\n }));\r\n\r\n // Batch insert\r\n await db.insertMany('idempotency_keys', records);\r\n\r\n logger.debug('Batch marked idempotency keys as written', {\r\n total_keys: entries.length,\r\n expires_at: expiresAt.toISOString(),\r\n });\r\n } catch (error) {\r\n logger.error('Failed to batch mark idempotency keys', {\r\n total_keys: entries.length,\r\n error: error instanceof Error ? error.message : String(error),\r\n });\r\n\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Cleanup expired idempotency keys\r\n *\r\n * @param db - Database adapter\r\n * @returns Number of keys deleted\r\n */\r\nexport async function cleanupExpiredKeys(db: IDatabaseAdapter): Promise<number> {\r\n try {\r\n const now = new Date();\r\n\r\n // Query for expired keys\r\n const expiredKeys = await db.query<IdempotencyKey>('idempotency_keys', [\r\n {\r\n field: 'expires_at' as keyof IdempotencyKey,\r\n operator: 'lt',\r\n value: now,\r\n },\r\n ]);\r\n\r\n // Delete expired keys\r\n let deletedCount = 0;\r\n for (const key of expiredKeys) {\r\n await db.delete('idempotency_keys', key.key);\r\n deletedCount++;\r\n }\r\n\r\n logger.info('Cleaned up expired idempotency keys', {\r\n deleted_count: deletedCount,\r\n });\r\n\r\n return deletedCount;\r\n } catch (error) {\r\n logger.error('Failed to cleanup expired idempotency keys', {\r\n error: error instanceof Error ? error.message : String(error),\r\n });\r\n\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Validate cost accuracy (within $0.001 precision)\r\n *\r\n * @param cost - Cost value to validate\r\n * @returns True if cost is accurate to $0.001\r\n */\r\nexport function validateCostAccuracy(cost: number): boolean {\r\n const rounded = parseFloat(cost.toFixed(3));\r\n return Math.abs(cost - rounded) < 0.0001;\r\n}\r\n\r\n/**\r\n * Round cost to $0.001 precision\r\n *\r\n * Uses standard \"round half up\" behavior for consistent rounding.\r\n *\r\n * @param cost - Cost value to round\r\n * @returns Cost rounded to 3 decimal places\r\n */\r\nexport function roundCost(cost: number): number {\r\n // Use Math.round for proper \"round half up\" behavior\r\n // Multiply by 1000, round, then divide by 1000 for $0.001 precision\r\n return Math.round(cost * 1000) / 1000;\r\n}\r\n"],"names":["crypto","createLogger","logger","DEFAULT_TTL_MS","createIdempotentKey","metrics","timestampStr","timestamp","Date","toISOString","content","agent_id","task_id","duration_ms","toString","status","join","hash","createHash","update","digest","debug","key","substring","hasBeenWritten","db","result","get","expiresAt","expires_at","now","expired_at","written_at","error","Error","message","String","markWritten","metricsId","ttlMs","getTime","idempotencyRecord","metrics_id","insert","batchCheckWritten","keys","results","Map","checks","map","written","checkResults","Promise","all","forEach","set","total_keys","length","already_written","Array","from","values","filter","v","batchMarkWritten","entries","records","insertMany","cleanupExpiredKeys","expiredKeys","query","field","operator","value","deletedCount","delete","info","deleted_count","validateCostAccuracy","cost","rounded","parseFloat","toFixed","Math","abs","roundCost","round"],"mappings":"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"}
@@ -0,0 +1,522 @@
1
+ /**
2
+ * Integration Schema Validator
3
+ *
4
+ * Task: P2-3.2 - JSON Schema Validation Enforcement
5
+ * Enforces JSON Schema validation at all 47 integration points
6
+ *
7
+ * Features:
8
+ * - Automatic validation at data boundaries
9
+ * - Schema registry with versioning
10
+ * - Migration support between schema versions
11
+ * - Performance: <50ms validation, <100ms schema loading
12
+ * - Comprehensive error reporting with StandardError
13
+ *
14
+ * @module integration-schema-validator
15
+ */ import Ajv from 'ajv';
16
+ import addFormats from 'ajv-formats';
17
+ import { StandardError, ErrorCode } from './errors.js';
18
+ import { getGlobalLogger } from './logging.js';
19
+ import fs from 'fs/promises';
20
+ import path from 'path';
21
+ const logger = getGlobalLogger();
22
+ // ============================================================================
23
+ // Integration Categories (6 categories, 47 points total)
24
+ // ============================================================================
25
+ const INTEGRATION_CATEGORIES = [
26
+ 'database-handoffs',
27
+ 'file-operations',
28
+ 'cfn-loop-communication',
29
+ 'phase4-workflow',
30
+ 'api-layer',
31
+ 'data-format-transformations'
32
+ ];
33
+ // ============================================================================
34
+ // IntegrationSchemaValidator Class
35
+ // ============================================================================
36
+ export class IntegrationSchemaValidator {
37
+ config;
38
+ ajv;
39
+ schemaCache;
40
+ migrations;
41
+ initialized = false;
42
+ constructor(config){
43
+ this.config = {
44
+ schemaPath: config.schemaPath,
45
+ enableCache: config.enableCache ?? true,
46
+ strictMode: config.strictMode ?? true,
47
+ maxCacheSize: config.maxCacheSize ?? 1000,
48
+ schemaExtension: config.schemaExtension ?? '.schema.json'
49
+ };
50
+ // Initialize Ajv with formats support
51
+ this.ajv = new Ajv({
52
+ allErrors: true,
53
+ strict: this.config.strictMode,
54
+ validateFormats: true,
55
+ verbose: true
56
+ });
57
+ addFormats(this.ajv); // Add format validators (date-time, email, uri, etc.)
58
+ this.schemaCache = new Map();
59
+ this.migrations = {};
60
+ logger.debug('IntegrationSchemaValidator initialized', {
61
+ schemaPath: this.config.schemaPath,
62
+ enableCache: this.config.enableCache,
63
+ strictMode: this.config.strictMode
64
+ });
65
+ }
66
+ /**
67
+ * Initialize validator by loading all schemas
68
+ */ async initialize() {
69
+ if (this.initialized) {
70
+ return;
71
+ }
72
+ try {
73
+ // Verify schema directory exists
74
+ await fs.access(this.config.schemaPath);
75
+ // Load all schemas from directory
76
+ const categories = await this.loadSchemaDirectory();
77
+ logger.info('Schema validator initialized', {
78
+ categories: categories.length,
79
+ schemasLoaded: this.schemaCache.size
80
+ });
81
+ this.initialized = true;
82
+ } catch (error) {
83
+ logger.error('Failed to initialize schema validator', error, {
84
+ schemaPath: this.config.schemaPath
85
+ });
86
+ throw new StandardError(ErrorCode.CONFIGURATION_ERROR, `Failed to initialize schema validator: ${error.message}`, {
87
+ schemaPath: this.config.schemaPath
88
+ }, error);
89
+ }
90
+ }
91
+ /**
92
+ * Shutdown validator and clear caches
93
+ */ async shutdown() {
94
+ this.schemaCache.clear();
95
+ this.migrations = {};
96
+ this.initialized = false;
97
+ logger.debug('Schema validator shutdown complete');
98
+ }
99
+ /**
100
+ * Validate data against a schema
101
+ *
102
+ * @param data - Data to validate
103
+ * @param schemaId - Schema identifier (e.g., "database-handoffs/pattern-deployment")
104
+ * @param version - Schema version (defaults to latest)
105
+ * @throws StandardError with VALIDATION_FAILED code if validation fails
106
+ */ async validate(data, schemaId, version) {
107
+ this.ensureInitialized();
108
+ const startTime = Date.now();
109
+ try {
110
+ // Get schema validator
111
+ const schema = await this.getSchema(schemaId, version);
112
+ // Perform validation
113
+ const valid = schema.validator(data);
114
+ if (!valid) {
115
+ const errors = this.formatErrors(schema.validator.errors || []);
116
+ logger.warn('Schema validation failed', {
117
+ schemaId,
118
+ version: schema.version,
119
+ errorCount: errors.length,
120
+ duration: Date.now() - startTime
121
+ });
122
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, `Schema validation failed for ${schemaId}@${schema.version}`, {
123
+ schemaId,
124
+ version: schema.version,
125
+ errors,
126
+ suggestions: this.generateSuggestions(errors, data)
127
+ });
128
+ }
129
+ logger.debug('Schema validation succeeded', {
130
+ schemaId,
131
+ version: schema.version,
132
+ duration: Date.now() - startTime
133
+ });
134
+ } catch (error) {
135
+ if (error instanceof StandardError) {
136
+ throw error;
137
+ }
138
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, `Validation error: ${error.message}`, {
139
+ schemaId,
140
+ version
141
+ }, error);
142
+ }
143
+ }
144
+ /**
145
+ * Validate batch of records
146
+ */ async validateBatch(records, schemaId, version, options = {}) {
147
+ this.ensureInitialized();
148
+ const result = {
149
+ valid: true,
150
+ totalRecords: records.length,
151
+ validRecords: 0,
152
+ invalidRecords: 0,
153
+ errors: []
154
+ };
155
+ for(let i = 0; i < records.length; i++){
156
+ try {
157
+ await this.validate(records[i], schemaId, version);
158
+ result.validRecords++;
159
+ } catch (error) {
160
+ result.invalidRecords++;
161
+ result.valid = false;
162
+ if (error instanceof StandardError) {
163
+ result.errors.push({
164
+ index: i,
165
+ errors: error.context?.errors || []
166
+ });
167
+ }
168
+ if (options.failFast) {
169
+ break;
170
+ }
171
+ }
172
+ }
173
+ logger.info('Batch validation completed', {
174
+ schemaId,
175
+ version,
176
+ total: result.totalRecords,
177
+ valid: result.validRecords,
178
+ invalid: result.invalidRecords
179
+ });
180
+ return result;
181
+ }
182
+ /**
183
+ * Migrate data from one schema version to another
184
+ */ async migrate(data, schemaId, fromVersion, toVersion) {
185
+ this.ensureInitialized();
186
+ const transition = `${fromVersion}->${toVersion}`;
187
+ const migrationFn = this.migrations[schemaId]?.[transition];
188
+ if (!migrationFn) {
189
+ // Check if migration is needed (same version)
190
+ if (fromVersion === toVersion) {
191
+ return data;
192
+ }
193
+ // No migration function registered
194
+ throw new StandardError(ErrorCode.CONFIGURATION_ERROR, `No migration available for ${schemaId} from ${fromVersion} to ${toVersion}`, {
195
+ schemaId,
196
+ fromVersion,
197
+ toVersion,
198
+ transition
199
+ });
200
+ }
201
+ try {
202
+ const migrated = await migrationFn(data, fromVersion, toVersion);
203
+ logger.info('Schema migration completed', {
204
+ schemaId,
205
+ fromVersion,
206
+ toVersion
207
+ });
208
+ return migrated;
209
+ } catch (error) {
210
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, `Migration failed: ${error.message}`, {
211
+ schemaId,
212
+ fromVersion,
213
+ toVersion
214
+ }, error);
215
+ }
216
+ }
217
+ /**
218
+ * Register a migration function
219
+ */ registerMigration(schemaId, fromVersion, toVersion, migrationFn) {
220
+ const transition = `${fromVersion}->${toVersion}`;
221
+ if (!this.migrations[schemaId]) {
222
+ this.migrations[schemaId] = {};
223
+ }
224
+ this.migrations[schemaId][transition] = migrationFn;
225
+ logger.debug('Migration registered', {
226
+ schemaId,
227
+ transition
228
+ });
229
+ }
230
+ /**
231
+ * Get schema metadata
232
+ */ async getSchema(schemaId, version) {
233
+ const cacheKey = `${schemaId}@${version || 'latest'}`;
234
+ // Check cache
235
+ if (this.config.enableCache && this.schemaCache.has(cacheKey)) {
236
+ return this.schemaCache.get(cacheKey);
237
+ }
238
+ // Load schema from file
239
+ const schema = await this.loadSchema(schemaId, version);
240
+ // Cache schema
241
+ if (this.config.enableCache) {
242
+ this.schemaCache.set(cacheKey, schema);
243
+ // Enforce cache size limit
244
+ if (this.schemaCache.size > this.config.maxCacheSize) {
245
+ const firstKey = this.schemaCache.keys().next().value;
246
+ this.schemaCache.delete(firstKey);
247
+ }
248
+ }
249
+ return schema;
250
+ }
251
+ /**
252
+ * Check if schema exists
253
+ */ async hasSchema(schemaId, version) {
254
+ try {
255
+ await this.getSchema(schemaId, version);
256
+ return true;
257
+ } catch {
258
+ return false;
259
+ }
260
+ }
261
+ /**
262
+ * List all available schemas
263
+ */ async listSchemas(category) {
264
+ this.ensureInitialized();
265
+ const schemas = Array.from(this.schemaCache.keys()).map((key)=>key.split('@')[0]) // Remove version
266
+ .filter((id, index, self)=>self.indexOf(id) === index); // Unique
267
+ if (category) {
268
+ return schemas.filter((id)=>id.startsWith(`${category}/`));
269
+ }
270
+ return schemas;
271
+ }
272
+ /**
273
+ * Get all available versions for a schema
274
+ */ async getVersions(schemaId) {
275
+ const versions = Array.from(this.schemaCache.keys()).filter((key)=>key.startsWith(`${schemaId}@`)).map((key)=>key.split('@')[1]).filter((v)=>v !== 'latest');
276
+ // Also check filesystem for versions not yet cached
277
+ const schemaDir = path.join(this.config.schemaPath, schemaId);
278
+ try {
279
+ const files = await fs.readdir(schemaDir);
280
+ const fileVersions = files.filter((f)=>f.endsWith(this.config.schemaExtension)).map((f)=>{
281
+ const match = f.match(/v([\d.]+)/);
282
+ return match ? match[1] : null;
283
+ }).filter((v)=>v !== null);
284
+ // Merge and deduplicate
285
+ const allVersions = [
286
+ ...new Set([
287
+ ...versions,
288
+ ...fileVersions
289
+ ])
290
+ ];
291
+ return allVersions.sort();
292
+ } catch {
293
+ return versions;
294
+ }
295
+ }
296
+ /**
297
+ * Get integration categories
298
+ */ async getCategories() {
299
+ return [
300
+ ...INTEGRATION_CATEGORIES
301
+ ];
302
+ }
303
+ /**
304
+ * Get validator configuration
305
+ */ getConfig() {
306
+ return {
307
+ ...this.config
308
+ };
309
+ }
310
+ // ============================================================================
311
+ // Private Methods
312
+ // ============================================================================
313
+ ensureInitialized() {
314
+ if (!this.initialized) {
315
+ throw new StandardError(ErrorCode.CONFIGURATION_ERROR, 'Schema validator not initialized. Call initialize() first.', {
316
+ initialized: this.initialized
317
+ });
318
+ }
319
+ }
320
+ async loadSchemaDirectory() {
321
+ const loadedCategories = [];
322
+ for (const category of INTEGRATION_CATEGORIES){
323
+ const categoryPath = path.join(this.config.schemaPath, category);
324
+ try {
325
+ await fs.access(categoryPath);
326
+ await this.loadCategorySchemas(category);
327
+ loadedCategories.push(category);
328
+ } catch (error) {
329
+ logger.warn(`Category directory not found: ${category}`, {
330
+ categoryPath
331
+ });
332
+ }
333
+ }
334
+ return loadedCategories;
335
+ }
336
+ async loadCategorySchemas(category) {
337
+ const categoryPath = path.join(this.config.schemaPath, category);
338
+ try {
339
+ const entries = await fs.readdir(categoryPath, {
340
+ withFileTypes: true
341
+ });
342
+ for (const entry of entries){
343
+ if (entry.isDirectory()) {
344
+ // Schema subdirectory (e.g., pattern-deployment/)
345
+ const schemaName = entry.name;
346
+ const schemaId = `${category}/${schemaName}`;
347
+ await this.loadSchemaVersions(schemaId, path.join(categoryPath, schemaName));
348
+ } else if (entry.isFile() && entry.name.endsWith(this.config.schemaExtension)) {
349
+ // Direct schema file
350
+ const schemaName = entry.name.replace(this.config.schemaExtension, '');
351
+ const schemaId = `${category}/${schemaName}`;
352
+ await this.loadSchemaFile(schemaId, path.join(categoryPath, entry.name), '1.0.0');
353
+ }
354
+ }
355
+ } catch (error) {
356
+ logger.error(`Failed to load schemas for category: ${category}`, error, {
357
+ categoryPath
358
+ });
359
+ }
360
+ }
361
+ async loadSchemaVersions(schemaId, schemaDir) {
362
+ try {
363
+ const files = await fs.readdir(schemaDir);
364
+ for (const file of files){
365
+ if (file.endsWith(this.config.schemaExtension)) {
366
+ const versionMatch = file.match(/v([\d.]+)/);
367
+ const version = versionMatch ? versionMatch[1] : '1.0.0';
368
+ const filePath = path.join(schemaDir, file);
369
+ await this.loadSchemaFile(schemaId, filePath, version);
370
+ }
371
+ }
372
+ } catch (error) {
373
+ logger.error(`Failed to load schema versions: ${schemaId}`, error, {
374
+ schemaDir
375
+ });
376
+ }
377
+ }
378
+ async loadSchemaFile(schemaId, filePath, version) {
379
+ try {
380
+ // Check if already loaded in cache
381
+ const cacheKey = `${schemaId}@${version}`;
382
+ if (this.schemaCache.has(cacheKey)) {
383
+ logger.debug('Schema already cached', {
384
+ schemaId,
385
+ version
386
+ });
387
+ return;
388
+ }
389
+ const content = await fs.readFile(filePath, 'utf-8');
390
+ const schema = JSON.parse(content);
391
+ // Check if schema with this $id already exists in Ajv
392
+ const schemaKey = schema.$id || `${schemaId}/${version}`;
393
+ if (this.ajv.getSchema(schemaKey)) {
394
+ logger.debug('Schema already compiled in Ajv', {
395
+ schemaId,
396
+ version,
397
+ schemaKey
398
+ });
399
+ // Use existing compiled schema
400
+ const validator = this.ajv.getSchema(schemaKey);
401
+ const category = schemaId.split('/')[0];
402
+ const metadata = {
403
+ id: schemaId,
404
+ version,
405
+ category,
406
+ description: schema.description,
407
+ validator
408
+ };
409
+ this.schemaCache.set(cacheKey, metadata);
410
+ return;
411
+ }
412
+ // Compile schema with Ajv
413
+ const validator = this.ajv.compile(schema);
414
+ // Extract category from schemaId
415
+ const category = schemaId.split('/')[0];
416
+ const metadata = {
417
+ id: schemaId,
418
+ version,
419
+ category,
420
+ description: schema.description,
421
+ validator
422
+ };
423
+ // Cache with version
424
+ this.schemaCache.set(cacheKey, metadata);
425
+ logger.debug('Schema loaded', {
426
+ schemaId,
427
+ version,
428
+ filePath
429
+ });
430
+ } catch (error) {
431
+ logger.error(`Failed to load schema file: ${filePath}`, error, {
432
+ schemaId,
433
+ version
434
+ });
435
+ throw error;
436
+ }
437
+ }
438
+ async loadSchema(schemaId, version) {
439
+ const category = schemaId.split('/')[0];
440
+ const schemaName = schemaId.split('/').slice(1).join('/');
441
+ // Determine file path
442
+ const categoryPath = path.join(this.config.schemaPath, category);
443
+ const schemaPath = path.join(categoryPath, schemaName);
444
+ // Try versioned schema directory
445
+ try {
446
+ const versionedFile = version ? `v${version}${this.config.schemaExtension}` : `v1.0.0${this.config.schemaExtension}`;
447
+ const filePath = path.join(schemaPath, versionedFile);
448
+ await fs.access(filePath);
449
+ const actualVersion = version || '1.0.0';
450
+ await this.loadSchemaFile(schemaId, filePath, actualVersion);
451
+ return this.schemaCache.get(`${schemaId}@${actualVersion}`);
452
+ } catch {
453
+ // Try direct schema file
454
+ const directFile = path.join(categoryPath, `${schemaName}${this.config.schemaExtension}`);
455
+ try {
456
+ await fs.access(directFile);
457
+ const actualVersion = version || '1.0.0';
458
+ await this.loadSchemaFile(schemaId, directFile, actualVersion);
459
+ return this.schemaCache.get(`${schemaId}@${actualVersion}`);
460
+ } catch (error) {
461
+ throw new StandardError(ErrorCode.FILE_NOT_FOUND, `Schema not found: ${schemaId}${version ? `@${version}` : ''}`, {
462
+ schemaId,
463
+ version,
464
+ searchPaths: [
465
+ schemaPath,
466
+ directFile
467
+ ]
468
+ }, error);
469
+ }
470
+ }
471
+ }
472
+ formatErrors(errors) {
473
+ return errors.map((error)=>({
474
+ path: error.instancePath || error.schemaPath,
475
+ message: error.message || 'Validation failed',
476
+ keyword: error.keyword,
477
+ params: error.params
478
+ }));
479
+ }
480
+ generateSuggestions(errors, data) {
481
+ const suggestions = [];
482
+ for (const error of errors){
483
+ if (error.keyword === 'required' && error.params?.missingProperty) {
484
+ const missing = error.params.missingProperty;
485
+ suggestions.push(missing);
486
+ // Check for typos in data keys
487
+ const dataKeys = Object.keys(data);
488
+ const similar = dataKeys.filter((key)=>this.levenshteinDistance(key, missing) <= 2);
489
+ if (similar.length > 0) {
490
+ suggestions.push(`Did you mean: ${similar.join(', ')}?`);
491
+ }
492
+ }
493
+ }
494
+ return [
495
+ ...new Set(suggestions)
496
+ ]; // Deduplicate
497
+ }
498
+ levenshteinDistance(a, b) {
499
+ const matrix = [];
500
+ for(let i = 0; i <= b.length; i++){
501
+ matrix[i] = [
502
+ i
503
+ ];
504
+ }
505
+ for(let j = 0; j <= a.length; j++){
506
+ matrix[0][j] = j;
507
+ }
508
+ for(let i = 1; i <= b.length; i++){
509
+ for(let j = 1; j <= a.length; j++){
510
+ if (b.charAt(i - 1) === a.charAt(j - 1)) {
511
+ matrix[i][j] = matrix[i - 1][j - 1];
512
+ } else {
513
+ matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1 // deletion
514
+ );
515
+ }
516
+ }
517
+ }
518
+ return matrix[b.length][a.length];
519
+ }
520
+ }
521
+
522
+ //# sourceMappingURL=integration-schema-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/integration-schema-validator.ts"],"sourcesContent":["/**\r\n * Integration Schema Validator\r\n *\r\n * Task: P2-3.2 - JSON Schema Validation Enforcement\r\n * Enforces JSON Schema validation at all 47 integration points\r\n *\r\n * Features:\r\n * - Automatic validation at data boundaries\r\n * - Schema registry with versioning\r\n * - Migration support between schema versions\r\n * - Performance: <50ms validation, <100ms schema loading\r\n * - Comprehensive error reporting with StandardError\r\n *\r\n * @module integration-schema-validator\r\n */\r\n\r\nimport Ajv, { ValidateFunction, ErrorObject } from 'ajv';\r\nimport addFormats from 'ajv-formats';\r\nimport { StandardError, ErrorCode, createValidationError } from './errors.js';\r\nimport { getGlobalLogger } from './logging.js';\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\n\r\nconst logger = getGlobalLogger();\r\n\r\n// ============================================================================\r\n// Type Definitions\r\n// ============================================================================\r\n\r\nexport interface SchemaValidatorConfig {\r\n /**\r\n * Path to directory containing JSON schemas\r\n */\r\n schemaPath: string;\r\n\r\n /**\r\n * Enable schema caching for performance\r\n * @default true\r\n */\r\n enableCache?: boolean;\r\n\r\n /**\r\n * Strict mode - fail on additional properties\r\n * @default true\r\n */\r\n strictMode?: boolean;\r\n\r\n /**\r\n * Maximum cache size (number of schemas)\r\n * @default 1000\r\n */\r\n maxCacheSize?: number;\r\n\r\n /**\r\n * Schema file extension\r\n * @default '.schema.json'\r\n */\r\n schemaExtension?: string;\r\n}\r\n\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors?: ValidationError[];\r\n warnings?: string[];\r\n}\r\n\r\nexport interface ValidationError {\r\n path: string;\r\n message: string;\r\n keyword?: string;\r\n params?: Record<string, any>;\r\n}\r\n\r\nexport interface BatchValidationResult {\r\n valid: boolean;\r\n totalRecords: number;\r\n validRecords: number;\r\n invalidRecords: number;\r\n errors: Array<{\r\n index: number;\r\n errors: ValidationError[];\r\n }>;\r\n}\r\n\r\nexport interface BatchValidationOptions {\r\n /**\r\n * Stop validation on first error\r\n * @default false\r\n */\r\n failFast?: boolean;\r\n\r\n /**\r\n * Include valid records in result\r\n * @default false\r\n */\r\n includeValidRecords?: boolean;\r\n}\r\n\r\nexport type MigrationFunction = (data: any, fromVersion: string, toVersion: string) => Promise<any>;\r\n\r\ninterface SchemaMetadata {\r\n id: string;\r\n version: string;\r\n category: string;\r\n description?: string;\r\n validator: ValidateFunction;\r\n}\r\n\r\ninterface MigrationRegistry {\r\n [schemaId: string]: {\r\n [transition: string]: MigrationFunction; // \"1.0.0->2.0.0\"\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Integration Categories (6 categories, 47 points total)\r\n// ============================================================================\r\n\r\nconst INTEGRATION_CATEGORIES = [\r\n 'database-handoffs', // 9 points\r\n 'file-operations', // 11 points\r\n 'cfn-loop-communication', // 8 points\r\n 'phase4-workflow', // 7 points\r\n 'api-layer', // 7 points\r\n 'data-format-transformations', // 5 points\r\n] as const;\r\n\r\nexport type IntegrationCategory = typeof INTEGRATION_CATEGORIES[number];\r\n\r\n// ============================================================================\r\n// IntegrationSchemaValidator Class\r\n// ============================================================================\r\n\r\nexport class IntegrationSchemaValidator {\r\n private config: Required<SchemaValidatorConfig>;\r\n private ajv: Ajv;\r\n private schemaCache: Map<string, SchemaMetadata>;\r\n private migrations: MigrationRegistry;\r\n private initialized: boolean = false;\r\n\r\n constructor(config: SchemaValidatorConfig) {\r\n this.config = {\r\n schemaPath: config.schemaPath,\r\n enableCache: config.enableCache ?? true,\r\n strictMode: config.strictMode ?? true,\r\n maxCacheSize: config.maxCacheSize ?? 1000,\r\n schemaExtension: config.schemaExtension ?? '.schema.json',\r\n };\r\n\r\n // Initialize Ajv with formats support\r\n this.ajv = new Ajv({\r\n allErrors: true, // Report all errors, not just first\r\n strict: this.config.strictMode,\r\n validateFormats: true,\r\n verbose: true, // Include schema and data in error messages\r\n });\r\n\r\n addFormats(this.ajv); // Add format validators (date-time, email, uri, etc.)\r\n\r\n this.schemaCache = new Map();\r\n this.migrations = {};\r\n\r\n logger.debug('IntegrationSchemaValidator initialized', {\r\n schemaPath: this.config.schemaPath,\r\n enableCache: this.config.enableCache,\r\n strictMode: this.config.strictMode,\r\n });\r\n }\r\n\r\n /**\r\n * Initialize validator by loading all schemas\r\n */\r\n async initialize(): Promise<void> {\r\n if (this.initialized) {\r\n return;\r\n }\r\n\r\n try {\r\n // Verify schema directory exists\r\n await fs.access(this.config.schemaPath);\r\n\r\n // Load all schemas from directory\r\n const categories = await this.loadSchemaDirectory();\r\n\r\n logger.info('Schema validator initialized', {\r\n categories: categories.length,\r\n schemasLoaded: this.schemaCache.size,\r\n });\r\n\r\n this.initialized = true;\r\n } catch (error) {\r\n logger.error('Failed to initialize schema validator', error as Error, {\r\n schemaPath: this.config.schemaPath,\r\n });\r\n\r\n throw new StandardError(\r\n ErrorCode.CONFIGURATION_ERROR,\r\n `Failed to initialize schema validator: ${(error as Error).message}`,\r\n { schemaPath: this.config.schemaPath },\r\n error as Error\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Shutdown validator and clear caches\r\n */\r\n async shutdown(): Promise<void> {\r\n this.schemaCache.clear();\r\n this.migrations = {};\r\n this.initialized = false;\r\n\r\n logger.debug('Schema validator shutdown complete');\r\n }\r\n\r\n /**\r\n * Validate data against a schema\r\n *\r\n * @param data - Data to validate\r\n * @param schemaId - Schema identifier (e.g., \"database-handoffs/pattern-deployment\")\r\n * @param version - Schema version (defaults to latest)\r\n * @throws StandardError with VALIDATION_FAILED code if validation fails\r\n */\r\n async validate(data: any, schemaId: string, version?: string): Promise<void> {\r\n this.ensureInitialized();\r\n\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Get schema validator\r\n const schema = await this.getSchema(schemaId, version);\r\n\r\n // Perform validation\r\n const valid = schema.validator(data);\r\n\r\n if (!valid) {\r\n const errors = this.formatErrors(schema.validator.errors || []);\r\n\r\n logger.warn('Schema validation failed', {\r\n schemaId,\r\n version: schema.version,\r\n errorCount: errors.length,\r\n duration: Date.now() - startTime,\r\n });\r\n\r\n throw new StandardError(\r\n ErrorCode.VALIDATION_FAILED,\r\n `Schema validation failed for ${schemaId}@${schema.version}`,\r\n {\r\n schemaId,\r\n version: schema.version,\r\n errors,\r\n suggestions: this.generateSuggestions(errors, data),\r\n }\r\n );\r\n }\r\n\r\n logger.debug('Schema validation succeeded', {\r\n schemaId,\r\n version: schema.version,\r\n duration: Date.now() - startTime,\r\n });\r\n } catch (error) {\r\n if (error instanceof StandardError) {\r\n throw error;\r\n }\r\n\r\n throw new StandardError(\r\n ErrorCode.VALIDATION_FAILED,\r\n `Validation error: ${(error as Error).message}`,\r\n { schemaId, version },\r\n error as Error\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Validate batch of records\r\n */\r\n async validateBatch(\r\n records: any[],\r\n schemaId: string,\r\n version?: string,\r\n options: BatchValidationOptions = {}\r\n ): Promise<BatchValidationResult> {\r\n this.ensureInitialized();\r\n\r\n const result: BatchValidationResult = {\r\n valid: true,\r\n totalRecords: records.length,\r\n validRecords: 0,\r\n invalidRecords: 0,\r\n errors: [],\r\n };\r\n\r\n for (let i = 0; i < records.length; i++) {\r\n try {\r\n await this.validate(records[i], schemaId, version);\r\n result.validRecords++;\r\n } catch (error) {\r\n result.invalidRecords++;\r\n result.valid = false;\r\n\r\n if (error instanceof StandardError) {\r\n result.errors.push({\r\n index: i,\r\n errors: error.context?.errors || [],\r\n });\r\n }\r\n\r\n if (options.failFast) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n logger.info('Batch validation completed', {\r\n schemaId,\r\n version,\r\n total: result.totalRecords,\r\n valid: result.validRecords,\r\n invalid: result.invalidRecords,\r\n });\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Migrate data from one schema version to another\r\n */\r\n async migrate(\r\n data: any,\r\n schemaId: string,\r\n fromVersion: string,\r\n toVersion: string\r\n ): Promise<any> {\r\n this.ensureInitialized();\r\n\r\n const transition = `${fromVersion}->${toVersion}`;\r\n const migrationFn = this.migrations[schemaId]?.[transition];\r\n\r\n if (!migrationFn) {\r\n // Check if migration is needed (same version)\r\n if (fromVersion === toVersion) {\r\n return data;\r\n }\r\n\r\n // No migration function registered\r\n throw new StandardError(\r\n ErrorCode.CONFIGURATION_ERROR,\r\n `No migration available for ${schemaId} from ${fromVersion} to ${toVersion}`,\r\n { schemaId, fromVersion, toVersion, transition }\r\n );\r\n }\r\n\r\n try {\r\n const migrated = await migrationFn(data, fromVersion, toVersion);\r\n\r\n logger.info('Schema migration completed', {\r\n schemaId,\r\n fromVersion,\r\n toVersion,\r\n });\r\n\r\n return migrated;\r\n } catch (error) {\r\n throw new StandardError(\r\n ErrorCode.VALIDATION_FAILED,\r\n `Migration failed: ${(error as Error).message}`,\r\n { schemaId, fromVersion, toVersion },\r\n error as Error\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Register a migration function\r\n */\r\n registerMigration(\r\n schemaId: string,\r\n fromVersion: string,\r\n toVersion: string,\r\n migrationFn: MigrationFunction\r\n ): void {\r\n const transition = `${fromVersion}->${toVersion}`;\r\n\r\n if (!this.migrations[schemaId]) {\r\n this.migrations[schemaId] = {};\r\n }\r\n\r\n this.migrations[schemaId][transition] = migrationFn;\r\n\r\n logger.debug('Migration registered', { schemaId, transition });\r\n }\r\n\r\n /**\r\n * Get schema metadata\r\n */\r\n async getSchema(schemaId: string, version?: string): Promise<SchemaMetadata> {\r\n const cacheKey = `${schemaId}@${version || 'latest'}`;\r\n\r\n // Check cache\r\n if (this.config.enableCache && this.schemaCache.has(cacheKey)) {\r\n return this.schemaCache.get(cacheKey)!;\r\n }\r\n\r\n // Load schema from file\r\n const schema = await this.loadSchema(schemaId, version);\r\n\r\n // Cache schema\r\n if (this.config.enableCache) {\r\n this.schemaCache.set(cacheKey, schema);\r\n\r\n // Enforce cache size limit\r\n if (this.schemaCache.size > this.config.maxCacheSize) {\r\n const firstKey = this.schemaCache.keys().next().value;\r\n this.schemaCache.delete(firstKey);\r\n }\r\n }\r\n\r\n return schema;\r\n }\r\n\r\n /**\r\n * Check if schema exists\r\n */\r\n async hasSchema(schemaId: string, version?: string): Promise<boolean> {\r\n try {\r\n await this.getSchema(schemaId, version);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * List all available schemas\r\n */\r\n async listSchemas(category?: IntegrationCategory): Promise<string[]> {\r\n this.ensureInitialized();\r\n\r\n const schemas = Array.from(this.schemaCache.keys())\r\n .map((key) => key.split('@')[0]) // Remove version\r\n .filter((id, index, self) => self.indexOf(id) === index); // Unique\r\n\r\n if (category) {\r\n return schemas.filter((id) => id.startsWith(`${category}/`));\r\n }\r\n\r\n return schemas;\r\n }\r\n\r\n /**\r\n * Get all available versions for a schema\r\n */\r\n async getVersions(schemaId: string): Promise<string[]> {\r\n const versions = Array.from(this.schemaCache.keys())\r\n .filter((key) => key.startsWith(`${schemaId}@`))\r\n .map((key) => key.split('@')[1])\r\n .filter((v) => v !== 'latest');\r\n\r\n // Also check filesystem for versions not yet cached\r\n const schemaDir = path.join(this.config.schemaPath, schemaId);\r\n\r\n try {\r\n const files = await fs.readdir(schemaDir);\r\n const fileVersions = files\r\n .filter((f) => f.endsWith(this.config.schemaExtension))\r\n .map((f) => {\r\n const match = f.match(/v([\\d.]+)/);\r\n return match ? match[1] : null;\r\n })\r\n .filter((v): v is string => v !== null);\r\n\r\n // Merge and deduplicate\r\n const allVersions = [...new Set([...versions, ...fileVersions])];\r\n return allVersions.sort();\r\n } catch {\r\n return versions;\r\n }\r\n }\r\n\r\n /**\r\n * Get integration categories\r\n */\r\n async getCategories(): Promise<IntegrationCategory[]> {\r\n return [...INTEGRATION_CATEGORIES];\r\n }\r\n\r\n /**\r\n * Get validator configuration\r\n */\r\n getConfig(): Required<SchemaValidatorConfig> {\r\n return { ...this.config };\r\n }\r\n\r\n // ============================================================================\r\n // Private Methods\r\n // ============================================================================\r\n\r\n private ensureInitialized(): void {\r\n if (!this.initialized) {\r\n throw new StandardError(\r\n ErrorCode.CONFIGURATION_ERROR,\r\n 'Schema validator not initialized. Call initialize() first.',\r\n { initialized: this.initialized }\r\n );\r\n }\r\n }\r\n\r\n private async loadSchemaDirectory(): Promise<IntegrationCategory[]> {\r\n const loadedCategories: IntegrationCategory[] = [];\r\n\r\n for (const category of INTEGRATION_CATEGORIES) {\r\n const categoryPath = path.join(this.config.schemaPath, category);\r\n\r\n try {\r\n await fs.access(categoryPath);\r\n await this.loadCategorySchemas(category);\r\n loadedCategories.push(category);\r\n } catch (error) {\r\n logger.warn(`Category directory not found: ${category}`, {\r\n categoryPath,\r\n });\r\n }\r\n }\r\n\r\n return loadedCategories;\r\n }\r\n\r\n private async loadCategorySchemas(category: IntegrationCategory): Promise<void> {\r\n const categoryPath = path.join(this.config.schemaPath, category);\r\n\r\n try {\r\n const entries = await fs.readdir(categoryPath, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n if (entry.isDirectory()) {\r\n // Schema subdirectory (e.g., pattern-deployment/)\r\n const schemaName = entry.name;\r\n const schemaId = `${category}/${schemaName}`;\r\n await this.loadSchemaVersions(schemaId, path.join(categoryPath, schemaName));\r\n } else if (entry.isFile() && entry.name.endsWith(this.config.schemaExtension)) {\r\n // Direct schema file\r\n const schemaName = entry.name.replace(this.config.schemaExtension, '');\r\n const schemaId = `${category}/${schemaName}`;\r\n await this.loadSchemaFile(schemaId, path.join(categoryPath, entry.name), '1.0.0');\r\n }\r\n }\r\n } catch (error) {\r\n logger.error(`Failed to load schemas for category: ${category}`, error as Error, {\r\n categoryPath,\r\n });\r\n }\r\n }\r\n\r\n private async loadSchemaVersions(schemaId: string, schemaDir: string): Promise<void> {\r\n try {\r\n const files = await fs.readdir(schemaDir);\r\n\r\n for (const file of files) {\r\n if (file.endsWith(this.config.schemaExtension)) {\r\n const versionMatch = file.match(/v([\\d.]+)/);\r\n const version = versionMatch ? versionMatch[1] : '1.0.0';\r\n const filePath = path.join(schemaDir, file);\r\n\r\n await this.loadSchemaFile(schemaId, filePath, version);\r\n }\r\n }\r\n } catch (error) {\r\n logger.error(`Failed to load schema versions: ${schemaId}`, error as Error, {\r\n schemaDir,\r\n });\r\n }\r\n }\r\n\r\n private async loadSchemaFile(\r\n schemaId: string,\r\n filePath: string,\r\n version: string\r\n ): Promise<void> {\r\n try {\r\n // Check if already loaded in cache\r\n const cacheKey = `${schemaId}@${version}`;\r\n if (this.schemaCache.has(cacheKey)) {\r\n logger.debug('Schema already cached', { schemaId, version });\r\n return;\r\n }\r\n\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n const schema = JSON.parse(content);\r\n\r\n // Check if schema with this $id already exists in Ajv\r\n const schemaKey = schema.$id || `${schemaId}/${version}`;\r\n if (this.ajv.getSchema(schemaKey)) {\r\n logger.debug('Schema already compiled in Ajv', { schemaId, version, schemaKey });\r\n // Use existing compiled schema\r\n const validator = this.ajv.getSchema(schemaKey)!;\r\n\r\n const category = schemaId.split('/')[0] as IntegrationCategory;\r\n const metadata: SchemaMetadata = {\r\n id: schemaId,\r\n version,\r\n category,\r\n description: schema.description,\r\n validator,\r\n };\r\n\r\n this.schemaCache.set(cacheKey, metadata);\r\n return;\r\n }\r\n\r\n // Compile schema with Ajv\r\n const validator = this.ajv.compile(schema);\r\n\r\n // Extract category from schemaId\r\n const category = schemaId.split('/')[0] as IntegrationCategory;\r\n\r\n const metadata: SchemaMetadata = {\r\n id: schemaId,\r\n version,\r\n category,\r\n description: schema.description,\r\n validator,\r\n };\r\n\r\n // Cache with version\r\n this.schemaCache.set(cacheKey, metadata);\r\n\r\n logger.debug('Schema loaded', { schemaId, version, filePath });\r\n } catch (error) {\r\n logger.error(`Failed to load schema file: ${filePath}`, error as Error, {\r\n schemaId,\r\n version,\r\n });\r\n throw error;\r\n }\r\n }\r\n\r\n private async loadSchema(schemaId: string, version?: string): Promise<SchemaMetadata> {\r\n const category = schemaId.split('/')[0] as IntegrationCategory;\r\n const schemaName = schemaId.split('/').slice(1).join('/');\r\n\r\n // Determine file path\r\n const categoryPath = path.join(this.config.schemaPath, category);\r\n const schemaPath = path.join(categoryPath, schemaName);\r\n\r\n // Try versioned schema directory\r\n try {\r\n const versionedFile = version\r\n ? `v${version}${this.config.schemaExtension}`\r\n : `v1.0.0${this.config.schemaExtension}`;\r\n\r\n const filePath = path.join(schemaPath, versionedFile);\r\n await fs.access(filePath);\r\n\r\n const actualVersion = version || '1.0.0';\r\n await this.loadSchemaFile(schemaId, filePath, actualVersion);\r\n\r\n return this.schemaCache.get(`${schemaId}@${actualVersion}`)!;\r\n } catch {\r\n // Try direct schema file\r\n const directFile = path.join(categoryPath, `${schemaName}${this.config.schemaExtension}`);\r\n\r\n try {\r\n await fs.access(directFile);\r\n\r\n const actualVersion = version || '1.0.0';\r\n await this.loadSchemaFile(schemaId, directFile, actualVersion);\r\n\r\n return this.schemaCache.get(`${schemaId}@${actualVersion}`)!;\r\n } catch (error) {\r\n throw new StandardError(\r\n ErrorCode.FILE_NOT_FOUND,\r\n `Schema not found: ${schemaId}${version ? `@${version}` : ''}`,\r\n { schemaId, version, searchPaths: [schemaPath, directFile] },\r\n error as Error\r\n );\r\n }\r\n }\r\n }\r\n\r\n private formatErrors(errors: ErrorObject[]): ValidationError[] {\r\n return errors.map((error) => ({\r\n path: error.instancePath || error.schemaPath,\r\n message: error.message || 'Validation failed',\r\n keyword: error.keyword,\r\n params: error.params,\r\n }));\r\n }\r\n\r\n private generateSuggestions(errors: ValidationError[], data: any): string[] {\r\n const suggestions: string[] = [];\r\n\r\n for (const error of errors) {\r\n if (error.keyword === 'required' && error.params?.missingProperty) {\r\n const missing = error.params.missingProperty;\r\n suggestions.push(missing);\r\n\r\n // Check for typos in data keys\r\n const dataKeys = Object.keys(data);\r\n const similar = dataKeys.filter(\r\n (key) => this.levenshteinDistance(key, missing) <= 2\r\n );\r\n\r\n if (similar.length > 0) {\r\n suggestions.push(`Did you mean: ${similar.join(', ')}?`);\r\n }\r\n }\r\n }\r\n\r\n return [...new Set(suggestions)]; // Deduplicate\r\n }\r\n\r\n private levenshteinDistance(a: string, b: string): number {\r\n const matrix: number[][] = [];\r\n\r\n for (let i = 0; i <= b.length; i++) {\r\n matrix[i] = [i];\r\n }\r\n\r\n for (let j = 0; j <= a.length; j++) {\r\n matrix[0][j] = j;\r\n }\r\n\r\n for (let i = 1; i <= b.length; i++) {\r\n for (let j = 1; j <= a.length; j++) {\r\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\r\n matrix[i][j] = matrix[i - 1][j - 1];\r\n } else {\r\n matrix[i][j] = Math.min(\r\n matrix[i - 1][j - 1] + 1, // substitution\r\n matrix[i][j - 1] + 1, // insertion\r\n matrix[i - 1][j] + 1 // deletion\r\n );\r\n }\r\n }\r\n }\r\n\r\n return matrix[b.length][a.length];\r\n }\r\n}\r\n"],"names":["Ajv","addFormats","StandardError","ErrorCode","getGlobalLogger","fs","path","logger","INTEGRATION_CATEGORIES","IntegrationSchemaValidator","config","ajv","schemaCache","migrations","initialized","schemaPath","enableCache","strictMode","maxCacheSize","schemaExtension","allErrors","strict","validateFormats","verbose","Map","debug","initialize","access","categories","loadSchemaDirectory","info","length","schemasLoaded","size","error","CONFIGURATION_ERROR","message","shutdown","clear","validate","data","schemaId","version","ensureInitialized","startTime","Date","now","schema","getSchema","valid","validator","errors","formatErrors","warn","errorCount","duration","VALIDATION_FAILED","suggestions","generateSuggestions","validateBatch","records","options","result","totalRecords","validRecords","invalidRecords","i","push","index","context","failFast","total","invalid","migrate","fromVersion","toVersion","transition","migrationFn","migrated","registerMigration","cacheKey","has","get","loadSchema","set","firstKey","keys","next","value","delete","hasSchema","listSchemas","category","schemas","Array","from","map","key","split","filter","id","self","indexOf","startsWith","getVersions","versions","v","schemaDir","join","files","readdir","fileVersions","f","endsWith","match","allVersions","Set","sort","getCategories","getConfig","loadedCategories","categoryPath","loadCategorySchemas","entries","withFileTypes","entry","isDirectory","schemaName","name","loadSchemaVersions","isFile","replace","loadSchemaFile","file","versionMatch","filePath","content","readFile","JSON","parse","schemaKey","$id","metadata","description","compile","slice","versionedFile","actualVersion","directFile","FILE_NOT_FOUND","searchPaths","instancePath","keyword","params","missingProperty","missing","dataKeys","Object","similar","levenshteinDistance","a","b","matrix","j","charAt","Math","min"],"mappings":"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"}