claude-flow-novice 2.15.2 → 2.15.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
- package/.claude/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
- package/.claude/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
- package/.claude/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
- package/.claude/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
- package/.claude/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
- package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
- package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
- package/.claude/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
- package/.claude/commands/cfn-loop-cli.md +16 -2
- package/.claude/commands/switch-api.md +31 -10
- package/.claude/hooks/cfn-BACKUP_USAGE.md +243 -243
- package/.claude/hooks/cfn-invoke-security-validation.sh +69 -69
- package/.claude/hooks/cfn-lint-sql-injection.sh +61 -0
- package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +109 -78
- package/.claude/hooks/cfn-post-edit.config.json +44 -44
- package/.claude/hooks/cfn-pre-edit-security-warning.sh +40 -0
- package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
- package/.claude/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
- package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
- package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
- package/.claude/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
- package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
- package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +184 -23
- package/.claude/skills/cfn-loop-orchestration/security_utils.sh +24 -0
- package/.claude/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
- package/.claude/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
- package/.claude/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
- package/.claude/skills/cfn-redis-coordination/agent-log.sh +4 -0
- package/.claude/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
- package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
- package/.claude/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
- package/.claude/skills/cfn-redis-coordination/get-context.sh +145 -112
- package/.claude/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
- package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +3 -0
- package/.claude/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
- package/.claude/skills/cfn-redis-coordination/redis-functions.sh +33 -0
- package/.claude/skills/cfn-redis-coordination/report-completion.sh +24 -31
- package/.claude/skills/cfn-redis-coordination/store-context.sh +4 -0
- package/.claude/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
- package/.claude/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
- package/.claude/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
- package/.claude/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
- package/.claude/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
- package/.claude/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
- package/.claude/skills/cfn-transparency-middleware/test-integration.sh +161 -161
- package/.claude/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
- package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +107 -92
- package/.claude/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
- package/README.md +116 -475
- package/claude-assets/agents/cfn-dev-team/README.md +103 -0
- package/claude-assets/agents/cfn-dev-team/architecture/goal-planner.md +1 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +77 -15
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +355 -6
- package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +82 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +82 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +77 -15
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +99 -12
- package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +1 -1
- package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +97 -0
- package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +20 -1
- package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +97 -0
- package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +110 -13
- package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +106 -15
- package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +115 -11
- package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +94 -7
- package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +87 -9
- package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +85 -7
- package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +160 -28
- package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +101 -19
- package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +108 -14
- package/claude-assets/agents/cfn-dev-team/reviewers/{reviewer.md → code-reviewer.md} +95 -8
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +107 -7
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +98 -7
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +95 -7
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +136 -9
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +108 -1
- package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +107 -13
- package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +737 -0
- package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +828 -0
- package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +106 -7
- package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +77 -0
- package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +684 -0
- package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +110 -1
- package/claude-assets/agents/cfn-dev-team/testers/tester.md +94 -7
- package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +1 -3
- package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +87 -13
- package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +103 -7
- package/claude-assets/agents/cfn-dev-team/utility/researcher.md +1 -3
- package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +94 -7
- package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +46 -0
- package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
- package/claude-assets/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
- package/claude-assets/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
- package/claude-assets/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
- package/claude-assets/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
- package/claude-assets/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
- package/claude-assets/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
- package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
- package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
- package/claude-assets/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
- package/claude-assets/commands/cfn-loop-cli.md +16 -2
- package/claude-assets/commands/switch-api.md +31 -10
- package/claude-assets/hooks/cfn-BACKUP_USAGE.md +243 -243
- package/claude-assets/hooks/cfn-invoke-security-validation.sh +69 -69
- package/claude-assets/hooks/cfn-lint-sql-injection.sh +61 -0
- package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +109 -78
- package/claude-assets/hooks/cfn-post-edit.config.json +44 -44
- package/claude-assets/hooks/cfn-post-execution/memory-cleanup.sh +19 -19
- package/claude-assets/hooks/cfn-pre-edit-security-warning.sh +40 -0
- package/claude-assets/hooks/cfn-pre-execution/memory-check.sh +19 -19
- package/claude-assets/hooks/detect-hardcoded-credentials.sh +212 -0
- package/claude-assets/skills/SKILL_TEMPLATE.md +774 -0
- package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +543 -572
- package/claude-assets/skills/agent-lifecycle/simple-audit.sh +57 -30
- package/claude-assets/skills/agent-template-generator/SKILL.md +440 -0
- package/claude-assets/skills/agent-template-generator/generate-agent.sh +405 -0
- package/claude-assets/skills/agent-validation-linter/SKILL.md +589 -0
- package/claude-assets/skills/agent-validation-linter/lint-agents.sh +271 -0
- package/claude-assets/skills/bootstrap/bash-fundamentals.md +786 -0
- package/claude-assets/skills/bootstrap/database-connection.md +464 -0
- package/claude-assets/skills/bootstrap/error-handling.md +580 -0
- package/claude-assets/skills/bootstrap/file-operations.md +699 -0
- package/claude-assets/skills/bootstrap/skill-loader.md +616 -0
- package/claude-assets/skills/bootstrap/sqlite-params.sh +287 -0
- package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
- package/claude-assets/skills/cfn-automatic-memory-persistence/persist-agent-output.sh +48 -48
- package/claude-assets/skills/cfn-automatic-memory-persistence/query-agent-history.sh +34 -34
- package/claude-assets/skills/cfn-automatic-memory-persistence/test-memory-persistence.sh +17 -16
- package/claude-assets/skills/cfn-deliverable-validation/confidence-calculator.sh +261 -261
- package/claude-assets/skills/cfn-deployment/SKILL.md +293 -0
- package/claude-assets/skills/cfn-deployment/execute.sh +21 -0
- package/claude-assets/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
- package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
- package/claude-assets/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
- package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +38 -0
- package/claude-assets/skills/cfn-error-batching-strategy/lib/core-functions.sh +47 -47
- package/claude-assets/skills/cfn-expert-update/update-expert.sh +345 -345
- package/claude-assets/skills/cfn-file-operations/SKILL.md +290 -0
- package/claude-assets/skills/cfn-file-operations/execute.sh +129 -0
- package/claude-assets/skills/cfn-file-operations/lib/atomic-write.sh +294 -0
- package/claude-assets/skills/cfn-file-operations/lib/lock.sh +361 -0
- package/claude-assets/skills/cfn-file-operations/test.sh +369 -0
- package/claude-assets/skills/cfn-hybrid-routing/check-dependencies.sh +51 -51
- package/claude-assets/skills/cfn-intervention-detector/detect-intervention.sh +110 -110
- package/claude-assets/skills/cfn-intervention-orchestrator/execute-intervention.sh +58 -58
- package/claude-assets/skills/cfn-log-operations/SKILL.md +308 -0
- package/claude-assets/skills/cfn-log-operations/execute.sh +420 -0
- package/claude-assets/skills/cfn-log-operations/lib/rotate.sh +406 -0
- package/claude-assets/skills/cfn-log-operations/lib/search.sh +448 -0
- package/claude-assets/skills/cfn-log-operations/test.sh +394 -0
- package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
- package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +184 -23
- package/claude-assets/skills/cfn-loop-orchestration/security_utils.sh +24 -0
- package/claude-assets/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
- package/claude-assets/skills/cfn-loop-validation/orchestrate-cfn-loop.sh +252 -252
- package/claude-assets/skills/cfn-loop2-output-processing/process-validator-output.sh +275 -275
- package/claude-assets/skills/cfn-memory-management/check-memory.sh +159 -159
- package/claude-assets/skills/cfn-memory-management/cleanup-memory.sh +196 -196
- package/claude-assets/skills/cfn-node-heap-sizer/task-mode-heap-limiter.sh +325 -325
- package/claude-assets/skills/cfn-parameterized-queries/SKILL.md +339 -0
- package/claude-assets/skills/cfn-playbook/query-playbook.sh +19 -15
- package/claude-assets/skills/cfn-playbook/update-playbook.sh +25 -14
- package/claude-assets/skills/cfn-playbook-auto-update/auto-update-playbook.sh +85 -85
- package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +44 -0
- package/claude-assets/skills/cfn-promotion/SKILL.md +305 -0
- package/claude-assets/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
- package/claude-assets/skills/cfn-redis-coordination/agent-log.sh +4 -0
- package/claude-assets/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
- package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +74 -74
- package/claude-assets/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
- package/claude-assets/skills/cfn-redis-coordination/get-context.sh +145 -112
- package/claude-assets/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
- package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +3 -0
- package/claude-assets/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
- package/claude-assets/skills/cfn-redis-coordination/redis-functions.sh +33 -0
- package/claude-assets/skills/cfn-redis-coordination/report-completion.sh +24 -31
- package/claude-assets/skills/cfn-redis-coordination/store-context.sh +4 -0
- package/claude-assets/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
- package/claude-assets/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
- package/claude-assets/skills/cfn-scope-simplifier/simplify-scope.sh +67 -67
- package/claude-assets/skills/cfn-skill-loader/SKILL.md +466 -0
- package/claude-assets/skills/cfn-skill-loader/execute.sh +344 -0
- package/claude-assets/skills/cfn-specialist-injection/recommend-specialist.sh +56 -56
- package/claude-assets/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
- package/claude-assets/skills/cfn-standardized-error-handling/capture-agent-error.sh +86 -86
- package/claude-assets/skills/cfn-standardized-error-handling/test-error-handling.sh +165 -165
- package/claude-assets/skills/cfn-task-audit/get-audit-data.sh +42 -21
- package/claude-assets/skills/cfn-task-audit/store-task-audit.sh +17 -10
- package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +264 -264
- package/claude-assets/skills/cfn-task-decomposition/task-decomposer.sh +278 -278
- package/claude-assets/skills/cfn-test-runner/detect-regressions.sh +17 -14
- package/claude-assets/skills/cfn-test-runner/detect-regressions.sh.backup-1763392821 +55 -0
- package/claude-assets/skills/cfn-test-runner/store-benchmarks.sh +17 -19
- package/claude-assets/skills/cfn-transparency-middleware/middleware-config.sh +28 -28
- package/claude-assets/skills/cfn-transparency-middleware/performance-benchmark.sh +78 -78
- package/claude-assets/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
- package/claude-assets/skills/cfn-transparency-middleware/test-integration.sh +161 -161
- package/claude-assets/skills/cfn-transparency-middleware/test-transparency-skill.sh +367 -367
- package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +107 -92
- package/claude-assets/skills/cfn-transparency-middleware/wrap-agent.sh +131 -131
- package/claude-assets/skills/cfn-utilities/SKILL.md +237 -0
- package/claude-assets/skills/cfn-utilities/execute.sh +32 -0
- package/claude-assets/skills/cfn-utilities/lib/errors.sh +56 -0
- package/claude-assets/skills/cfn-utilities/lib/file-ops.sh +164 -0
- package/claude-assets/skills/cfn-utilities/lib/logging.sh +77 -0
- package/claude-assets/skills/cfn-utilities/lib/retry.sh +127 -0
- package/claude-assets/skills/cfn-utilities/test.sh +317 -0
- package/claude-assets/skills/docker-build/SKILL.md +96 -203
- package/claude-assets/skills/docker-build/build.sh +73 -73
- package/claude-assets/skills/integration/agent-handoff.sh +492 -0
- package/claude-assets/skills/integration/file-operations.sh +414 -0
- package/claude-assets/skills/json-validation/SKILL.md +431 -0
- package/claude-assets/skills/json-validation/test-validate-success-criteria.sh +421 -0
- package/claude-assets/skills/json-validation/validate-success-criteria.sh +197 -0
- package/claude-assets/skills/redis-coordination/validate-parameters.sh +34 -0
- package/claude-assets/skills/workflow-codification/APPROVAL_WORKFLOW.md +806 -0
- package/claude-assets/skills/workflow-codification/COST_TRACKING.md +637 -0
- package/claude-assets/skills/workflow-codification/DEPLOY_QUICK_REFERENCE.md +106 -0
- package/claude-assets/skills/workflow-codification/EDGE_CASE_TRACKING.md +404 -0
- package/claude-assets/skills/workflow-codification/PROPAGATE_UPDATE_QUICK_REFERENCE.md +366 -0
- package/claude-assets/skills/workflow-codification/README_PHASE4.md +457 -0
- package/claude-assets/skills/workflow-codification/SKILL.md +110 -0
- package/claude-assets/skills/workflow-codification/analyze-patterns.sh +899 -0
- package/claude-assets/skills/workflow-codification/approval-workflow.sh +514 -0
- package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh +481 -0
- package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh.backup-1763392820 +512 -0
- package/claude-assets/skills/workflow-codification/generate-skill-update.sh +525 -0
- package/claude-assets/skills/workflow-codification/lib/security-utils.sh +204 -0
- package/claude-assets/skills/workflow-codification/propagate-skill-update.sh +648 -0
- package/claude-assets/skills/workflow-codification/propagate-skill-update.sh.backup-1763392820 +664 -0
- package/claude-assets/skills/workflow-codification/review-skill.sh +643 -0
- package/claude-assets/skills/workflow-codification/templates/email-notification.txt +114 -0
- package/claude-assets/skills/workflow-codification/templates/slack-notification.md +85 -0
- package/claude-assets/skills/workflow-codification/test-integration.sh +296 -0
- package/claude-assets/skills/workflow-codification/test-metadata-update.sh +350 -0
- package/claude-assets/skills/workflow-codification/track-cost-savings.sh +486 -0
- package/claude-assets/skills/workflow-codification/track-cost-savings.sh.backup-1763392821 +445 -0
- package/claude-assets/skills/workflow-codification/track-edge-case.sh +290 -0
- package/claude-assets/skills/workflow-codification/workflow-codification.db +0 -0
- package/dist/ace/ace-curator.js +10 -2
- package/dist/ace/ace-curator.js.map +1 -1
- package/dist/ace/ace-generator.js +4 -0
- package/dist/ace/ace-generator.js.map +1 -1
- package/dist/ace/ace-reflector.js +1 -1
- package/dist/ace/ace-reflector.js.map +1 -1
- package/dist/ace/context-injection.js +24 -2
- package/dist/ace/context-injection.js.map +1 -1
- package/dist/agents/agent-loader.js +146 -165
- package/dist/agents/agent-loader.js.map +1 -1
- package/dist/agents/task-agent-integration.js +1 -1
- package/dist/agents/task-agent-integration.js.map +1 -1
- package/dist/api/health-endpoints.js +390 -0
- package/dist/api/health-endpoints.js.map +1 -0
- package/dist/cli/agent-executor.js +4 -1
- package/dist/cli/agent-executor.js.map +1 -1
- package/dist/cli/agent-prompt-builder.js +89 -1
- package/dist/cli/agent-prompt-builder.js.map +1 -1
- package/dist/cli/agent-spawn.js +130 -37
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/config-manager.js +91 -109
- package/dist/cli/config-manager.js.map +1 -1
- package/dist/cli/skill-cache-validator.js +412 -0
- package/dist/cli/skill-cache-validator.js.map +1 -0
- package/dist/cli/skill-cli.js +991 -0
- package/dist/cli/skill-cli.js.map +1 -0
- package/dist/cli/skill-execution-logger.js +284 -0
- package/dist/cli/skill-execution-logger.js.map +1 -0
- package/dist/cli/skill-loader.js +457 -0
- package/dist/cli/skill-loader.js.map +1 -0
- package/dist/coordination/event-bus.js +2 -2
- package/dist/coordination/event-bus.js.map +1 -1
- package/dist/coordination/fleet-manager.js +1 -1
- package/dist/coordination/fleet-manager.js.map +1 -1
- package/dist/coordination/index.js +23 -9
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/types/fleet-manager.types.js.map +1 -1
- package/dist/db/migration-manager.js +483 -0
- package/dist/db/migration-manager.js.map +1 -0
- package/dist/db/skills-query.js +535 -0
- package/dist/db/skills-query.js.map +1 -0
- package/dist/integration/DatabaseHandoff.js +507 -0
- package/dist/integration/DatabaseHandoff.js.map +1 -0
- package/dist/integration/StandardAdapter.js +291 -0
- package/dist/integration/StandardAdapter.js.map +1 -0
- package/dist/jobs/edge-case-analyzer.js +367 -0
- package/dist/jobs/edge-case-analyzer.js.map +1 -0
- package/dist/jobs/promotion-sla-enforcer.js +288 -0
- package/dist/jobs/promotion-sla-enforcer.js.map +1 -0
- package/dist/lib/agent-output-parser.js +518 -0
- package/dist/lib/agent-output-parser.js.map +1 -0
- package/dist/lib/agent-output-validator.js +950 -0
- package/dist/lib/agent-output-validator.js.map +1 -0
- package/dist/lib/agent-workspace.js +281 -0
- package/dist/lib/agent-workspace.js.map +1 -0
- package/dist/lib/artifact-registry.js +443 -0
- package/dist/lib/artifact-registry.js.map +1 -0
- package/dist/lib/atomic-file-writer.js +377 -0
- package/dist/lib/atomic-file-writer.js.map +1 -0
- package/dist/lib/backup-manager.js +779 -0
- package/dist/lib/backup-manager.js.map +1 -0
- package/dist/lib/checkpoint-manager.js +837 -0
- package/dist/lib/checkpoint-manager.js.map +1 -0
- package/dist/lib/circuit-breaker.js +340 -0
- package/dist/lib/circuit-breaker.js.map +1 -0
- package/dist/lib/completion-signal-handler.js +243 -0
- package/dist/lib/completion-signal-handler.js.map +1 -0
- package/dist/lib/config-manager.js +312 -0
- package/dist/lib/config-manager.js.map +1 -0
- package/dist/lib/config-migrator.js +386 -0
- package/dist/lib/config-migrator.js.map +1 -0
- package/dist/lib/config-validator.js +687 -0
- package/dist/lib/config-validator.js.map +1 -0
- package/dist/lib/correlation-cache.js +311 -0
- package/dist/lib/correlation-cache.js.map +1 -0
- package/dist/lib/correlation.js +263 -0
- package/dist/lib/correlation.js.map +1 -0
- package/dist/lib/database-service/connection-pool-manager.js +520 -0
- package/dist/lib/database-service/connection-pool-manager.js.map +1 -0
- package/dist/lib/database-service/correlation.js +329 -0
- package/dist/lib/database-service/correlation.js.map +1 -0
- package/dist/lib/database-service/errors.js +120 -0
- package/dist/lib/database-service/errors.js.map +1 -0
- package/dist/lib/database-service/index.js +168 -0
- package/dist/lib/database-service/index.js.map +1 -0
- package/dist/lib/database-service/postgres-adapter.js +526 -0
- package/dist/lib/database-service/postgres-adapter.js.map +1 -0
- package/dist/lib/database-service/redis-adapter.js +360 -0
- package/dist/lib/database-service/redis-adapter.js.map +1 -0
- package/dist/lib/database-service/sqlite-adapter.js +544 -0
- package/dist/lib/database-service/sqlite-adapter.js.map +1 -0
- package/dist/lib/database-service/transaction-manager.js +773 -0
- package/dist/lib/database-service/transaction-manager.js.map +1 -0
- package/dist/lib/database-service/types.js +23 -0
- package/dist/lib/database-service/types.js.map +1 -0
- package/dist/lib/deadlock-resolver.js +292 -0
- package/dist/lib/deadlock-resolver.js.map +1 -0
- package/dist/lib/distributed-lock.js +451 -0
- package/dist/lib/distributed-lock.js.map +1 -0
- package/dist/lib/edge-case-deduplicator.js +227 -0
- package/dist/lib/edge-case-deduplicator.js.map +1 -0
- package/dist/lib/encryption-manager.js +322 -0
- package/dist/lib/encryption-manager.js.map +1 -0
- package/dist/lib/error-aggregator.js +234 -0
- package/dist/lib/error-aggregator.js.map +1 -0
- package/dist/lib/errors.js +287 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/file-lock-manager.js +578 -0
- package/dist/lib/file-lock-manager.js.map +1 -0
- package/dist/lib/file-operations.js +367 -0
- package/dist/lib/file-operations.js.map +1 -0
- package/dist/lib/idempotent-write.js +237 -0
- package/dist/lib/idempotent-write.js.map +1 -0
- package/dist/lib/integration-schema-validator.js +522 -0
- package/dist/lib/integration-schema-validator.js.map +1 -0
- package/dist/lib/lock-health-monitor.js +298 -0
- package/dist/lib/lock-health-monitor.js.map +1 -0
- package/dist/lib/log-shipper.js +422 -0
- package/dist/lib/log-shipper.js.map +1 -0
- package/dist/lib/logging.js +146 -0
- package/dist/lib/logging.js.map +1 -0
- package/dist/lib/message-deduplicator.js +439 -0
- package/dist/lib/message-deduplicator.js.map +1 -0
- package/dist/lib/multi-system-query.js +604 -0
- package/dist/lib/multi-system-query.js.map +1 -0
- package/dist/lib/orphan-detector.js +332 -0
- package/dist/lib/orphan-detector.js.map +1 -0
- package/dist/lib/password-generator.js +166 -0
- package/dist/lib/password-generator.js.map +1 -0
- package/dist/lib/path-validator.js +429 -0
- package/dist/lib/path-validator.js.map +1 -0
- package/dist/lib/query-translator.js +905 -0
- package/dist/lib/query-translator.js.map +1 -0
- package/dist/lib/queue-recovery.js +469 -0
- package/dist/lib/queue-recovery.js.map +1 -0
- package/dist/lib/redis-queue-manager.js +512 -0
- package/dist/lib/redis-queue-manager.js.map +1 -0
- package/dist/lib/reflection-archiver.js +272 -0
- package/dist/lib/reflection-archiver.js.map +1 -0
- package/dist/lib/retry-manager.js +453 -0
- package/dist/lib/retry-manager.js.map +1 -0
- package/dist/lib/retry.js +262 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/schema-transform.js +695 -0
- package/dist/lib/schema-transform.js.map +1 -0
- package/dist/lib/schema-validator.js +491 -0
- package/dist/lib/schema-validator.js.map +1 -0
- package/dist/lib/skill-cache.js +297 -0
- package/dist/lib/skill-cache.js.map +1 -0
- package/dist/lib/skill-content-manager.js +337 -0
- package/dist/lib/skill-content-manager.js.map +1 -0
- package/dist/lib/skill-frontmatter-parser.js +237 -0
- package/dist/lib/skill-frontmatter-parser.js.map +1 -0
- package/dist/lib/skill-git-integration.js +275 -0
- package/dist/lib/skill-git-integration.js.map +1 -0
- package/dist/lib/skill-markdown-validator.js +396 -0
- package/dist/lib/skill-markdown-validator.js.map +1 -0
- package/dist/lib/skill-output-parser.js +312 -0
- package/dist/lib/skill-output-parser.js.map +1 -0
- package/dist/lib/unified-query-api.js +467 -0
- package/dist/lib/unified-query-api.js.map +1 -0
- package/dist/middleware/auth-middleware.js +350 -0
- package/dist/middleware/auth-middleware.js.map +1 -0
- package/dist/middleware/schema-validation.js +347 -0
- package/dist/middleware/schema-validation.js.map +1 -0
- package/dist/providers/anthropic-provider.js +1 -1
- package/dist/providers/anthropic-provider.js.map +1 -1
- package/dist/providers/provider-factory.js +2 -2
- package/dist/providers/provider-factory.js.map +1 -1
- package/dist/services/edge-case-analyzer.js +321 -0
- package/dist/services/edge-case-analyzer.js.map +1 -0
- package/dist/services/edge-case-deduplicator.js +266 -0
- package/dist/services/edge-case-deduplicator.js.map +1 -0
- package/dist/services/edge-case-detector.js +337 -0
- package/dist/services/edge-case-detector.js.map +1 -0
- package/dist/services/edge-case-tracker.js +547 -0
- package/dist/services/edge-case-tracker.js.map +1 -0
- package/dist/services/health-check-system.js +586 -0
- package/dist/services/health-check-system.js.map +1 -0
- package/dist/services/metrics-logger.js +412 -0
- package/dist/services/metrics-logger.js.map +1 -0
- package/dist/services/patch-generator.js +378 -0
- package/dist/services/patch-generator.js.map +1 -0
- package/dist/services/patch-validator.js +337 -0
- package/dist/services/patch-validator.js.map +1 -0
- package/dist/services/performance-monitor.js +811 -0
- package/dist/services/performance-monitor.js.map +1 -0
- package/dist/services/promotion-pipeline.js +918 -0
- package/dist/services/promotion-pipeline.js.map +1 -0
- package/dist/services/promotion-validator.js +394 -0
- package/dist/services/promotion-validator.js.map +1 -0
- package/dist/services/reflection-logger.js +388 -0
- package/dist/services/reflection-logger.js.map +1 -0
- package/dist/services/skill-deployment.js +472 -0
- package/dist/services/skill-deployment.js.map +1 -0
- package/dist/services/skill-loader.js +427 -0
- package/dist/services/skill-loader.js.map +1 -0
- package/dist/services/skill-promotion.js +372 -0
- package/dist/services/skill-promotion.js.map +1 -0
- package/dist/services/skill-validator.js +454 -0
- package/dist/services/skill-validator.js.map +1 -0
- package/dist/services/skill-versioning.js +244 -0
- package/dist/services/skill-versioning.js.map +1 -0
- package/dist/services/workspace-supervisor.js +597 -0
- package/dist/services/workspace-supervisor.js.map +1 -0
- package/dist/types/agent-output.js +44 -0
- package/dist/types/agent-output.js.map +1 -0
- package/dist/types/config.js +28 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/edge-case.js +45 -0
- package/dist/types/edge-case.js.map +1 -0
- package/package.json +201 -176
- package/readme/README.md +19 -4
- package/scripts/artifact-cleanup.sh +392 -0
- package/scripts/backup-cleanup.sh +627 -0
- package/scripts/cleanup-workspaces.sh +412 -0
- package/scripts/cleanup-yaml-configs.sh +141 -0
- package/scripts/deploy-approved-skills.sh +263 -0
- package/scripts/deploy-production.sh +355 -355
- package/scripts/docker-playwright-fix.sh +311 -311
- package/scripts/docker-rebuild-all-agents.sh +127 -127
- package/scripts/health-check.sh +447 -0
- package/scripts/log-aggregator.sh +554 -0
- package/scripts/log-monitor.sh +629 -0
- package/scripts/manage-agent-workspaces.sh +434 -0
- package/scripts/memory-leak-prevention.sh +305 -305
- package/scripts/migrate-artifacts.sh +563 -0
- package/scripts/migrate-schema.sh +533 -0
- package/scripts/migrate-yaml-to-json.sh +465 -0
- package/scripts/promote-staged-skills.sh +423 -0
- package/scripts/run-marketing-tests.sh +42 -42
- package/scripts/update_paths.sh +46 -46
- package/scripts/verify-no-secrets.sh +88 -35
- package/.claude/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
- package/.claude/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
- package/.claude/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
- package/.claude/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
- package/README.md.backup_before_replace +0 -781
- package/claude-assets/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
- package/claude-assets/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
- package/claude-assets/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
- package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
- 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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"}
|