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/schema-transform.ts"],"sourcesContent":["/**\r\n * Schema Transform Library\r\n *\r\n * Provides bidirectional transformations between SQLite and Redis schemas.\r\n * Ensures data consistency and prevents data loss during transformations.\r\n *\r\n * Task: Integration Standardization Plan - Task 2.2\r\n * Version: 1.0.0\r\n */\r\n\r\nimport { getGlobalLogger } from './logging.js';\r\nimport { StandardError } from './errors.js';\r\n\r\nconst logger = getGlobalLogger();\r\n\r\n// ============================================================================\r\n// Type Definitions\r\n// ============================================================================\r\n\r\nexport type TransformDirection = 'sqlite-to-redis' | 'redis-to-sqlite' | 'postgres-to-sqlite';\r\n\r\nexport type SchemaName = 'agent_executions' | 'skill_executions' | 'artifacts' | 'coordination_events';\r\n\r\nexport interface SQLiteRow {\r\n [key: string]: string | number | null;\r\n}\r\n\r\nexport interface RedisData {\r\n [key: string]: string | number;\r\n}\r\n\r\nexport interface PostgresRow {\r\n [key: string]: any;\r\n}\r\n\r\nexport interface TransformResult<T> {\r\n success: boolean;\r\n data?: T;\r\n errors?: string[];\r\n warnings?: string[];\r\n}\r\n\r\nexport interface SchemaMapping {\r\n version: string;\r\n schema: SchemaName;\r\n fields: FieldMapping[];\r\n primaryKey: string;\r\n ttl?: number;\r\n}\r\n\r\nexport interface FieldMapping {\r\n source: string;\r\n destination: string;\r\n sourceType: string;\r\n destinationType: string;\r\n transform: ((val: any) => any) | null;\r\n required: boolean;\r\n defaultValue?: any;\r\n}\r\n\r\n// ============================================================================\r\n// Type Converters\r\n// ============================================================================\r\n\r\nexport const TYPE_CONVERTERS = {\r\n /**\r\n * DECIMAL to REAL (PostgreSQL → SQLite)\r\n */\r\n 'DECIMAL_TO_REAL': (val: string | number | null): number | null => {\r\n if (val === null || val === undefined) return null;\r\n const num = typeof val === 'string' ? parseFloat(val) : val;\r\n return isNaN(num) ? null : num;\r\n },\r\n\r\n /**\r\n * INTEGER conversion (handles string/number inputs)\r\n */\r\n 'INTEGER': (val: number | string | null): number | null => {\r\n if (val === null || val === undefined) return null;\r\n const num = typeof val === 'string' ? parseInt(val, 10) : val;\r\n return isNaN(num) ? null : num;\r\n },\r\n\r\n /**\r\n * REAL conversion (handles string/number inputs)\r\n */\r\n 'REAL': (val: number | string | null): number | null => {\r\n if (val === null || val === undefined) return null;\r\n const num = typeof val === 'string' ? parseFloat(val) : val;\r\n return isNaN(num) ? null : num;\r\n },\r\n\r\n /**\r\n * Number to string (for Redis storage)\r\n */\r\n 'NUMBER_TO_STRING': (val: number | null): string | null => {\r\n if (val === null || val === undefined) return null;\r\n if (isNaN(val)) return null;\r\n return val.toString();\r\n },\r\n\r\n /**\r\n * String to number (from Redis)\r\n */\r\n 'STRING_TO_NUMBER': (val: string | null): number | null => {\r\n if (val === null || val === undefined || val === '') return null;\r\n const num = parseFloat(val);\r\n return isNaN(num) ? null : num;\r\n },\r\n\r\n /**\r\n * ENUM to TEXT (PostgreSQL → SQLite)\r\n */\r\n 'ENUM_TO_TEXT': (val: string | null): string | null => {\r\n if (val === null || val === undefined) return null;\r\n return val.toString();\r\n },\r\n\r\n /**\r\n * DATETIME string to Unix timestamp (SQLite → Redis)\r\n */\r\n 'DATETIME_TO_TIMESTAMP': (val: string | null): number | null => {\r\n if (val === null || val === undefined) return null;\r\n const timestamp = new Date(val).getTime();\r\n return isNaN(timestamp) ? null : timestamp;\r\n },\r\n\r\n /**\r\n * Unix timestamp to DATETIME string (Redis → SQLite)\r\n */\r\n 'TIMESTAMP_TO_DATETIME': (val: number | string | null): string | null => {\r\n if (val === null || val === undefined) return null;\r\n const num = typeof val === 'string' ? parseInt(val, 10) : val;\r\n if (isNaN(num)) return null;\r\n return new Date(num).toISOString();\r\n },\r\n\r\n /**\r\n * PostgreSQL TIMESTAMP to SQLite DATETIME\r\n */\r\n 'TIMESTAMP_TO_ISO': (val: Date | string | number | null): string | null => {\r\n if (val === null || val === undefined) return null;\r\n try {\r\n if (val instanceof Date) return val.toISOString();\r\n if (typeof val === 'number') return new Date(val * 1000).toISOString();\r\n return new Date(val).toISOString();\r\n } catch {\r\n return null;\r\n }\r\n },\r\n\r\n /**\r\n * Parse JSON string to object\r\n */\r\n 'TEXT_TO_JSON': (val: string | null): any => {\r\n if (val === null || val === undefined || val === '') return null;\r\n try {\r\n return JSON.parse(val);\r\n } catch (err) {\r\n logger.warn('Failed to parse JSON', { value: val, error: (err as Error).message });\r\n return null;\r\n }\r\n },\r\n\r\n /**\r\n * Stringify object to JSON\r\n */\r\n 'JSON_TO_TEXT': (val: any): string | null => {\r\n if (val === null || val === undefined) return null;\r\n try {\r\n return JSON.stringify(val);\r\n } catch (err) {\r\n logger.warn('Failed to stringify JSON', { value: val, error: (err as Error).message });\r\n return null;\r\n }\r\n },\r\n\r\n /**\r\n * Boolean to INTEGER (0/1 for SQLite)\r\n */\r\n 'BOOLEAN_TO_INTEGER': (val: boolean | number | null): number | null => {\r\n if (val === null || val === undefined) return null;\r\n if (typeof val === 'number') return val === 1 ? 1 : 0;\r\n return val ? 1 : 0;\r\n },\r\n\r\n /**\r\n * INTEGER to Boolean (SQLite → JavaScript)\r\n */\r\n 'INTEGER_TO_BOOLEAN': (val: number | string | null): boolean | null => {\r\n if (val === null || val === undefined) return null;\r\n const num = typeof val === 'string' ? parseInt(val, 10) : val;\r\n return num === 1;\r\n },\r\n\r\n /**\r\n * Identity transform (no conversion needed)\r\n */\r\n 'IDENTITY': (val: any): any => val,\r\n};\r\n\r\n// ============================================================================\r\n// Schema Mappings\r\n// ============================================================================\r\n\r\nexport const SCHEMA_MAPPINGS: Record<SchemaName, SchemaMapping> = {\r\n /**\r\n * Agent Executions: Redis ↔ SQLite\r\n */\r\n agent_executions: {\r\n version: '1.0.0',\r\n schema: 'agent_executions',\r\n primaryKey: 'agent_id',\r\n ttl: 86400, // 24 hours in Redis\r\n fields: [\r\n {\r\n source: 'id',\r\n destination: 'agent_id',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'agent_id',\r\n destination: 'agent_id',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'task_id',\r\n destination: 'task_id',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'type',\r\n destination: 'type',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'status',\r\n destination: 'status',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'confidence',\r\n destination: 'confidence',\r\n sourceType: 'REAL',\r\n destinationType: 'string',\r\n transform: null, // Direction-specific\r\n required: false,\r\n },\r\n {\r\n source: 'spawned_at',\r\n destination: 'spawned_at',\r\n sourceType: 'DATETIME',\r\n destinationType: 'number',\r\n transform: null, // Direction-specific\r\n required: true,\r\n },\r\n {\r\n source: 'completed_at',\r\n destination: 'completed_at',\r\n sourceType: 'DATETIME',\r\n destinationType: 'number',\r\n transform: null, // Direction-specific\r\n required: false,\r\n },\r\n {\r\n source: 'metadata',\r\n destination: 'metadata',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: false,\r\n },\r\n ],\r\n },\r\n\r\n /**\r\n * Skill Executions: PostgreSQL → SQLite (one-way)\r\n */\r\n skill_executions: {\r\n version: '1.0.0',\r\n schema: 'skill_executions',\r\n primaryKey: 'id',\r\n fields: [\r\n {\r\n source: 'id',\r\n destination: 'id',\r\n sourceType: 'SERIAL',\r\n destinationType: 'INTEGER',\r\n transform: TYPE_CONVERTERS.INTEGER,\r\n required: true,\r\n },\r\n {\r\n source: 'skill_id',\r\n destination: 'skill_id',\r\n sourceType: 'INTEGER',\r\n destinationType: 'INTEGER',\r\n transform: TYPE_CONVERTERS.INTEGER,\r\n required: true,\r\n },\r\n {\r\n source: 'execution_time_ms',\r\n destination: 'execution_time_ms',\r\n sourceType: 'INTEGER',\r\n destinationType: 'INTEGER',\r\n transform: TYPE_CONVERTERS.INTEGER,\r\n required: true,\r\n },\r\n {\r\n source: 'cost_usd',\r\n destination: 'cost_usd',\r\n sourceType: 'DECIMAL',\r\n destinationType: 'REAL',\r\n transform: TYPE_CONVERTERS.DECIMAL_TO_REAL,\r\n required: false,\r\n },\r\n {\r\n source: 'tokens_avoided',\r\n destination: 'tokens_avoided',\r\n sourceType: 'INTEGER',\r\n destinationType: 'INTEGER',\r\n transform: TYPE_CONVERTERS.INTEGER,\r\n required: false,\r\n },\r\n {\r\n source: 'status',\r\n destination: 'status',\r\n sourceType: 'ENUM',\r\n destinationType: 'TEXT',\r\n transform: TYPE_CONVERTERS.ENUM_TO_TEXT,\r\n required: true,\r\n },\r\n {\r\n source: 'executed_at',\r\n destination: 'executed_at',\r\n sourceType: 'TIMESTAMP',\r\n destinationType: 'DATETIME',\r\n transform: TYPE_CONVERTERS.TIMESTAMP_TO_ISO,\r\n required: true,\r\n },\r\n {\r\n source: 'metadata',\r\n destination: 'metadata',\r\n sourceType: 'JSONB',\r\n destinationType: 'TEXT',\r\n transform: TYPE_CONVERTERS.JSON_TO_TEXT,\r\n required: false,\r\n },\r\n ],\r\n },\r\n\r\n /**\r\n * Artifacts: SQLite ↔ Redis (cache layer)\r\n */\r\n artifacts: {\r\n version: '1.0.0',\r\n schema: 'artifacts',\r\n primaryKey: 'id',\r\n ttl: 2592000, // 30 days in Redis cache\r\n fields: [\r\n {\r\n source: 'id',\r\n destination: 'artifact_id',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'name',\r\n destination: 'name',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'type',\r\n destination: 'type',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'content',\r\n destination: 'content',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: false,\r\n },\r\n {\r\n source: 'content_hash',\r\n destination: 'content_hash',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: false,\r\n },\r\n {\r\n source: 'size_bytes',\r\n destination: 'size_bytes',\r\n sourceType: 'INTEGER',\r\n destinationType: 'string',\r\n transform: null, // Direction-specific\r\n required: false,\r\n },\r\n {\r\n source: 'metadata',\r\n destination: 'metadata',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: false,\r\n },\r\n {\r\n source: 'created_at',\r\n destination: 'created_at',\r\n sourceType: 'DATETIME',\r\n destinationType: 'number',\r\n transform: null, // Direction-specific\r\n required: true,\r\n },\r\n {\r\n source: 'expires_at',\r\n destination: 'expires_at',\r\n sourceType: 'DATETIME',\r\n destinationType: 'number',\r\n transform: null, // Direction-specific\r\n required: false,\r\n },\r\n {\r\n source: 'status',\r\n destination: 'status',\r\n sourceType: 'TEXT',\r\n destinationType: 'string',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n ],\r\n },\r\n\r\n /**\r\n * Coordination Events: Redis → SQLite (archival)\r\n */\r\n coordination_events: {\r\n version: '1.0.0',\r\n schema: 'coordination_events',\r\n primaryKey: 'event_id',\r\n ttl: 3600, // 1 hour in Redis\r\n fields: [\r\n {\r\n source: 'event_id',\r\n destination: 'id',\r\n sourceType: 'string',\r\n destinationType: 'TEXT',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'task_id',\r\n destination: 'task_id',\r\n sourceType: 'string',\r\n destinationType: 'TEXT',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'agent_id',\r\n destination: 'agent_id',\r\n sourceType: 'string',\r\n destinationType: 'TEXT',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: false,\r\n },\r\n {\r\n source: 'event_type',\r\n destination: 'event_type',\r\n sourceType: 'string',\r\n destinationType: 'TEXT',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: true,\r\n },\r\n {\r\n source: 'timestamp',\r\n destination: 'timestamp',\r\n sourceType: 'number',\r\n destinationType: 'DATETIME',\r\n transform: null, // Direction-specific\r\n required: true,\r\n },\r\n {\r\n source: 'payload',\r\n destination: 'payload',\r\n sourceType: 'string',\r\n destinationType: 'TEXT',\r\n transform: TYPE_CONVERTERS.IDENTITY,\r\n required: false,\r\n },\r\n ],\r\n },\r\n};\r\n\r\n// ============================================================================\r\n// Transform Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Transform SQLite row to Redis data\r\n */\r\nexport function sqliteToRedis(schema: SchemaName, row: SQLiteRow): TransformResult<RedisData> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n const result: RedisData = {};\r\n\r\n const mapping = SCHEMA_MAPPINGS[schema];\r\n if (!mapping) {\r\n throw new StandardError(`Unknown schema: ${schema}`, 'SCHEMA_TRANSFORM_ERROR');\r\n }\r\n\r\n for (const field of mapping.fields) {\r\n const value = row[field.source];\r\n\r\n // Handle required fields\r\n if (field.required && (value === null || value === undefined)) {\r\n errors.push(`Required field '${field.source}' is missing`);\r\n continue;\r\n }\r\n\r\n // Skip null/undefined for optional fields\r\n if (value === null || value === undefined) {\r\n continue;\r\n }\r\n\r\n // Apply transformation\r\n let transformed: any;\r\n if (field.transform) {\r\n transformed = field.transform(value);\r\n } else {\r\n // Direction-specific transforms\r\n if (field.sourceType === 'REAL' && field.destinationType === 'string') {\r\n transformed = TYPE_CONVERTERS.NUMBER_TO_STRING(value as number);\r\n } else if (field.sourceType === 'INTEGER' && field.destinationType === 'string') {\r\n transformed = TYPE_CONVERTERS.NUMBER_TO_STRING(value as number);\r\n } else if (field.sourceType === 'DATETIME' && field.destinationType === 'number') {\r\n transformed = TYPE_CONVERTERS.DATETIME_TO_TIMESTAMP(value as string);\r\n } else {\r\n transformed = value;\r\n }\r\n }\r\n\r\n // Validate transformation\r\n if (transformed === null && field.required) {\r\n warnings.push(`Transformation of required field '${field.source}' resulted in null`);\r\n }\r\n\r\n // Only add non-null values to Redis (Redis doesn't have NULL)\r\n if (transformed !== null) {\r\n result[field.destination] = transformed;\r\n }\r\n }\r\n\r\n if (errors.length > 0) {\r\n return { success: false, errors, warnings };\r\n }\r\n\r\n logger.debug('SQLite → Redis transformation completed', {\r\n schema,\r\n fieldCount: Object.keys(result).length,\r\n warnings: warnings.length\r\n });\r\n\r\n return { success: true, data: result, warnings: warnings.length > 0 ? warnings : undefined };\r\n}\r\n\r\n/**\r\n * Transform Redis data to SQLite row\r\n */\r\nexport function redisToSqlite(schema: SchemaName, data: RedisData): TransformResult<SQLiteRow> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n const result: SQLiteRow = {};\r\n\r\n const mapping = SCHEMA_MAPPINGS[schema];\r\n if (!mapping) {\r\n throw new StandardError(`Unknown schema: ${schema}`, 'SCHEMA_TRANSFORM_ERROR');\r\n }\r\n\r\n for (const field of mapping.fields) {\r\n const value = data[field.destination];\r\n\r\n // Handle required fields\r\n if (field.required && (value === null || value === undefined)) {\r\n errors.push(`Required field '${field.destination}' is missing`);\r\n continue;\r\n }\r\n\r\n // Set null for missing optional fields\r\n if (value === null || value === undefined) {\r\n result[field.source] = null;\r\n continue;\r\n }\r\n\r\n // Apply transformation\r\n let transformed: any;\r\n if (field.transform) {\r\n transformed = field.transform(value);\r\n } else {\r\n // Direction-specific transforms\r\n if (field.destinationType === 'string' && field.sourceType === 'REAL') {\r\n transformed = TYPE_CONVERTERS.STRING_TO_NUMBER(value as string);\r\n } else if (field.destinationType === 'string' && field.sourceType === 'INTEGER') {\r\n transformed = TYPE_CONVERTERS.STRING_TO_NUMBER(value as string);\r\n } else if (field.destinationType === 'number' && field.sourceType === 'DATETIME') {\r\n transformed = TYPE_CONVERTERS.TIMESTAMP_TO_DATETIME(value as number);\r\n } else {\r\n transformed = value;\r\n }\r\n }\r\n\r\n // Validate transformation\r\n if (transformed === null && field.required) {\r\n warnings.push(`Transformation of required field '${field.destination}' resulted in null`);\r\n }\r\n\r\n result[field.source] = transformed;\r\n }\r\n\r\n if (errors.length > 0) {\r\n return { success: false, errors, warnings };\r\n }\r\n\r\n logger.debug('Redis → SQLite transformation completed', {\r\n schema,\r\n fieldCount: Object.keys(result).length,\r\n warnings: warnings.length\r\n });\r\n\r\n return { success: true, data: result, warnings: warnings.length > 0 ? warnings : undefined };\r\n}\r\n\r\n/**\r\n * Transform PostgreSQL row to SQLite row (one-way)\r\n */\r\nexport function postgrestoSqlite(schema: SchemaName, row: PostgresRow): TransformResult<SQLiteRow> {\r\n if (schema !== 'skill_executions') {\r\n throw new StandardError(`PostgreSQL → SQLite transform only supports 'skill_executions', got: ${schema}`, 'SCHEMA_TRANSFORM_ERROR');\r\n }\r\n\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n const result: SQLiteRow = {};\r\n\r\n const mapping = SCHEMA_MAPPINGS[schema];\r\n\r\n for (const field of mapping.fields) {\r\n const value = row[field.source];\r\n\r\n // Handle required fields\r\n if (field.required && (value === null || value === undefined)) {\r\n errors.push(`Required field '${field.source}' is missing`);\r\n continue;\r\n }\r\n\r\n // Set null for missing optional fields\r\n if (value === null || value === undefined) {\r\n result[field.destination] = null;\r\n continue;\r\n }\r\n\r\n // Apply transformation\r\n const transformed = field.transform ? field.transform(value) : value;\r\n\r\n // Validate transformation\r\n if (transformed === null && field.required) {\r\n warnings.push(`Transformation of required field '${field.source}' resulted in null`);\r\n }\r\n\r\n result[field.destination] = transformed;\r\n }\r\n\r\n if (errors.length > 0) {\r\n return { success: false, errors, warnings };\r\n }\r\n\r\n logger.debug('PostgreSQL → SQLite transformation completed', {\r\n schema,\r\n fieldCount: Object.keys(result).length,\r\n warnings: warnings.length\r\n });\r\n\r\n return { success: true, data: result, warnings: warnings.length > 0 ? warnings : undefined };\r\n}\r\n\r\n/**\r\n * Transform batch of records\r\n */\r\nexport function transformBatch(\r\n schema: SchemaName,\r\n data: any[],\r\n direction: TransformDirection\r\n): TransformResult<any[]> {\r\n const results: any[] = [];\r\n const allErrors: string[] = [];\r\n const allWarnings: string[] = [];\r\n\r\n for (let i = 0; i < data.length; i++) {\r\n const item = data[i];\r\n let transformResult: TransformResult<any>;\r\n\r\n try {\r\n switch (direction) {\r\n case 'sqlite-to-redis':\r\n transformResult = sqliteToRedis(schema, item);\r\n break;\r\n case 'redis-to-sqlite':\r\n transformResult = redisToSqlite(schema, item);\r\n break;\r\n case 'postgres-to-sqlite':\r\n transformResult = postgrestoSqlite(schema, item);\r\n break;\r\n default:\r\n throw new StandardError(`Unknown transform direction: ${direction}`, 'SCHEMA_TRANSFORM_ERROR');\r\n }\r\n\r\n if (transformResult.success && transformResult.data) {\r\n results.push(transformResult.data);\r\n } else {\r\n allErrors.push(`Record ${i}: ${transformResult.errors?.join(', ')}`);\r\n }\r\n\r\n if (transformResult.warnings) {\r\n allWarnings.push(...transformResult.warnings.map(w => `Record ${i}: ${w}`));\r\n }\r\n } catch (err) {\r\n allErrors.push(`Record ${i}: ${(err as Error).message}`);\r\n }\r\n }\r\n\r\n logger.info('Batch transformation completed', {\r\n schema,\r\n direction,\r\n total: data.length,\r\n succeeded: results.length,\r\n failed: allErrors.length,\r\n warnings: allWarnings.length,\r\n });\r\n\r\n if (allErrors.length > 0) {\r\n return {\r\n success: false,\r\n data: results,\r\n errors: allErrors,\r\n warnings: allWarnings.length > 0 ? allWarnings : undefined\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n data: results,\r\n warnings: allWarnings.length > 0 ? allWarnings : undefined\r\n };\r\n}\r\n\r\n/**\r\n * Get schema mapping for a given schema\r\n */\r\nexport function getSchemaMapping(schema: SchemaName): SchemaMapping {\r\n const mapping = SCHEMA_MAPPINGS[schema];\r\n if (!mapping) {\r\n throw new StandardError(`Unknown schema: ${schema}`, 'SCHEMA_TRANSFORM_ERROR');\r\n }\r\n return mapping;\r\n}\r\n\r\n/**\r\n * Check if transformation is supported\r\n */\r\nexport function isTransformSupported(schema: SchemaName, direction: TransformDirection): boolean {\r\n if (!SCHEMA_MAPPINGS[schema]) {\r\n return false;\r\n }\r\n\r\n // skill_executions only supports postgres-to-sqlite\r\n if (schema === 'skill_executions') {\r\n return direction === 'postgres-to-sqlite';\r\n }\r\n\r\n // Other schemas support bidirectional\r\n return direction === 'sqlite-to-redis' || direction === 'redis-to-sqlite';\r\n}\r\n"],"names":["getGlobalLogger","StandardError","logger","TYPE_CONVERTERS","val","undefined","num","parseFloat","isNaN","parseInt","toString","timestamp","Date","getTime","toISOString","JSON","parse","err","warn","value","error","message","stringify","SCHEMA_MAPPINGS","agent_executions","version","schema","primaryKey","ttl","fields","source","destination","sourceType","destinationType","transform","IDENTITY","required","skill_executions","INTEGER","DECIMAL_TO_REAL","ENUM_TO_TEXT","TIMESTAMP_TO_ISO","JSON_TO_TEXT","artifacts","coordination_events","sqliteToRedis","row","errors","warnings","result","mapping","field","push","transformed","NUMBER_TO_STRING","DATETIME_TO_TIMESTAMP","length","success","debug","fieldCount","Object","keys","data","redisToSqlite","STRING_TO_NUMBER","TIMESTAMP_TO_DATETIME","postgrestoSqlite","transformBatch","direction","results","allErrors","allWarnings","i","item","transformResult","join","map","w","info","total","succeeded","failed","getSchemaMapping","isTransformSupported"],"mappings":"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"}
@@ -0,0 +1,491 @@
1
+ /**
2
+ * Schema Validator Library
3
+ *
4
+ * Provides consistency checks, drift detection, and data loss verification
5
+ * for SQLite ↔ Redis schema transformations.
6
+ *
7
+ * Task: Integration Standardization Plan - Task 2.2
8
+ * Version: 1.0.0
9
+ */ import { getGlobalLogger } from './logging.js';
10
+ import { StandardError } from './errors.js';
11
+ const logger = getGlobalLogger();
12
+ import { sqliteToRedis, redisToSqlite, SCHEMA_MAPPINGS } from './schema-transform.js';
13
+ // ============================================================================
14
+ // Consistency Validation
15
+ // ============================================================================
16
+ /**
17
+ * Validate consistency between SQLite and Redis data
18
+ *
19
+ * Compares data from both sources and reports mismatches
20
+ */ export function validateConsistency(schema, sqliteData, redisData) {
21
+ const errors = [];
22
+ const warnings = [];
23
+ try {
24
+ // Get schema mapping
25
+ const mapping = SCHEMA_MAPPINGS[schema];
26
+ if (!mapping) {
27
+ return {
28
+ valid: false,
29
+ errors: [
30
+ `Unknown schema: ${schema}`
31
+ ],
32
+ warnings: [],
33
+ timestamp: new Date()
34
+ };
35
+ }
36
+ // Transform SQLite data to Redis format for comparison
37
+ const transformResult = sqliteToRedis(schema, sqliteData);
38
+ if (!transformResult.success) {
39
+ errors.push(`Failed to transform SQLite data: ${transformResult.errors?.join(', ')}`);
40
+ }
41
+ const transformedData = transformResult.data;
42
+ if (!transformedData) {
43
+ return {
44
+ valid: false,
45
+ errors: [
46
+ 'Transformation produced no data'
47
+ ],
48
+ warnings: transformResult.warnings || [],
49
+ timestamp: new Date(),
50
+ schema
51
+ };
52
+ }
53
+ // Compare each field
54
+ for (const field of mapping.fields){
55
+ const redisField = field.destination;
56
+ const expectedValue = transformedData[redisField];
57
+ const actualValue = redisData[redisField];
58
+ // Skip if both are null/undefined
59
+ if ((expectedValue === null || expectedValue === undefined) && (actualValue === null || actualValue === undefined)) {
60
+ continue;
61
+ }
62
+ // Check for missing fields
63
+ if (expectedValue !== null && expectedValue !== undefined && (actualValue === null || actualValue === undefined)) {
64
+ if (field.required) {
65
+ errors.push(`Required field '${redisField}' is missing in Redis data`);
66
+ } else {
67
+ warnings.push(`Optional field '${redisField}' is missing in Redis data`);
68
+ }
69
+ continue;
70
+ }
71
+ // Compare values (handle type coercion for numbers/strings)
72
+ if (!valuesEqual(expectedValue, actualValue)) {
73
+ const diff = `expected ${JSON.stringify(expectedValue)}, got ${JSON.stringify(actualValue)}`;
74
+ if (field.required) {
75
+ errors.push(`Mismatch on field '${redisField}': ${diff}`);
76
+ } else {
77
+ warnings.push(`Mismatch on optional field '${redisField}': ${diff}`);
78
+ }
79
+ }
80
+ }
81
+ // Check for extra fields in Redis (not in mapping)
82
+ for(const key in redisData){
83
+ const hasField = mapping.fields.some((f)=>f.destination === key);
84
+ if (!hasField) {
85
+ warnings.push(`Unexpected field '${key}' in Redis data`);
86
+ }
87
+ }
88
+ const valid = errors.length === 0;
89
+ logger.debug('Consistency validation completed', {
90
+ schema,
91
+ valid,
92
+ errorCount: errors.length,
93
+ warningCount: warnings.length
94
+ });
95
+ return {
96
+ valid,
97
+ errors,
98
+ warnings,
99
+ timestamp: new Date(),
100
+ schema,
101
+ details: {
102
+ fieldsCompared: mapping.fields.length,
103
+ mismatches: errors.length + warnings.length
104
+ }
105
+ };
106
+ } catch (err) {
107
+ logger.error('Consistency validation failed', err, {
108
+ schema
109
+ });
110
+ return {
111
+ valid: false,
112
+ errors: [
113
+ `Validation error: ${err.message}`
114
+ ],
115
+ warnings: [],
116
+ timestamp: new Date(),
117
+ schema
118
+ };
119
+ }
120
+ }
121
+ /**
122
+ * Compare two values with type coercion handling
123
+ */ function valuesEqual(a, b) {
124
+ // Exact match
125
+ if (a === b) return true;
126
+ // Null/undefined equivalence
127
+ if ((a === null || a === undefined) && (b === null || b === undefined)) {
128
+ return true;
129
+ }
130
+ // Number/string coercion
131
+ if (typeof a === 'number' && typeof b === 'string') {
132
+ return a.toString() === b;
133
+ }
134
+ if (typeof a === 'string' && typeof b === 'number') {
135
+ return a === b.toString();
136
+ }
137
+ // Deep equality for objects
138
+ if (typeof a === 'object' && typeof b === 'object' && a !== null && b !== null) {
139
+ return JSON.stringify(a) === JSON.stringify(b);
140
+ }
141
+ return false;
142
+ }
143
+ // ============================================================================
144
+ // Schema Drift Detection
145
+ // ============================================================================
146
+ /**
147
+ * Detect schema drift between SQLite and Redis data sets
148
+ *
149
+ * Analyzes multiple records to find structural inconsistencies
150
+ */ export async function detectDrift(schema, sqliteRecords, redisRecords) {
151
+ const mismatches = [];
152
+ const missingInSqlite = new Set();
153
+ const missingInRedis = new Set();
154
+ const typeMismatches = [];
155
+ try {
156
+ // Get schema mapping
157
+ const mapping = SCHEMA_MAPPINGS[schema];
158
+ if (!mapping) {
159
+ throw new StandardError(`Unknown schema: ${schema}`, 'SCHEMA_VALIDATION_ERROR');
160
+ }
161
+ // Analyze SQLite records
162
+ const sqliteFields = new Set();
163
+ for (const record of sqliteRecords){
164
+ for(const key in record){
165
+ sqliteFields.add(key);
166
+ }
167
+ }
168
+ // Analyze Redis records
169
+ const redisFields = new Set();
170
+ for (const record of redisRecords){
171
+ for(const key in record){
172
+ redisFields.add(key);
173
+ }
174
+ }
175
+ // Find missing fields in SQLite
176
+ for (const field of mapping.fields){
177
+ if (!sqliteFields.has(field.source)) {
178
+ missingInSqlite.add(field.source);
179
+ }
180
+ }
181
+ // Find missing fields in Redis
182
+ for (const field of mapping.fields){
183
+ if (!redisFields.has(field.destination)) {
184
+ missingInRedis.add(field.destination);
185
+ }
186
+ }
187
+ // Compare sample records for value drift
188
+ const sampleSize = Math.min(sqliteRecords.length, redisRecords.length, 100);
189
+ for(let i = 0; i < sampleSize; i++){
190
+ const sqliteRow = sqliteRecords[i];
191
+ const redisRow = redisRecords[i];
192
+ // Transform SQLite to Redis for comparison
193
+ const transformResult = sqliteToRedis(schema, sqliteRow);
194
+ if (!transformResult.success || !transformResult.data) {
195
+ continue;
196
+ }
197
+ const transformed = transformResult.data;
198
+ // Compare fields
199
+ for (const field of mapping.fields){
200
+ const redisField = field.destination;
201
+ const expected = transformed[redisField];
202
+ const actual = redisRow[redisField];
203
+ if (!valuesEqual(expected, actual)) {
204
+ mismatches.push({
205
+ field: redisField,
206
+ sqliteValue: expected,
207
+ redisValue: actual,
208
+ difference: `SQLite: ${JSON.stringify(expected)}, Redis: ${JSON.stringify(actual)}`
209
+ });
210
+ }
211
+ // Check type consistency
212
+ if (expected !== null && actual !== null) {
213
+ const expectedType = typeof expected;
214
+ const actualType = typeof actual;
215
+ if (expectedType !== actualType) {
216
+ typeMismatches.push({
217
+ field: redisField,
218
+ expectedType,
219
+ actualType,
220
+ location: 'redis'
221
+ });
222
+ }
223
+ }
224
+ }
225
+ }
226
+ const driftDetected = mismatches.length > 0 || missingInSqlite.size > 0 || missingInRedis.size > 0 || typeMismatches.length > 0;
227
+ logger.info('Schema drift detection completed', {
228
+ schema,
229
+ driftDetected,
230
+ mismatches: mismatches.length,
231
+ missingInSqlite: missingInSqlite.size,
232
+ missingInRedis: missingInRedis.size,
233
+ typeMismatches: typeMismatches.length
234
+ });
235
+ return {
236
+ schema,
237
+ driftDetected,
238
+ mismatches: mismatches.slice(0, 50),
239
+ missingInSqlite: Array.from(missingInSqlite),
240
+ missingInRedis: Array.from(missingInRedis),
241
+ typeMismatches,
242
+ timestamp: new Date(),
243
+ affectedRecords: sampleSize
244
+ };
245
+ } catch (err) {
246
+ logger.error('Schema drift detection failed', err, {
247
+ schema
248
+ });
249
+ throw new StandardError(`Drift detection failed: ${err.message}`, 'SCHEMA_VALIDATION_ERROR');
250
+ }
251
+ }
252
+ // ============================================================================
253
+ // Data Loss Verification
254
+ // ============================================================================
255
+ /**
256
+ * Verify no data loss during transformation
257
+ *
258
+ * Performs round-trip transformation and compares with original
259
+ */ export function verifyNoDataLoss(schema, original, direction) {
260
+ const lostFields = [];
261
+ const modifiedFields = [];
262
+ const nullifications = [];
263
+ try {
264
+ let roundTrip;
265
+ // Perform round-trip transformation
266
+ if (direction === 'sqlite-to-redis') {
267
+ const toRedis = sqliteToRedis(schema, original);
268
+ if (!toRedis.success || !toRedis.data) {
269
+ return {
270
+ lossDetected: true,
271
+ lostFields: [
272
+ 'ALL'
273
+ ],
274
+ modifiedFields: [],
275
+ nullifications: [],
276
+ details: `Forward transformation failed: ${toRedis.errors?.join(', ')}`
277
+ };
278
+ }
279
+ const backToSqlite = redisToSqlite(schema, toRedis.data);
280
+ if (!backToSqlite.success || !backToSqlite.data) {
281
+ return {
282
+ lossDetected: true,
283
+ lostFields: [
284
+ 'ALL'
285
+ ],
286
+ modifiedFields: [],
287
+ nullifications: [],
288
+ details: `Reverse transformation failed: ${backToSqlite.errors?.join(', ')}`
289
+ };
290
+ }
291
+ roundTrip = backToSqlite.data;
292
+ } else if (direction === 'redis-to-sqlite') {
293
+ const toSqlite = redisToSqlite(schema, original);
294
+ if (!toSqlite.success || !toSqlite.data) {
295
+ return {
296
+ lossDetected: true,
297
+ lostFields: [
298
+ 'ALL'
299
+ ],
300
+ modifiedFields: [],
301
+ nullifications: [],
302
+ details: `Forward transformation failed: ${toSqlite.errors?.join(', ')}`
303
+ };
304
+ }
305
+ const backToRedis = sqliteToRedis(schema, toSqlite.data);
306
+ if (!backToRedis.success || !backToRedis.data) {
307
+ return {
308
+ lossDetected: true,
309
+ lostFields: [
310
+ 'ALL'
311
+ ],
312
+ modifiedFields: [],
313
+ nullifications: [],
314
+ details: `Reverse transformation failed: ${backToRedis.errors?.join(', ')}`
315
+ };
316
+ }
317
+ roundTrip = backToRedis.data;
318
+ } else if (direction === 'postgres-to-sqlite') {
319
+ // One-way transform - cannot perform round-trip
320
+ return {
321
+ lossDetected: false,
322
+ lostFields: [],
323
+ modifiedFields: [],
324
+ nullifications: [],
325
+ details: 'PostgreSQL → SQLite is one-way; round-trip verification not applicable'
326
+ };
327
+ } else {
328
+ throw new StandardError(`Unknown direction: ${direction}`, 'SCHEMA_VALIDATION_ERROR');
329
+ }
330
+ // Compare original with round-trip result
331
+ for(const key in original){
332
+ const originalValue = original[key];
333
+ const roundTripValue = roundTrip[key];
334
+ // Check for lost fields
335
+ if (originalValue !== null && originalValue !== undefined && (roundTripValue === null || roundTripValue === undefined)) {
336
+ lostFields.push(key);
337
+ continue;
338
+ }
339
+ // Check for nullifications
340
+ if (originalValue !== null && roundTripValue === null) {
341
+ nullifications.push(key);
342
+ continue;
343
+ }
344
+ // Check for modifications (with tolerance for type coercion)
345
+ if (!valuesEqual(originalValue, roundTripValue)) {
346
+ modifiedFields.push({
347
+ field: key,
348
+ originalValue,
349
+ transformedValue: roundTripValue,
350
+ reason: detectModificationReason(originalValue, roundTripValue)
351
+ });
352
+ }
353
+ }
354
+ const lossDetected = lostFields.length > 0 || nullifications.length > 0 || modifiedFields.length > 0;
355
+ logger.debug('Data loss verification completed', {
356
+ schema,
357
+ direction,
358
+ lossDetected,
359
+ lostFields: lostFields.length,
360
+ nullifications: nullifications.length,
361
+ modifications: modifiedFields.length
362
+ });
363
+ return {
364
+ lossDetected,
365
+ lostFields,
366
+ modifiedFields,
367
+ nullifications,
368
+ details: lossDetected ? `Lost: ${lostFields.length}, Nullified: ${nullifications.length}, Modified: ${modifiedFields.length}` : 'No data loss detected'
369
+ };
370
+ } catch (err) {
371
+ logger.error('Data loss verification failed', err, {
372
+ schema,
373
+ direction
374
+ });
375
+ return {
376
+ lossDetected: true,
377
+ lostFields: [
378
+ 'UNKNOWN'
379
+ ],
380
+ modifiedFields: [],
381
+ nullifications: [],
382
+ details: `Verification error: ${err.message}`
383
+ };
384
+ }
385
+ }
386
+ /**
387
+ * Detect reason for field modification
388
+ */ function detectModificationReason(original, transformed) {
389
+ const origType = typeof original;
390
+ const transType = typeof transformed;
391
+ if (origType !== transType) {
392
+ return `Type conversion: ${origType} → ${transType}`;
393
+ }
394
+ if (origType === 'number') {
395
+ const diff = Math.abs(original - transformed);
396
+ if (diff < 0.000001) {
397
+ return 'Floating point precision loss';
398
+ }
399
+ return `Value change: ${original} → ${transformed}`;
400
+ }
401
+ if (origType === 'string') {
402
+ if (original.length !== transformed.length) {
403
+ return `String length change: ${original.length} → ${transformed.length}`;
404
+ }
405
+ return 'String content modification';
406
+ }
407
+ return 'Unknown modification';
408
+ }
409
+ // ============================================================================
410
+ // Batch Validation
411
+ // ============================================================================
412
+ /**
413
+ * Validate batch of records for consistency
414
+ */ export function validateBatch(schema, sqliteRecords, redisRecords) {
415
+ const errors = [];
416
+ const warnings = [];
417
+ if (sqliteRecords.length !== redisRecords.length) {
418
+ warnings.push(`Record count mismatch: SQLite has ${sqliteRecords.length}, Redis has ${redisRecords.length}`);
419
+ }
420
+ const count = Math.min(sqliteRecords.length, redisRecords.length);
421
+ let validCount = 0;
422
+ for(let i = 0; i < count; i++){
423
+ const result = validateConsistency(schema, sqliteRecords[i], redisRecords[i]);
424
+ if (result.valid) {
425
+ validCount++;
426
+ } else {
427
+ errors.push(`Record ${i}: ${result.errors.join(', ')}`);
428
+ }
429
+ if (result.warnings.length > 0) {
430
+ warnings.push(`Record ${i}: ${result.warnings.join(', ')}`);
431
+ }
432
+ }
433
+ const valid = errors.length === 0;
434
+ logger.info('Batch validation completed', {
435
+ schema,
436
+ total: count,
437
+ valid: validCount,
438
+ invalid: count - validCount,
439
+ warnings: warnings.length
440
+ });
441
+ return {
442
+ valid,
443
+ errors,
444
+ warnings,
445
+ timestamp: new Date(),
446
+ schema,
447
+ details: {
448
+ total: count,
449
+ valid: validCount,
450
+ invalid: count - validCount
451
+ }
452
+ };
453
+ }
454
+ /**
455
+ * Verify no data loss for batch of records
456
+ */ export function verifyBatchNoDataLoss(schema, records, direction) {
457
+ const allLostFields = new Set();
458
+ const allModifiedFields = [];
459
+ const allNullifications = new Set();
460
+ let lossDetected = false;
461
+ for(let i = 0; i < records.length; i++){
462
+ const check = verifyNoDataLoss(schema, records[i], direction);
463
+ if (check.lossDetected) {
464
+ lossDetected = true;
465
+ }
466
+ check.lostFields.forEach((f)=>allLostFields.add(f));
467
+ check.nullifications.forEach((f)=>allNullifications.add(f));
468
+ allModifiedFields.push(...check.modifiedFields.map((m)=>({
469
+ ...m,
470
+ field: `Record ${i}.${m.field}`
471
+ })));
472
+ }
473
+ logger.info('Batch data loss verification completed', {
474
+ schema,
475
+ direction,
476
+ total: records.length,
477
+ lossDetected,
478
+ lostFields: allLostFields.size,
479
+ nullifications: allNullifications.size,
480
+ modifications: allModifiedFields.length
481
+ });
482
+ return {
483
+ lossDetected,
484
+ lostFields: Array.from(allLostFields),
485
+ modifiedFields: allModifiedFields.slice(0, 100),
486
+ nullifications: Array.from(allNullifications),
487
+ details: `Validated ${records.length} records`
488
+ };
489
+ }
490
+
491
+ //# sourceMappingURL=schema-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/schema-validator.ts"],"sourcesContent":["/**\r\n * Schema Validator Library\r\n *\r\n * Provides consistency checks, drift detection, and data loss verification\r\n * for SQLite ↔ Redis schema transformations.\r\n *\r\n * Task: Integration Standardization Plan - Task 2.2\r\n * Version: 1.0.0\r\n */\r\n\r\nimport { getGlobalLogger } from './logging.js';\r\nimport { StandardError } from './errors.js';\r\n\r\nconst logger = getGlobalLogger();\r\nimport {\r\n SchemaName,\r\n SQLiteRow,\r\n RedisData,\r\n sqliteToRedis,\r\n redisToSqlite,\r\n postgrestoSqlite,\r\n TransformDirection,\r\n SCHEMA_MAPPINGS,\r\n} from './schema-transform.js';\r\n\r\n// ============================================================================\r\n// Type Definitions\r\n// ============================================================================\r\n\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: string[];\r\n warnings: string[];\r\n timestamp: Date;\r\n schema?: SchemaName;\r\n details?: Record<string, any>;\r\n}\r\n\r\nexport interface DriftReport {\r\n schema: SchemaName;\r\n driftDetected: boolean;\r\n mismatches: FieldMismatch[];\r\n missingInSqlite: string[];\r\n missingInRedis: string[];\r\n typeMismatches: TypeMismatch[];\r\n timestamp: Date;\r\n affectedRecords?: number;\r\n}\r\n\r\nexport interface FieldMismatch {\r\n field: string;\r\n sqliteValue: any;\r\n redisValue: any;\r\n difference: string;\r\n}\r\n\r\nexport interface TypeMismatch {\r\n field: string;\r\n expectedType: string;\r\n actualType: string;\r\n location: 'sqlite' | 'redis';\r\n}\r\n\r\nexport interface DataLossCheck {\r\n lossDetected: boolean;\r\n lostFields: string[];\r\n modifiedFields: FieldModification[];\r\n nullifications: string[];\r\n details: string;\r\n}\r\n\r\nexport interface FieldModification {\r\n field: string;\r\n originalValue: any;\r\n transformedValue: any;\r\n reason: string;\r\n}\r\n\r\n// ============================================================================\r\n// Consistency Validation\r\n// ============================================================================\r\n\r\n/**\r\n * Validate consistency between SQLite and Redis data\r\n *\r\n * Compares data from both sources and reports mismatches\r\n */\r\nexport function validateConsistency(\r\n schema: SchemaName,\r\n sqliteData: SQLiteRow,\r\n redisData: RedisData\r\n): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n try {\r\n // Get schema mapping\r\n const mapping = SCHEMA_MAPPINGS[schema];\r\n if (!mapping) {\r\n return {\r\n valid: false,\r\n errors: [`Unknown schema: ${schema}`],\r\n warnings: [],\r\n timestamp: new Date(),\r\n };\r\n }\r\n\r\n // Transform SQLite data to Redis format for comparison\r\n const transformResult = sqliteToRedis(schema, sqliteData);\r\n if (!transformResult.success) {\r\n errors.push(`Failed to transform SQLite data: ${transformResult.errors?.join(', ')}`);\r\n }\r\n\r\n const transformedData = transformResult.data;\r\n if (!transformedData) {\r\n return {\r\n valid: false,\r\n errors: ['Transformation produced no data'],\r\n warnings: transformResult.warnings || [],\r\n timestamp: new Date(),\r\n schema,\r\n };\r\n }\r\n\r\n // Compare each field\r\n for (const field of mapping.fields) {\r\n const redisField = field.destination;\r\n const expectedValue = transformedData[redisField];\r\n const actualValue = redisData[redisField];\r\n\r\n // Skip if both are null/undefined\r\n if ((expectedValue === null || expectedValue === undefined) &&\r\n (actualValue === null || actualValue === undefined)) {\r\n continue;\r\n }\r\n\r\n // Check for missing fields\r\n if (expectedValue !== null && expectedValue !== undefined &&\r\n (actualValue === null || actualValue === undefined)) {\r\n if (field.required) {\r\n errors.push(`Required field '${redisField}' is missing in Redis data`);\r\n } else {\r\n warnings.push(`Optional field '${redisField}' is missing in Redis data`);\r\n }\r\n continue;\r\n }\r\n\r\n // Compare values (handle type coercion for numbers/strings)\r\n if (!valuesEqual(expectedValue, actualValue)) {\r\n const diff = `expected ${JSON.stringify(expectedValue)}, got ${JSON.stringify(actualValue)}`;\r\n\r\n if (field.required) {\r\n errors.push(`Mismatch on field '${redisField}': ${diff}`);\r\n } else {\r\n warnings.push(`Mismatch on optional field '${redisField}': ${diff}`);\r\n }\r\n }\r\n }\r\n\r\n // Check for extra fields in Redis (not in mapping)\r\n for (const key in redisData) {\r\n const hasField = mapping.fields.some(f => f.destination === key);\r\n if (!hasField) {\r\n warnings.push(`Unexpected field '${key}' in Redis data`);\r\n }\r\n }\r\n\r\n const valid = errors.length === 0;\r\n\r\n logger.debug('Consistency validation completed', {\r\n schema,\r\n valid,\r\n errorCount: errors.length,\r\n warningCount: warnings.length,\r\n });\r\n\r\n return {\r\n valid,\r\n errors,\r\n warnings,\r\n timestamp: new Date(),\r\n schema,\r\n details: {\r\n fieldsCompared: mapping.fields.length,\r\n mismatches: errors.length + warnings.length,\r\n },\r\n };\r\n } catch (err) {\r\n logger.error('Consistency validation failed', err as Error, { schema });\r\n return {\r\n valid: false,\r\n errors: [`Validation error: ${(err as Error).message}`],\r\n warnings: [],\r\n timestamp: new Date(),\r\n schema,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Compare two values with type coercion handling\r\n */\r\nfunction valuesEqual(a: any, b: any): boolean {\r\n // Exact match\r\n if (a === b) return true;\r\n\r\n // Null/undefined equivalence\r\n if ((a === null || a === undefined) && (b === null || b === undefined)) {\r\n return true;\r\n }\r\n\r\n // Number/string coercion\r\n if (typeof a === 'number' && typeof b === 'string') {\r\n return a.toString() === b;\r\n }\r\n if (typeof a === 'string' && typeof b === 'number') {\r\n return a === b.toString();\r\n }\r\n\r\n // Deep equality for objects\r\n if (typeof a === 'object' && typeof b === 'object' && a !== null && b !== null) {\r\n return JSON.stringify(a) === JSON.stringify(b);\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// ============================================================================\r\n// Schema Drift Detection\r\n// ============================================================================\r\n\r\n/**\r\n * Detect schema drift between SQLite and Redis data sets\r\n *\r\n * Analyzes multiple records to find structural inconsistencies\r\n */\r\nexport async function detectDrift(\r\n schema: SchemaName,\r\n sqliteRecords: SQLiteRow[],\r\n redisRecords: RedisData[]\r\n): Promise<DriftReport> {\r\n const mismatches: FieldMismatch[] = [];\r\n const missingInSqlite: Set<string> = new Set();\r\n const missingInRedis: Set<string> = new Set();\r\n const typeMismatches: TypeMismatch[] = [];\r\n\r\n try {\r\n // Get schema mapping\r\n const mapping = SCHEMA_MAPPINGS[schema];\r\n if (!mapping) {\r\n throw new StandardError(`Unknown schema: ${schema}`, 'SCHEMA_VALIDATION_ERROR');\r\n }\r\n\r\n // Analyze SQLite records\r\n const sqliteFields = new Set<string>();\r\n for (const record of sqliteRecords) {\r\n for (const key in record) {\r\n sqliteFields.add(key);\r\n }\r\n }\r\n\r\n // Analyze Redis records\r\n const redisFields = new Set<string>();\r\n for (const record of redisRecords) {\r\n for (const key in record) {\r\n redisFields.add(key);\r\n }\r\n }\r\n\r\n // Find missing fields in SQLite\r\n for (const field of mapping.fields) {\r\n if (!sqliteFields.has(field.source)) {\r\n missingInSqlite.add(field.source);\r\n }\r\n }\r\n\r\n // Find missing fields in Redis\r\n for (const field of mapping.fields) {\r\n if (!redisFields.has(field.destination)) {\r\n missingInRedis.add(field.destination);\r\n }\r\n }\r\n\r\n // Compare sample records for value drift\r\n const sampleSize = Math.min(sqliteRecords.length, redisRecords.length, 100);\r\n for (let i = 0; i < sampleSize; i++) {\r\n const sqliteRow = sqliteRecords[i];\r\n const redisRow = redisRecords[i];\r\n\r\n // Transform SQLite to Redis for comparison\r\n const transformResult = sqliteToRedis(schema, sqliteRow);\r\n if (!transformResult.success || !transformResult.data) {\r\n continue;\r\n }\r\n\r\n const transformed = transformResult.data;\r\n\r\n // Compare fields\r\n for (const field of mapping.fields) {\r\n const redisField = field.destination;\r\n const expected = transformed[redisField];\r\n const actual = redisRow[redisField];\r\n\r\n if (!valuesEqual(expected, actual)) {\r\n mismatches.push({\r\n field: redisField,\r\n sqliteValue: expected,\r\n redisValue: actual,\r\n difference: `SQLite: ${JSON.stringify(expected)}, Redis: ${JSON.stringify(actual)}`,\r\n });\r\n }\r\n\r\n // Check type consistency\r\n if (expected !== null && actual !== null) {\r\n const expectedType = typeof expected;\r\n const actualType = typeof actual;\r\n if (expectedType !== actualType) {\r\n typeMismatches.push({\r\n field: redisField,\r\n expectedType,\r\n actualType,\r\n location: 'redis',\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n const driftDetected = mismatches.length > 0 ||\r\n missingInSqlite.size > 0 ||\r\n missingInRedis.size > 0 ||\r\n typeMismatches.length > 0;\r\n\r\n logger.info('Schema drift detection completed', {\r\n schema,\r\n driftDetected,\r\n mismatches: mismatches.length,\r\n missingInSqlite: missingInSqlite.size,\r\n missingInRedis: missingInRedis.size,\r\n typeMismatches: typeMismatches.length,\r\n });\r\n\r\n return {\r\n schema,\r\n driftDetected,\r\n mismatches: mismatches.slice(0, 50), // Limit to first 50\r\n missingInSqlite: Array.from(missingInSqlite),\r\n missingInRedis: Array.from(missingInRedis),\r\n typeMismatches,\r\n timestamp: new Date(),\r\n affectedRecords: sampleSize,\r\n };\r\n } catch (err) {\r\n logger.error('Schema drift detection failed', err as Error, { schema });\r\n throw new StandardError(`Drift detection failed: ${(err as Error).message}`, 'SCHEMA_VALIDATION_ERROR');\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Data Loss Verification\r\n// ============================================================================\r\n\r\n/**\r\n * Verify no data loss during transformation\r\n *\r\n * Performs round-trip transformation and compares with original\r\n */\r\nexport function verifyNoDataLoss(\r\n schema: SchemaName,\r\n original: any,\r\n direction: TransformDirection\r\n): DataLossCheck {\r\n const lostFields: string[] = [];\r\n const modifiedFields: FieldModification[] = [];\r\n const nullifications: string[] = [];\r\n\r\n try {\r\n let roundTrip: any;\r\n\r\n // Perform round-trip transformation\r\n if (direction === 'sqlite-to-redis') {\r\n const toRedis = sqliteToRedis(schema, original);\r\n if (!toRedis.success || !toRedis.data) {\r\n return {\r\n lossDetected: true,\r\n lostFields: ['ALL'],\r\n modifiedFields: [],\r\n nullifications: [],\r\n details: `Forward transformation failed: ${toRedis.errors?.join(', ')}`,\r\n };\r\n }\r\n\r\n const backToSqlite = redisToSqlite(schema, toRedis.data);\r\n if (!backToSqlite.success || !backToSqlite.data) {\r\n return {\r\n lossDetected: true,\r\n lostFields: ['ALL'],\r\n modifiedFields: [],\r\n nullifications: [],\r\n details: `Reverse transformation failed: ${backToSqlite.errors?.join(', ')}`,\r\n };\r\n }\r\n\r\n roundTrip = backToSqlite.data;\r\n } else if (direction === 'redis-to-sqlite') {\r\n const toSqlite = redisToSqlite(schema, original);\r\n if (!toSqlite.success || !toSqlite.data) {\r\n return {\r\n lossDetected: true,\r\n lostFields: ['ALL'],\r\n modifiedFields: [],\r\n nullifications: [],\r\n details: `Forward transformation failed: ${toSqlite.errors?.join(', ')}`,\r\n };\r\n }\r\n\r\n const backToRedis = sqliteToRedis(schema, toSqlite.data);\r\n if (!backToRedis.success || !backToRedis.data) {\r\n return {\r\n lossDetected: true,\r\n lostFields: ['ALL'],\r\n modifiedFields: [],\r\n nullifications: [],\r\n details: `Reverse transformation failed: ${backToRedis.errors?.join(', ')}`,\r\n };\r\n }\r\n\r\n roundTrip = backToRedis.data;\r\n } else if (direction === 'postgres-to-sqlite') {\r\n // One-way transform - cannot perform round-trip\r\n return {\r\n lossDetected: false,\r\n lostFields: [],\r\n modifiedFields: [],\r\n nullifications: [],\r\n details: 'PostgreSQL → SQLite is one-way; round-trip verification not applicable',\r\n };\r\n } else {\r\n throw new StandardError(`Unknown direction: ${direction}`, 'SCHEMA_VALIDATION_ERROR');\r\n }\r\n\r\n // Compare original with round-trip result\r\n for (const key in original) {\r\n const originalValue = original[key];\r\n const roundTripValue = roundTrip[key];\r\n\r\n // Check for lost fields\r\n if (originalValue !== null && originalValue !== undefined &&\r\n (roundTripValue === null || roundTripValue === undefined)) {\r\n lostFields.push(key);\r\n continue;\r\n }\r\n\r\n // Check for nullifications\r\n if (originalValue !== null && roundTripValue === null) {\r\n nullifications.push(key);\r\n continue;\r\n }\r\n\r\n // Check for modifications (with tolerance for type coercion)\r\n if (!valuesEqual(originalValue, roundTripValue)) {\r\n modifiedFields.push({\r\n field: key,\r\n originalValue,\r\n transformedValue: roundTripValue,\r\n reason: detectModificationReason(originalValue, roundTripValue),\r\n });\r\n }\r\n }\r\n\r\n const lossDetected = lostFields.length > 0 || nullifications.length > 0 || modifiedFields.length > 0;\r\n\r\n logger.debug('Data loss verification completed', {\r\n schema,\r\n direction,\r\n lossDetected,\r\n lostFields: lostFields.length,\r\n nullifications: nullifications.length,\r\n modifications: modifiedFields.length,\r\n });\r\n\r\n return {\r\n lossDetected,\r\n lostFields,\r\n modifiedFields,\r\n nullifications,\r\n details: lossDetected\r\n ? `Lost: ${lostFields.length}, Nullified: ${nullifications.length}, Modified: ${modifiedFields.length}`\r\n : 'No data loss detected',\r\n };\r\n } catch (err) {\r\n logger.error('Data loss verification failed', err as Error, { schema, direction });\r\n return {\r\n lossDetected: true,\r\n lostFields: ['UNKNOWN'],\r\n modifiedFields: [],\r\n nullifications: [],\r\n details: `Verification error: ${(err as Error).message}`,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Detect reason for field modification\r\n */\r\nfunction detectModificationReason(original: any, transformed: any): string {\r\n const origType = typeof original;\r\n const transType = typeof transformed;\r\n\r\n if (origType !== transType) {\r\n return `Type conversion: ${origType} → ${transType}`;\r\n }\r\n\r\n if (origType === 'number') {\r\n const diff = Math.abs(original - transformed);\r\n if (diff < 0.000001) {\r\n return 'Floating point precision loss';\r\n }\r\n return `Value change: ${original} → ${transformed}`;\r\n }\r\n\r\n if (origType === 'string') {\r\n if (original.length !== transformed.length) {\r\n return `String length change: ${original.length} → ${transformed.length}`;\r\n }\r\n return 'String content modification';\r\n }\r\n\r\n return 'Unknown modification';\r\n}\r\n\r\n// ============================================================================\r\n// Batch Validation\r\n// ============================================================================\r\n\r\n/**\r\n * Validate batch of records for consistency\r\n */\r\nexport function validateBatch(\r\n schema: SchemaName,\r\n sqliteRecords: SQLiteRow[],\r\n redisRecords: RedisData[]\r\n): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (sqliteRecords.length !== redisRecords.length) {\r\n warnings.push(`Record count mismatch: SQLite has ${sqliteRecords.length}, Redis has ${redisRecords.length}`);\r\n }\r\n\r\n const count = Math.min(sqliteRecords.length, redisRecords.length);\r\n let validCount = 0;\r\n\r\n for (let i = 0; i < count; i++) {\r\n const result = validateConsistency(schema, sqliteRecords[i], redisRecords[i]);\r\n\r\n if (result.valid) {\r\n validCount++;\r\n } else {\r\n errors.push(`Record ${i}: ${result.errors.join(', ')}`);\r\n }\r\n\r\n if (result.warnings.length > 0) {\r\n warnings.push(`Record ${i}: ${result.warnings.join(', ')}`);\r\n }\r\n }\r\n\r\n const valid = errors.length === 0;\r\n\r\n logger.info('Batch validation completed', {\r\n schema,\r\n total: count,\r\n valid: validCount,\r\n invalid: count - validCount,\r\n warnings: warnings.length,\r\n });\r\n\r\n return {\r\n valid,\r\n errors,\r\n warnings,\r\n timestamp: new Date(),\r\n schema,\r\n details: {\r\n total: count,\r\n valid: validCount,\r\n invalid: count - validCount,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Verify no data loss for batch of records\r\n */\r\nexport function verifyBatchNoDataLoss(\r\n schema: SchemaName,\r\n records: any[],\r\n direction: TransformDirection\r\n): DataLossCheck {\r\n const allLostFields: Set<string> = new Set();\r\n const allModifiedFields: FieldModification[] = [];\r\n const allNullifications: Set<string> = new Set();\r\n let lossDetected = false;\r\n\r\n for (let i = 0; i < records.length; i++) {\r\n const check = verifyNoDataLoss(schema, records[i], direction);\r\n\r\n if (check.lossDetected) {\r\n lossDetected = true;\r\n }\r\n\r\n check.lostFields.forEach(f => allLostFields.add(f));\r\n check.nullifications.forEach(f => allNullifications.add(f));\r\n allModifiedFields.push(...check.modifiedFields.map(m => ({\r\n ...m,\r\n field: `Record ${i}.${m.field}`,\r\n })));\r\n }\r\n\r\n logger.info('Batch data loss verification completed', {\r\n schema,\r\n direction,\r\n total: records.length,\r\n lossDetected,\r\n lostFields: allLostFields.size,\r\n nullifications: allNullifications.size,\r\n modifications: allModifiedFields.length,\r\n });\r\n\r\n return {\r\n lossDetected,\r\n lostFields: Array.from(allLostFields),\r\n modifiedFields: allModifiedFields.slice(0, 100), // Limit to first 100\r\n nullifications: Array.from(allNullifications),\r\n details: `Validated ${records.length} records`,\r\n };\r\n}\r\n"],"names":["getGlobalLogger","StandardError","logger","sqliteToRedis","redisToSqlite","SCHEMA_MAPPINGS","validateConsistency","schema","sqliteData","redisData","errors","warnings","mapping","valid","timestamp","Date","transformResult","success","push","join","transformedData","data","field","fields","redisField","destination","expectedValue","actualValue","undefined","required","valuesEqual","diff","JSON","stringify","key","hasField","some","f","length","debug","errorCount","warningCount","details","fieldsCompared","mismatches","err","error","message","a","b","toString","detectDrift","sqliteRecords","redisRecords","missingInSqlite","Set","missingInRedis","typeMismatches","sqliteFields","record","add","redisFields","has","source","sampleSize","Math","min","i","sqliteRow","redisRow","transformed","expected","actual","sqliteValue","redisValue","difference","expectedType","actualType","location","driftDetected","size","info","slice","Array","from","affectedRecords","verifyNoDataLoss","original","direction","lostFields","modifiedFields","nullifications","roundTrip","toRedis","lossDetected","backToSqlite","toSqlite","backToRedis","originalValue","roundTripValue","transformedValue","reason","detectModificationReason","modifications","origType","transType","abs","validateBatch","count","validCount","result","total","invalid","verifyBatchNoDataLoss","records","allLostFields","allModifiedFields","allNullifications","check","forEach","map","m"],"mappings":"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"}