claude-flow-novice 2.15.5 → 2.15.6
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/.gs-api-quota.json +16 -0
- package/.claude/cfn-extras/.gs-progress-state.json +22 -0
- package/.claude/cfn-extras/GOOGLE_SHEETS_IMPLEMENTATION_SUMMARY.md +414 -0
- package/.claude/cfn-extras/agents/google-sheets/README.md +114 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-advanced-analytics-specialist.md +288 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-api-integrator.md +127 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-automation-scripting-specialist.md +195 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-business-validator.md +179 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-collaboration-security-specialist.md +240 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-coordinator.md +214 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-data-transformer.md +127 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-data-validation-quality-specialist.md +177 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-data-validator.md +119 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-data-visualization-specialist.md +135 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-design-layout-specialist.md +109 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-formula-engineer.md +127 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-formula-engineering-specialist.md +138 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-formula-validator.md +128 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-generalist.md +645 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-integration-api-specialist.md +258 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-performance-analyst.md +125 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-performance-optimization-specialist.md +211 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-schema-designer.md +130 -0
- package/.claude/cfn-extras/agents/google-sheets/google-sheets-template-architecture-specialist.md +259 -0
- package/.claude/cfn-extras/docs/GOOGLE_SHEETS_CFN_LOOP.md +617 -0
- package/.claude/cfn-extras/skills/GOOGLE_SHEETS_SKILLS_README.md +453 -0
- package/.claude/cfn-extras/skills/google-sheets-api-coordinator/SKILL.md +272 -0
- package/.claude/cfn-extras/skills/google-sheets-api-coordinator/api-call.sh +254 -0
- package/.claude/cfn-extras/skills/google-sheets-api-coordinator/test.sh +174 -0
- package/.claude/cfn-extras/skills/google-sheets-api-coordinator/validate.sh +98 -0
- package/.claude/cfn-extras/skills/google-sheets-decomposition/SKILL.md +269 -0
- package/.claude/cfn-extras/skills/google-sheets-decomposition/decompose.sh +313 -0
- package/.claude/cfn-extras/skills/google-sheets-formula-builder/SKILL.md +237 -0
- package/.claude/cfn-extras/skills/google-sheets-formula-builder/build-formula.sh +220 -0
- package/.claude/cfn-extras/skills/google-sheets-formula-builder/test.sh +172 -0
- package/.claude/cfn-extras/skills/google-sheets-formula-builder/validate.sh +98 -0
- package/.claude/cfn-extras/skills/google-sheets-progress/SKILL.md +287 -0
- package/.claude/cfn-extras/skills/google-sheets-progress/test.sh +385 -0
- package/.claude/cfn-extras/skills/google-sheets-progress/track-progress.sh +516 -0
- package/.claude/cfn-extras/skills/google-sheets-progress/validate.sh +119 -0
- package/.claude/cfn-extras/skills/google-sheets-sprint-order/SKILL.md +277 -0
- package/.claude/cfn-extras/skills/google-sheets-sprint-order/order-sprints.sh +233 -0
- package/.claude/cfn-extras/skills/google-sheets-validation/SKILL.md +352 -0
- package/.claude/cfn-extras/skills/google-sheets-validation/test.sh +355 -0
- package/.claude/cfn-extras/skills/google-sheets-validation/validate-state.sh +374 -0
- package/.claude/cfn-extras/skills/google-sheets-validation/validate.sh +128 -0
- package/.claude/commands/cfn-context.md +10 -0
- package/.claude/commands/cfn-loop-cli.md +36 -15
- package/.claude/commands/google-sheets/google-sheets-loop.md +289 -0
- package/.claude/skills/cfn-agent-selector/SKILL.md +143 -0
- package/.claude/skills/cfn-agent-selector/select-agents.sh +94 -0
- package/.claude/skills/cfn-agent-spawning/get-agent-provider-env.sh +22 -2
- package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +21 -2
- package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +11 -5
- package/.claude/skills/cfn-docker-redis-coordination/MIGRATION_SUMMARY.md +348 -0
- package/.claude/skills/cfn-docker-redis-coordination/README.md +294 -0
- package/.claude/skills/cfn-docker-redis-coordination/jest.config.js +37 -0
- package/.claude/skills/cfn-docker-redis-coordination/package-lock.json +5259 -0
- package/.claude/skills/cfn-docker-redis-coordination/package.json +40 -0
- package/.claude/skills/cfn-docker-redis-coordination/src/coordinator.ts +801 -0
- package/.claude/skills/cfn-docker-redis-coordination/src/index.ts +42 -0
- package/.claude/skills/cfn-docker-redis-coordination/src/types.ts +351 -0
- package/.claude/skills/cfn-docker-redis-coordination/tests/coordinator.test.ts +1464 -0
- package/.claude/skills/cfn-docker-redis-coordination/tsconfig.json +30 -0
- package/.claude/skills/cfn-loop-orchestration/.eslintrc.js +56 -0
- package/.claude/skills/cfn-loop-orchestration/.prettierrc.json +18 -0
- package/.claude/skills/cfn-loop-orchestration/README.md +149 -41
- package/.claude/skills/cfn-loop-orchestration/jest.config.js +67 -0
- package/.claude/skills/cfn-loop-orchestration/orchestrate-wrapper.sh +268 -0
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +91 -8
- package/.claude/skills/cfn-loop-orchestration/package-lock.json +5470 -0
- package/.claude/skills/cfn-loop-orchestration/package.json +49 -0
- package/.claude/skills/cfn-loop-orchestration/src/agent-spawner/agent-spawner.ts +34 -0
- package/.claude/skills/cfn-loop-orchestration/src/gate-checker/gate-checker.ts +36 -0
- package/.claude/skills/cfn-loop-orchestration/src/index.ts +14 -0
- package/.claude/skills/cfn-loop-orchestration/src/orchestrator/orchestrator.ts +31 -0
- package/.claude/skills/cfn-loop-orchestration/src/redis/redis-coordinator.ts +72 -0
- package/.claude/skills/cfn-loop-orchestration/src/types.ts +188 -0
- package/.claude/skills/cfn-loop-orchestration/src/utils/logger.ts +32 -0
- package/.claude/skills/cfn-loop-orchestration/tests/setup.ts +22 -0
- package/.claude/skills/cfn-loop-orchestration/tests/types.test.ts +132 -0
- package/.claude/skills/cfn-loop-orchestration/tsconfig.json +54 -0
- package/.claude/skills/cfn-redis-coordination/bash-wrappers/store-context.sh +23 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-logger.d.ts +92 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-logger.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-logger.js +329 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-logger.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-recovery.d.ts +75 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-recovery.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-recovery.js +302 -0
- package/.claude/skills/cfn-redis-coordination/dist/agent-recovery.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/completion-reporter.d.ts +58 -0
- package/.claude/skills/cfn-redis-coordination/dist/completion-reporter.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/completion-reporter.js +237 -0
- package/.claude/skills/cfn-redis-coordination/dist/completion-reporter.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/context-manager.d.ts +63 -0
- package/.claude/skills/cfn-redis-coordination/dist/context-manager.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/context-manager.js +230 -0
- package/.claude/skills/cfn-redis-coordination/dist/context-manager.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/index.d.ts +45 -0
- package/.claude/skills/cfn-redis-coordination/dist/index.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/index.js +114 -0
- package/.claude/skills/cfn-redis-coordination/dist/index.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/mode-detector.d.ts +31 -0
- package/.claude/skills/cfn-redis-coordination/dist/mode-detector.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/mode-detector.js +185 -0
- package/.claude/skills/cfn-redis-coordination/dist/mode-detector.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/redis-client.d.ts +191 -0
- package/.claude/skills/cfn-redis-coordination/dist/redis-client.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/redis-client.js +509 -0
- package/.claude/skills/cfn-redis-coordination/dist/redis-client.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/result-collector.d.ts +75 -0
- package/.claude/skills/cfn-redis-coordination/dist/result-collector.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/result-collector.js +281 -0
- package/.claude/skills/cfn-redis-coordination/dist/result-collector.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/swarm-manager.d.ts +75 -0
- package/.claude/skills/cfn-redis-coordination/dist/swarm-manager.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/swarm-manager.js +354 -0
- package/.claude/skills/cfn-redis-coordination/dist/swarm-manager.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-analyzer.d.ts +62 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-analyzer.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-analyzer.js +305 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-analyzer.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-executor.d.ts +97 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-executor.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-executor.js +283 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-executor.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/types.d.ts +176 -0
- package/.claude/skills/cfn-redis-coordination/dist/types.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/types.js +81 -0
- package/.claude/skills/cfn-redis-coordination/dist/types.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/waiting-coordinator.d.ts +86 -0
- package/.claude/skills/cfn-redis-coordination/dist/waiting-coordinator.d.ts.map +1 -0
- package/.claude/skills/cfn-redis-coordination/dist/waiting-coordinator.js +419 -0
- package/.claude/skills/cfn-redis-coordination/dist/waiting-coordinator.js.map +1 -0
- package/.claude/skills/cfn-redis-coordination/docs/migration/PHASE_3_REDIS_COORDINATION_COMPLETION_REPORT.md +553 -0
- package/.claude/skills/cfn-redis-coordination/jest.config.js +23 -0
- package/.claude/skills/cfn-redis-coordination/package-lock.json +5272 -0
- package/.claude/skills/cfn-redis-coordination/package.json +45 -0
- package/.claude/skills/cfn-redis-coordination/redis-cli-wrapper.sh +21 -8
- package/.claude/skills/cfn-redis-coordination/src/agent-logger.ts +446 -0
- package/.claude/skills/cfn-redis-coordination/src/agent-recovery.ts +454 -0
- package/.claude/skills/cfn-redis-coordination/src/completion-reporter.ts +396 -0
- package/.claude/skills/cfn-redis-coordination/src/context-manager.ts +327 -0
- package/.claude/skills/cfn-redis-coordination/src/index.ts +82 -0
- package/.claude/skills/cfn-redis-coordination/src/mode-detector.ts +155 -0
- package/.claude/skills/cfn-redis-coordination/src/redis/redis-client.ts +305 -0
- package/.claude/skills/cfn-redis-coordination/src/redis/redis-functions.ts +283 -0
- package/.claude/skills/cfn-redis-coordination/src/redis-client.ts +654 -0
- package/.claude/skills/cfn-redis-coordination/src/result-collector.ts +437 -0
- package/.claude/skills/cfn-redis-coordination/src/swarm-manager.ts +494 -0
- package/.claude/skills/cfn-redis-coordination/src/task-analyzer.ts +404 -0
- package/.claude/skills/cfn-redis-coordination/src/task-executor.ts +423 -0
- package/.claude/skills/cfn-redis-coordination/src/types.ts +235 -0
- package/.claude/skills/cfn-redis-coordination/src/waiting-coordinator.ts +587 -0
- package/.claude/skills/cfn-redis-coordination/test-connection-attempts.js +70 -0
- package/.claude/skills/cfn-redis-coordination/test-mode-simple.js +121 -0
- package/.claude/skills/cfn-redis-coordination/test-redis-check.js +84 -0
- package/.claude/skills/cfn-redis-coordination/test-task-mode-redis.cjs +391 -0
- package/.claude/skills/cfn-redis-coordination/tests/coordination.test.ts +779 -0
- package/.claude/skills/cfn-redis-coordination/tsconfig.json +31 -0
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +172 -2
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +1 -1
- package/claude-assets/agents/custom/cfn-redis-operations.md +530 -0
- package/claude-assets/agents/custom/cfn-system-expert.md +77 -0
- package/claude-assets/cfn-extras/.gs-api-quota.json +16 -0
- package/claude-assets/cfn-extras/.gs-progress-state.json +22 -0
- package/claude-assets/cfn-extras/GOOGLE_SHEETS_IMPLEMENTATION_SUMMARY.md +414 -0
- package/claude-assets/cfn-extras/agents/google-sheets/README.md +114 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-advanced-analytics-specialist.md +288 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-api-integrator.md +127 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-automation-scripting-specialist.md +195 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-business-validator.md +179 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-collaboration-security-specialist.md +240 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-coordinator.md +214 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-data-transformer.md +127 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-data-validation-quality-specialist.md +177 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-data-validator.md +119 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-data-visualization-specialist.md +135 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-design-layout-specialist.md +109 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-formula-engineer.md +127 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-formula-engineering-specialist.md +138 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-formula-validator.md +128 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-generalist.md +645 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-integration-api-specialist.md +258 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-performance-analyst.md +125 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-performance-optimization-specialist.md +211 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-schema-designer.md +130 -0
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-template-architecture-specialist.md +259 -0
- package/claude-assets/cfn-extras/docs/GOOGLE_SHEETS_CFN_LOOP.md +617 -0
- package/claude-assets/cfn-extras/skills/GOOGLE_SHEETS_SKILLS_README.md +453 -0
- package/claude-assets/cfn-extras/skills/google-sheets-api-coordinator/SKILL.md +272 -0
- package/claude-assets/cfn-extras/skills/google-sheets-api-coordinator/api-call.sh +254 -0
- package/claude-assets/cfn-extras/skills/google-sheets-api-coordinator/test.sh +174 -0
- package/claude-assets/cfn-extras/skills/google-sheets-api-coordinator/validate.sh +98 -0
- package/claude-assets/cfn-extras/skills/google-sheets-decomposition/SKILL.md +269 -0
- package/claude-assets/cfn-extras/skills/google-sheets-decomposition/decompose.sh +313 -0
- package/claude-assets/cfn-extras/skills/google-sheets-formula-builder/SKILL.md +237 -0
- package/claude-assets/cfn-extras/skills/google-sheets-formula-builder/build-formula.sh +220 -0
- package/claude-assets/cfn-extras/skills/google-sheets-formula-builder/test.sh +172 -0
- package/claude-assets/cfn-extras/skills/google-sheets-formula-builder/validate.sh +98 -0
- package/claude-assets/cfn-extras/skills/google-sheets-progress/SKILL.md +287 -0
- package/claude-assets/cfn-extras/skills/google-sheets-progress/test.sh +385 -0
- package/claude-assets/cfn-extras/skills/google-sheets-progress/track-progress.sh +516 -0
- package/claude-assets/cfn-extras/skills/google-sheets-progress/validate.sh +119 -0
- package/claude-assets/cfn-extras/skills/google-sheets-sprint-order/SKILL.md +277 -0
- package/claude-assets/cfn-extras/skills/google-sheets-sprint-order/order-sprints.sh +233 -0
- package/claude-assets/cfn-extras/skills/google-sheets-validation/SKILL.md +352 -0
- package/claude-assets/cfn-extras/skills/google-sheets-validation/test.sh +355 -0
- package/claude-assets/cfn-extras/skills/google-sheets-validation/validate-state.sh +374 -0
- package/claude-assets/cfn-extras/skills/google-sheets-validation/validate.sh +128 -0
- package/claude-assets/commands/cfn-context.md +10 -0
- package/claude-assets/commands/cfn-loop-cli.md +36 -15
- package/claude-assets/commands/google-sheets/google-sheets-loop.md +289 -0
- package/claude-assets/hooks/cfn-pre-execution/SESSION_START_README.md +87 -0
- package/claude-assets/hooks/cfn-pre-execution/TEST_SESSION_START.md +128 -0
- package/claude-assets/hooks/cfn-pre-execution/session-start-context.sh +111 -0
- package/claude-assets/skills/cfn-agent-selection-with-fallback/INTEGRATION_EXAMPLE.md +209 -0
- package/claude-assets/skills/cfn-agent-selection-with-fallback/README.md +130 -0
- package/claude-assets/skills/cfn-agent-selection-with-fallback/SKILL.md +243 -0
- package/claude-assets/skills/cfn-agent-selection-with-fallback/agent-mappings.json +142 -0
- package/claude-assets/skills/cfn-agent-selection-with-fallback/select-agents.sh +173 -0
- package/claude-assets/skills/cfn-agent-selection-with-fallback/task-classifier.sh +71 -0
- package/claude-assets/skills/cfn-agent-selection-with-fallback/test-agent-selection.sh +282 -0
- package/claude-assets/skills/cfn-agent-selector/SKILL.md +143 -0
- package/claude-assets/skills/cfn-agent-selector/select-agents.sh +94 -0
- package/claude-assets/skills/cfn-agent-spawning/get-agent-provider-env.sh +22 -2
- package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +21 -2
- package/claude-assets/skills/cfn-docker-coordination/.eslintrc.json +33 -0
- package/claude-assets/skills/cfn-docker-coordination/README.md +349 -0
- package/claude-assets/skills/cfn-docker-coordination/docker-helpers.sh +433 -0
- package/claude-assets/skills/cfn-docker-coordination/jest.config.js +25 -0
- package/claude-assets/skills/cfn-docker-coordination/package-lock.json +6827 -0
- package/claude-assets/skills/cfn-docker-coordination/package.json +38 -0
- package/claude-assets/skills/cfn-docker-coordination/src/agent-container.ts +471 -0
- package/claude-assets/skills/cfn-docker-coordination/src/docker-client.ts +483 -0
- package/claude-assets/skills/cfn-docker-coordination/src/health-checker.ts +418 -0
- package/claude-assets/skills/cfn-docker-coordination/src/index.ts +45 -0
- package/claude-assets/skills/cfn-docker-coordination/src/network-manager.ts +377 -0
- package/claude-assets/skills/cfn-docker-coordination/src/types.ts +412 -0
- package/claude-assets/skills/cfn-docker-coordination/src/volume-manager.ts +389 -0
- package/claude-assets/skills/cfn-docker-coordination/tests/agent-container.test.ts +379 -0
- package/claude-assets/skills/cfn-docker-coordination/tests/docker-client.test.ts +345 -0
- package/claude-assets/skills/cfn-docker-coordination/tests/health-checker.test.ts +535 -0
- package/claude-assets/skills/cfn-docker-coordination/tests/integration.test.ts +193 -0
- package/claude-assets/skills/cfn-docker-coordination/tests/network-manager.test.ts +352 -0
- package/claude-assets/skills/cfn-docker-coordination/tests/setup.ts +36 -0
- package/claude-assets/skills/cfn-docker-coordination/tsconfig.json +29 -0
- package/claude-assets/skills/cfn-docker-logging/INTEGRATION.md +268 -0
- package/claude-assets/skills/cfn-docker-logging/SAMPLE_OUTPUTS.md +237 -0
- package/claude-assets/skills/cfn-docker-logging/SKILL.md +442 -0
- package/claude-assets/skills/cfn-docker-logging/capture-container-logs.sh +120 -0
- package/claude-assets/skills/cfn-docker-logging/enable-logging.sh +430 -0
- package/claude-assets/skills/cfn-docker-logging/init-hybrid-logging.sh +210 -0
- package/claude-assets/skills/cfn-docker-logging/queries/analytics-summary.sh +87 -0
- package/claude-assets/skills/cfn-docker-logging/queries/query-agent-timeline.sh +51 -0
- package/claude-assets/skills/cfn-docker-logging/queries/query-consensus-history.sh +56 -0
- package/claude-assets/skills/cfn-docker-logging/queries/query-coordination-timeline.sh +39 -0
- package/claude-assets/skills/cfn-docker-logging/queries/query-failed-containers.sh +40 -0
- package/claude-assets/skills/cfn-docker-logging/queries/query-gate-checks.sh +39 -0
- package/claude-assets/skills/cfn-docker-logging/schema.sql +111 -0
- package/claude-assets/skills/cfn-docker-logging/sqlite-helpers.sh +240 -0
- package/claude-assets/skills/cfn-docker-logging/test-hybrid-logging.sh +331 -0
- package/claude-assets/skills/cfn-docker-loop-orchestration/orchestrate.sh +11 -5
- package/claude-assets/skills/cfn-docker-redis-coordination/MIGRATION_SUMMARY.md +348 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/README.md +294 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/jest.config.js +37 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/package-lock.json +5259 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/package.json +40 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/src/coordinator.ts +801 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/src/index.ts +42 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/src/types.ts +351 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/tests/coordinator.test.ts +1464 -0
- package/claude-assets/skills/cfn-docker-redis-coordination/tsconfig.json +30 -0
- package/claude-assets/skills/cfn-error-logging/.eslintrc.json +57 -0
- package/claude-assets/skills/cfn-error-logging/.prettierrc.json +10 -0
- package/claude-assets/skills/cfn-error-logging/MIGRATION_SUMMARY.md +485 -0
- package/claude-assets/skills/cfn-error-logging/package.json +47 -0
- package/claude-assets/skills/cfn-error-logging/src/error-logger.ts +1042 -0
- package/claude-assets/skills/cfn-error-logging/src/index.ts +12 -0
- package/claude-assets/skills/cfn-error-logging/src/types.ts +456 -0
- package/claude-assets/skills/cfn-error-logging/tests/error-logger.test.ts +1302 -0
- package/claude-assets/skills/cfn-error-logging/tsconfig.json +38 -0
- package/claude-assets/skills/cfn-loop-orchestration/.eslintrc.js +56 -0
- package/claude-assets/skills/cfn-loop-orchestration/.prettierrc.json +18 -0
- package/claude-assets/skills/cfn-loop-orchestration/README.md +149 -41
- package/claude-assets/skills/cfn-loop-orchestration/jest.config.js +67 -0
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate-wrapper.sh +268 -0
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +91 -8
- package/claude-assets/skills/cfn-loop-orchestration/package-lock.json +5470 -0
- package/claude-assets/skills/cfn-loop-orchestration/package.json +49 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/agent-spawner/agent-spawner.ts +34 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/gate-checker/gate-checker.ts +36 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/index.ts +14 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/orchestrator/orchestrator.ts +31 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/redis/redis-coordinator.ts +72 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/types.ts +188 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/utils/logger.ts +32 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/setup.ts +22 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/types.test.ts +132 -0
- package/claude-assets/skills/cfn-loop-orchestration/tsconfig.json +54 -0
- package/claude-assets/skills/cfn-redis-coordination/bash-wrappers/store-context.sh +23 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-logger.d.ts +92 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-logger.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-logger.js +329 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-logger.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-recovery.d.ts +75 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-recovery.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-recovery.js +302 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/agent-recovery.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/completion-reporter.d.ts +58 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/completion-reporter.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/completion-reporter.js +237 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/completion-reporter.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/context-manager.d.ts +63 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/context-manager.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/context-manager.js +230 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/context-manager.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/index.d.ts +45 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/index.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/index.js +114 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/index.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/mode-detector.d.ts +31 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/mode-detector.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/mode-detector.js +185 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/mode-detector.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/redis-client.d.ts +191 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/redis-client.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/redis-client.js +509 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/redis-client.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/result-collector.d.ts +75 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/result-collector.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/result-collector.js +281 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/result-collector.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/swarm-manager.d.ts +75 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/swarm-manager.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/swarm-manager.js +354 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/swarm-manager.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-analyzer.d.ts +62 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-analyzer.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-analyzer.js +305 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-analyzer.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-executor.d.ts +97 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-executor.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-executor.js +283 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-executor.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/types.d.ts +176 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/types.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/types.js +81 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/types.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/waiting-coordinator.d.ts +86 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/waiting-coordinator.d.ts.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/waiting-coordinator.js +419 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/waiting-coordinator.js.map +1 -0
- package/claude-assets/skills/cfn-redis-coordination/docs/migration/PHASE_3_REDIS_COORDINATION_COMPLETION_REPORT.md +553 -0
- package/claude-assets/skills/cfn-redis-coordination/jest.config.js +23 -0
- package/claude-assets/skills/cfn-redis-coordination/package-lock.json +5272 -0
- package/claude-assets/skills/cfn-redis-coordination/package.json +45 -0
- package/claude-assets/skills/cfn-redis-coordination/redis-cli-wrapper.sh +21 -8
- package/claude-assets/skills/cfn-redis-coordination/src/agent-logger.ts +446 -0
- package/claude-assets/skills/cfn-redis-coordination/src/agent-recovery.ts +454 -0
- package/claude-assets/skills/cfn-redis-coordination/src/completion-reporter.ts +396 -0
- package/claude-assets/skills/cfn-redis-coordination/src/context-manager.ts +327 -0
- package/claude-assets/skills/cfn-redis-coordination/src/index.ts +82 -0
- package/claude-assets/skills/cfn-redis-coordination/src/mode-detector.ts +155 -0
- package/claude-assets/skills/cfn-redis-coordination/src/redis/redis-client.ts +305 -0
- package/claude-assets/skills/cfn-redis-coordination/src/redis/redis-functions.ts +283 -0
- package/claude-assets/skills/cfn-redis-coordination/src/redis-client.ts +654 -0
- package/claude-assets/skills/cfn-redis-coordination/src/result-collector.ts +437 -0
- package/claude-assets/skills/cfn-redis-coordination/src/swarm-manager.ts +494 -0
- package/claude-assets/skills/cfn-redis-coordination/src/task-analyzer.ts +404 -0
- package/claude-assets/skills/cfn-redis-coordination/src/task-executor.ts +423 -0
- package/claude-assets/skills/cfn-redis-coordination/src/types.ts +235 -0
- package/claude-assets/skills/cfn-redis-coordination/src/waiting-coordinator.ts +587 -0
- package/claude-assets/skills/cfn-redis-coordination/test-connection-attempts.js +70 -0
- package/claude-assets/skills/cfn-redis-coordination/test-mode-simple.js +121 -0
- package/claude-assets/skills/cfn-redis-coordination/test-redis-check.js +84 -0
- package/claude-assets/skills/cfn-redis-coordination/test-task-mode-redis.cjs +391 -0
- package/claude-assets/skills/cfn-redis-coordination/tests/coordination.test.ts +779 -0
- package/claude-assets/skills/cfn-redis-coordination/tsconfig.json +31 -0
- package/claude-assets/skills/cfn-skill-propagation/README.md +233 -0
- package/claude-assets/skills/cfn-skill-propagation/package-lock.json +5174 -0
- package/claude-assets/skills/cfn-skill-propagation/package.json +52 -0
- package/claude-assets/skills/cfn-skill-propagation/propagate-skill-update.sh +32 -0
- package/claude-assets/skills/cfn-skill-propagation/src/cli.ts +75 -0
- package/claude-assets/skills/cfn-skill-propagation/src/database-adapter.ts +239 -0
- package/claude-assets/skills/cfn-skill-propagation/src/file-system-adapter.ts +113 -0
- package/claude-assets/skills/cfn-skill-propagation/src/index.ts +72 -0
- package/claude-assets/skills/cfn-skill-propagation/src/logger.ts +43 -0
- package/claude-assets/skills/cfn-skill-propagation/src/metadata-parser.ts +154 -0
- package/claude-assets/skills/cfn-skill-propagation/src/skill-propagator.ts +274 -0
- package/claude-assets/skills/cfn-skill-propagation/src/skill-validator.ts +179 -0
- package/claude-assets/skills/cfn-skill-propagation/src/types.ts +143 -0
- package/claude-assets/skills/cfn-skill-propagation/src/version-manager.ts +118 -0
- package/claude-assets/skills/cfn-skill-propagation/tests/file-system-adapter.test.ts +91 -0
- package/claude-assets/skills/cfn-skill-propagation/tests/metadata-parser.test.ts +176 -0
- package/claude-assets/skills/cfn-skill-propagation/tests/skill-propagator.test.ts +209 -0
- package/claude-assets/skills/cfn-skill-propagation/tests/skill-validator.test.ts +203 -0
- package/claude-assets/skills/cfn-skill-propagation/tests/version-manager.test.ts +115 -0
- package/claude-assets/skills/cfn-skill-propagation/tsconfig.json +34 -0
- package/claude-assets/skills/task-classifier/SKILL.md +81 -0
- package/claude-assets/skills/task-classifier/classify-task.sh +62 -0
- package/claude-assets/skills/workflow-codification/package-lock.json +5170 -0
- package/claude-assets/skills/workflow-codification/package.json +30 -0
- package/claude-assets/skills/workflow-codification/src/index.ts +24 -0
- package/claude-assets/skills/workflow-codification/src/pattern-analyzer.ts +537 -0
- package/claude-assets/skills/workflow-codification/src/types.ts +180 -0
- package/claude-assets/skills/workflow-codification/tests/pattern-analyzer.test.ts +960 -0
- package/claude-assets/skills/workflow-codification/tsconfig.json +34 -0
- package/claude-assets/skills/workflow-codification/workflow-codification.db +0 -0
- package/dist/agent-spawner/agent-spawner.js +448 -0
- package/dist/agent-spawner/agent-spawner.js.map +1 -0
- package/dist/agent-spawner/index.js +10 -0
- package/dist/agent-spawner/index.js.map +1 -0
- package/dist/agent-spawner/types.js +14 -0
- package/dist/agent-spawner/types.js.map +1 -0
- package/dist/agents/agent-loader.js +146 -165
- package/dist/agents/agent-loader.js.map +1 -1
- package/dist/cli/agent-executor.js +47 -1
- package/dist/cli/agent-executor.js.map +1 -1
- package/dist/cli/agent-spawn.js +4 -1
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/tool-executor.js +3 -1
- package/dist/cli/tool-executor.js.map +1 -1
- package/dist/gate-checker/gate-checker.js +292 -0
- package/dist/gate-checker/gate-checker.js.map +1 -0
- package/dist/gate-checker/types.js +94 -0
- package/dist/gate-checker/types.js.map +1 -0
- package/dist/lib/database-service/connection-pool-manager.js +2 -1
- package/dist/lib/database-service/connection-pool-manager.js.map +1 -1
- package/dist/orchestrator/index.js +10 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/orchestrate.js +496 -0
- package/dist/orchestrator/orchestrate.js.map +1 -0
- package/dist/orchestrator/types.js +58 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/package.json +1 -1
- package/scripts/switch-api.sh +142 -4
- package/scripts/verify-no-secrets.sh +6 -13
- package/tests/README.md +175 -58
|
@@ -0,0 +1,801 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis Coordinator Implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides type-safe Redis-based coordination for CFN Loop tasks and agents.
|
|
5
|
+
* Handles task initialization, agent registration, status tracking, consensus
|
|
6
|
+
* collection, and loop synchronization with proper error handling and timeouts.
|
|
7
|
+
*
|
|
8
|
+
* @module cfn-docker-redis-coordination/coordinator
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import Redis from 'ioredis';
|
|
12
|
+
import {
|
|
13
|
+
RedisConfig,
|
|
14
|
+
CoordinatorConfig,
|
|
15
|
+
IRedisClient,
|
|
16
|
+
ILogger,
|
|
17
|
+
AgentStatus,
|
|
18
|
+
TaskContext,
|
|
19
|
+
WaitLoopParams,
|
|
20
|
+
WaitLoopResult,
|
|
21
|
+
CollectConsensusParams,
|
|
22
|
+
CollectConsensusResult,
|
|
23
|
+
ExecutionMode,
|
|
24
|
+
ValidationError,
|
|
25
|
+
SecurityError,
|
|
26
|
+
TimeoutError,
|
|
27
|
+
RedisConnectionError,
|
|
28
|
+
isValidTaskId,
|
|
29
|
+
isValidAgentId,
|
|
30
|
+
isValidConfidence,
|
|
31
|
+
} from './types';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Redis Coordinator for CFN Loop task coordination
|
|
35
|
+
*
|
|
36
|
+
* Manages task initialization, agent registration, status tracking,
|
|
37
|
+
* and consensus collection using Redis as the coordination backend.
|
|
38
|
+
*/
|
|
39
|
+
export class RedisCoordinator {
|
|
40
|
+
private redisClient: IRedisClient;
|
|
41
|
+
private readonly config: CoordinatorConfig;
|
|
42
|
+
private readonly logger: ILogger;
|
|
43
|
+
private readonly mode: ExecutionMode;
|
|
44
|
+
private readonly defaultTimeout: number;
|
|
45
|
+
private readonly defaultTTL: number;
|
|
46
|
+
|
|
47
|
+
// Security constraints (CWE prevention)
|
|
48
|
+
private readonly securityLimits = {
|
|
49
|
+
maxTaskIdLength: 256,
|
|
50
|
+
maxAgentIdLength: 256,
|
|
51
|
+
maxContextSize: 1024 * 1024, // 1MB
|
|
52
|
+
maxConfidenceLength: 10,
|
|
53
|
+
timeoutMin: 1,
|
|
54
|
+
timeoutMax: 3600,
|
|
55
|
+
maxIterations: 100,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
// Redis key prefixes
|
|
60
|
+
private readonly keyPrefixes = {
|
|
61
|
+
task: 'cfn_docker:task',
|
|
62
|
+
agent: 'cfn_docker:agent',
|
|
63
|
+
confidence: 'cfn_docker:task',
|
|
64
|
+
consensus: 'cfn_docker:task',
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
constructor(
|
|
68
|
+
config: CoordinatorConfig,
|
|
69
|
+
logger: ILogger,
|
|
70
|
+
redisClient?: IRedisClient
|
|
71
|
+
) {
|
|
72
|
+
this.config = config;
|
|
73
|
+
this.logger = logger;
|
|
74
|
+
this.mode = config.mode || 'standard';
|
|
75
|
+
this.defaultTimeout = config.defaultTimeout || 30;
|
|
76
|
+
this.defaultTTL = config.defaultTTL || 3600;
|
|
77
|
+
|
|
78
|
+
// Validate configuration
|
|
79
|
+
if (!isValidTaskId(config.taskId)) {
|
|
80
|
+
throw new ValidationError('Invalid task ID format', {
|
|
81
|
+
taskId: config.taskId,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Initialize Redis client
|
|
86
|
+
if (redisClient) {
|
|
87
|
+
this.redisClient = redisClient;
|
|
88
|
+
} else {
|
|
89
|
+
this.redisClient = this.createRedisClient(config.redis);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Create and configure Redis client
|
|
95
|
+
*/
|
|
96
|
+
private createRedisClient(config: RedisConfig): IRedisClient {
|
|
97
|
+
const options: Record<string, unknown> = {
|
|
98
|
+
host: config.host,
|
|
99
|
+
port: config.port,
|
|
100
|
+
db: config.db,
|
|
101
|
+
connectTimeout: config.timeout || 5000,
|
|
102
|
+
maxRetriesPerRequest: 3,
|
|
103
|
+
enableReadyCheck: true,
|
|
104
|
+
enableOfflineQueue: true,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
if (config.password) {
|
|
108
|
+
options.password = config.password;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (config.retryStrategy) {
|
|
112
|
+
options.retryStrategy = config.retryStrategy;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const client = new Redis(options);
|
|
117
|
+
return this.wrapRedisClient(client);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
throw new RedisConnectionError(
|
|
120
|
+
`Failed to create Redis client: ${error instanceof Error ? error.message : String(error)}`,
|
|
121
|
+
{ config }
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Wrap ioredis Redis client to match IRedisClient interface
|
|
128
|
+
*/
|
|
129
|
+
private wrapRedisClient(client: Redis): IRedisClient {
|
|
130
|
+
return {
|
|
131
|
+
exists: async (key: string): Promise<boolean> => {
|
|
132
|
+
const result = await (client.exists(key) as unknown as Promise<number>);
|
|
133
|
+
return result > 0;
|
|
134
|
+
},
|
|
135
|
+
del: (key: string) => client.del(key) as unknown as Promise<number>,
|
|
136
|
+
keys: (pattern: string) => client.keys(pattern) as unknown as Promise<string[]>,
|
|
137
|
+
dbsize: () => client.dbsize() as unknown as Promise<number>,
|
|
138
|
+
flushdb: () => client.flushdb() as unknown as Promise<string>,
|
|
139
|
+
get: (key: string) => client.get(key) as unknown as Promise<string | null>,
|
|
140
|
+
set: (key: string, value: string) => client.set(key, value) as unknown as Promise<string>,
|
|
141
|
+
setex: (key: string, seconds: number, value: string) =>
|
|
142
|
+
client.setex(key, seconds, value) as unknown as Promise<string>,
|
|
143
|
+
hget: (key: string, field: string) =>
|
|
144
|
+
client.hget(key, field) as unknown as Promise<string | null>,
|
|
145
|
+
hset: async (key: string, fields: Record<string, string | number | boolean>) => {
|
|
146
|
+
const flatArgs: (string | number)[] = [];
|
|
147
|
+
for (const [field, value] of Object.entries(fields)) {
|
|
148
|
+
flatArgs.push(field, String(value));
|
|
149
|
+
}
|
|
150
|
+
const result = await (client.hset(key, ...flatArgs) as unknown as Promise<number>);
|
|
151
|
+
return result;
|
|
152
|
+
},
|
|
153
|
+
hmset: async (
|
|
154
|
+
key: string,
|
|
155
|
+
fields: Record<string, string | number | boolean>
|
|
156
|
+
) => {
|
|
157
|
+
const flatArgs: (string | number)[] = [];
|
|
158
|
+
for (const [field, value] of Object.entries(fields)) {
|
|
159
|
+
flatArgs.push(field, String(value));
|
|
160
|
+
}
|
|
161
|
+
const result = await (client.hmset(key, ...flatArgs) as unknown as Promise<string>);
|
|
162
|
+
return result;
|
|
163
|
+
},
|
|
164
|
+
hgetall: (key: string) =>
|
|
165
|
+
client.hgetall(key) as unknown as Promise<Record<string, string>>,
|
|
166
|
+
hkeys: (key: string) => client.hkeys(key) as unknown as Promise<string[]>,
|
|
167
|
+
hvals: (key: string) => client.hvals(key) as unknown as Promise<string[]>,
|
|
168
|
+
lpush: async (key: string, values: string[]) => {
|
|
169
|
+
const result = await (client.lpush(key, ...values) as unknown as Promise<number>);
|
|
170
|
+
return result;
|
|
171
|
+
},
|
|
172
|
+
rpush: async (key: string, values: string[]) => {
|
|
173
|
+
const result = await (client.rpush(key, ...values) as unknown as Promise<number>);
|
|
174
|
+
return result;
|
|
175
|
+
},
|
|
176
|
+
blpop: (keys: string[], timeout: number) =>
|
|
177
|
+
client.blpop(...keys, timeout) as unknown as Promise<[string, string] | null>,
|
|
178
|
+
lrange: (key: string, start: number, stop: number) =>
|
|
179
|
+
client.lrange(key, start, stop) as unknown as Promise<string[]>,
|
|
180
|
+
sadd: async (key: string, members: string[]) => {
|
|
181
|
+
const result = await (client.sadd(key, ...members) as unknown as Promise<number>);
|
|
182
|
+
return result;
|
|
183
|
+
},
|
|
184
|
+
smembers: (key: string) => client.smembers(key) as unknown as Promise<string[]>,
|
|
185
|
+
scard: (key: string) => client.scard(key) as unknown as Promise<number>,
|
|
186
|
+
expire: (key: string, seconds: number) =>
|
|
187
|
+
client.expire(key, seconds) as unknown as Promise<number>,
|
|
188
|
+
pexpire: (key: string, milliseconds: number) =>
|
|
189
|
+
client.pexpire(key, milliseconds) as unknown as Promise<number>,
|
|
190
|
+
ttl: (key: string) => client.ttl(key) as unknown as Promise<number>,
|
|
191
|
+
ping: () => client.ping() as unknown as Promise<string>,
|
|
192
|
+
info: (section?: string) => {
|
|
193
|
+
if (section) {
|
|
194
|
+
return (client.info(section) as unknown) as Promise<string>;
|
|
195
|
+
}
|
|
196
|
+
return (client.info() as unknown) as Promise<string>;
|
|
197
|
+
},
|
|
198
|
+
quit: async () => {
|
|
199
|
+
await (client.quit() as unknown as Promise<void>);
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Initialize task coordination
|
|
206
|
+
*/
|
|
207
|
+
async initTask(contextFile?: TaskContext): Promise<void> {
|
|
208
|
+
try {
|
|
209
|
+
const taskId = this.config.taskId;
|
|
210
|
+
const now = new Date().toISOString();
|
|
211
|
+
|
|
212
|
+
// Store task metadata
|
|
213
|
+
await this.redisClient.hset(
|
|
214
|
+
`${this.keyPrefixes.task}:${taskId}:meta`,
|
|
215
|
+
{
|
|
216
|
+
created_at: now,
|
|
217
|
+
ttl: String(this.defaultTTL),
|
|
218
|
+
created_by: 'cfn-docker-redis-coordination',
|
|
219
|
+
mode: this.mode,
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
// Set TTL on metadata
|
|
224
|
+
await this.redisClient.expire(
|
|
225
|
+
`${this.keyPrefixes.task}:${taskId}:meta`,
|
|
226
|
+
this.defaultTTL
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Store context if provided
|
|
230
|
+
if (contextFile && Object.keys(contextFile).length > 0) {
|
|
231
|
+
const contextKey = `${this.keyPrefixes.task}:${taskId}:context`;
|
|
232
|
+
const contextData: Record<string, string> = {};
|
|
233
|
+
|
|
234
|
+
for (const [key, value] of Object.entries(contextFile)) {
|
|
235
|
+
// Security: validate context size
|
|
236
|
+
const stringValue = String(value);
|
|
237
|
+
if (stringValue.length > this.securityLimits.maxContextSize) {
|
|
238
|
+
throw new SecurityError(`Context value too large for key: ${key}`);
|
|
239
|
+
}
|
|
240
|
+
contextData[key] = stringValue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
await this.redisClient.hset(contextKey, contextData);
|
|
244
|
+
await this.redisClient.expire(contextKey, this.defaultTTL);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
this.logger.log(`Task coordination initialized: ${taskId}`);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
250
|
+
this.logger.error(`Failed to initialize task: ${message}`);
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Store or update task context
|
|
257
|
+
*/
|
|
258
|
+
async storeContext(context: TaskContext): Promise<void> {
|
|
259
|
+
try {
|
|
260
|
+
const taskId = this.config.taskId;
|
|
261
|
+
const contextKey = `${this.keyPrefixes.task}:${taskId}:context`;
|
|
262
|
+
|
|
263
|
+
const contextData: Record<string, string> = {};
|
|
264
|
+
for (const [key, value] of Object.entries(context)) {
|
|
265
|
+
const stringValue = String(value);
|
|
266
|
+
if (stringValue.length > this.securityLimits.maxContextSize) {
|
|
267
|
+
throw new SecurityError(`Context value too large for key: ${key}`);
|
|
268
|
+
}
|
|
269
|
+
contextData[key] = stringValue;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
await this.redisClient.hset(contextKey, contextData);
|
|
273
|
+
await this.redisClient.expire(contextKey, this.defaultTTL);
|
|
274
|
+
|
|
275
|
+
this.logger.log(`Context stored for task: ${taskId}`);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
278
|
+
this.logger.error(`Failed to store context: ${message}`);
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get task context
|
|
285
|
+
*/
|
|
286
|
+
async getContext(): Promise<TaskContext> {
|
|
287
|
+
try {
|
|
288
|
+
const taskId = this.config.taskId;
|
|
289
|
+
const contextKey = `${this.keyPrefixes.task}:${taskId}:context`;
|
|
290
|
+
|
|
291
|
+
const exists = await this.redisClient.exists(contextKey);
|
|
292
|
+
if (!exists) {
|
|
293
|
+
throw new ValidationError(`No context found for task: ${taskId}`);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const context = await this.redisClient.hgetall(contextKey);
|
|
297
|
+
this.logger.log(`Context retrieved for task: ${taskId}`);
|
|
298
|
+
return context;
|
|
299
|
+
} catch (error) {
|
|
300
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
301
|
+
this.logger.error(`Failed to get context: ${message}`);
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Register new agent
|
|
308
|
+
*/
|
|
309
|
+
async registerAgent(
|
|
310
|
+
agentId: string,
|
|
311
|
+
agentType: string,
|
|
312
|
+
containerId?: string
|
|
313
|
+
): Promise<void> {
|
|
314
|
+
try {
|
|
315
|
+
// Validate inputs
|
|
316
|
+
if (!isValidAgentId(agentId)) {
|
|
317
|
+
throw new ValidationError('Invalid agent ID format', { agentId });
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const now = new Date().toISOString();
|
|
321
|
+
const agentKey = `${this.keyPrefixes.agent}:${agentId}`;
|
|
322
|
+
|
|
323
|
+
// Store agent information
|
|
324
|
+
await this.redisClient.hset(agentKey, {
|
|
325
|
+
agent_id: agentId,
|
|
326
|
+
agent_type: agentType,
|
|
327
|
+
container_id: containerId || '',
|
|
328
|
+
task_id: this.config.taskId,
|
|
329
|
+
status: 'spawning',
|
|
330
|
+
iteration: '1',
|
|
331
|
+
created_at: now,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Add to status history
|
|
335
|
+
await this.redisClient.lpush(
|
|
336
|
+
`${this.keyPrefixes.agent}:${agentId}:status_history`,
|
|
337
|
+
[JSON.stringify({ status: 'spawning', timestamp: now })]
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
// Set TTL
|
|
341
|
+
await this.redisClient.expire(agentKey, this.defaultTTL);
|
|
342
|
+
await this.redisClient.expire(
|
|
343
|
+
`${this.keyPrefixes.agent}:${agentId}:status_history`,
|
|
344
|
+
this.defaultTTL
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
this.logger.log(`Agent registered: ${agentId} (type: ${agentType})`);
|
|
348
|
+
} catch (error) {
|
|
349
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
350
|
+
this.logger.error(`Failed to register agent: ${message}`);
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Update agent status
|
|
357
|
+
*/
|
|
358
|
+
async updateStatus(
|
|
359
|
+
agentId: string,
|
|
360
|
+
status: AgentStatus,
|
|
361
|
+
iteration: number = 1
|
|
362
|
+
): Promise<void> {
|
|
363
|
+
try {
|
|
364
|
+
// Validate inputs
|
|
365
|
+
if (!isValidAgentId(agentId)) {
|
|
366
|
+
throw new ValidationError('Invalid agent ID format', { agentId });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (!['spawning', 'running', 'working', 'completed', 'failed', 'timeout'].includes(status)) {
|
|
370
|
+
throw new ValidationError(`Invalid agent status: ${status}`);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const now = new Date().toISOString();
|
|
374
|
+
const agentKey = `${this.keyPrefixes.agent}:${agentId}`;
|
|
375
|
+
|
|
376
|
+
// Update agent status
|
|
377
|
+
await this.redisClient.hset(agentKey, {
|
|
378
|
+
status,
|
|
379
|
+
iteration: String(iteration),
|
|
380
|
+
updated_at: now,
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// Add to status history
|
|
384
|
+
await this.redisClient.lpush(
|
|
385
|
+
`${this.keyPrefixes.agent}:${agentId}:status_history`,
|
|
386
|
+
[JSON.stringify({ status, timestamp: now })]
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
this.logger.log(`Status updated for agent ${agentId}: ${status}`);
|
|
390
|
+
} catch (error) {
|
|
391
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
392
|
+
this.logger.error(`Failed to update status: ${message}`);
|
|
393
|
+
throw error;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Signal agent completion with confidence score
|
|
399
|
+
*/
|
|
400
|
+
async signalComplete(
|
|
401
|
+
agentId: string,
|
|
402
|
+
confidence: number,
|
|
403
|
+
iteration: number = 1
|
|
404
|
+
): Promise<void> {
|
|
405
|
+
try {
|
|
406
|
+
// Validate inputs
|
|
407
|
+
if (!isValidAgentId(agentId)) {
|
|
408
|
+
throw new ValidationError('Invalid agent ID format', { agentId });
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (!isValidConfidence(confidence)) {
|
|
412
|
+
throw new ValidationError('Confidence must be between 0.0 and 1.0', {
|
|
413
|
+
confidence,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const taskId = this.config.taskId;
|
|
418
|
+
const now = new Date().toISOString();
|
|
419
|
+
const agentKey = `${this.keyPrefixes.agent}:${agentId}`;
|
|
420
|
+
|
|
421
|
+
// Signal completion via list
|
|
422
|
+
const statusKey = `${this.keyPrefixes.task}:${taskId}:agent:${agentId}:done`;
|
|
423
|
+
await this.redisClient.lpush(statusKey, ['complete']);
|
|
424
|
+
await this.redisClient.expire(statusKey, this.defaultTTL);
|
|
425
|
+
|
|
426
|
+
// Get agent type
|
|
427
|
+
const agentType =
|
|
428
|
+
(await this.redisClient.hget(agentKey, 'agent_type')) || 'unknown';
|
|
429
|
+
|
|
430
|
+
// Store confidence result
|
|
431
|
+
const confidenceKey = `${this.keyPrefixes.confidence}:${taskId}:confidence:${agentId}`;
|
|
432
|
+
await this.redisClient.hset(confidenceKey, {
|
|
433
|
+
confidence: String(confidence),
|
|
434
|
+
iteration: String(iteration),
|
|
435
|
+
reported_at: now,
|
|
436
|
+
agent_type: agentType,
|
|
437
|
+
});
|
|
438
|
+
await this.redisClient.expire(confidenceKey, this.defaultTTL);
|
|
439
|
+
|
|
440
|
+
// Update agent status
|
|
441
|
+
await this.updateStatus(agentId, 'completed', iteration);
|
|
442
|
+
|
|
443
|
+
this.logger.log(
|
|
444
|
+
`Agent ${agentId} completion signaled with confidence: ${confidence}`
|
|
445
|
+
);
|
|
446
|
+
} catch (error) {
|
|
447
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
448
|
+
this.logger.error(`Failed to signal completion: ${message}`);
|
|
449
|
+
throw error;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Wait for loop completion (all agents)
|
|
455
|
+
*/
|
|
456
|
+
async waitLoop(params: WaitLoopParams): Promise<WaitLoopResult> {
|
|
457
|
+
const startTime = Date.now();
|
|
458
|
+
// Hoist progress tracking outside try block so it's available in catch
|
|
459
|
+
let completedAgents = 0;
|
|
460
|
+
|
|
461
|
+
try {
|
|
462
|
+
const {
|
|
463
|
+
taskId,
|
|
464
|
+
loopNumber,
|
|
465
|
+
agentCount,
|
|
466
|
+
timeout = this.defaultTimeout,
|
|
467
|
+
verbose = false,
|
|
468
|
+
} = params;
|
|
469
|
+
|
|
470
|
+
// Validate inputs
|
|
471
|
+
if (!isValidTaskId(taskId)) {
|
|
472
|
+
throw new ValidationError('Invalid task ID format', { taskId });
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (loopNumber < 1 || loopNumber > 4) {
|
|
476
|
+
throw new ValidationError('Loop number must be between 1 and 4', {
|
|
477
|
+
loopNumber,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (agentCount < 1) {
|
|
482
|
+
throw new ValidationError('Agent count must be >= 1', { agentCount });
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (timeout < this.securityLimits.timeoutMin ||
|
|
486
|
+
timeout > this.securityLimits.timeoutMax) {
|
|
487
|
+
throw new ValidationError(
|
|
488
|
+
`Timeout must be between ${this.securityLimits.timeoutMin} and ${this.securityLimits.timeoutMax}`,
|
|
489
|
+
{ timeout }
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
this.logger.log(
|
|
494
|
+
`Waiting for Loop ${loopNumber} completion (${agentCount} agents, timeout: ${timeout}s)`
|
|
495
|
+
);
|
|
496
|
+
|
|
497
|
+
const endTime = startTime + timeout * 1000;
|
|
498
|
+
|
|
499
|
+
while (Date.now() < endTime) {
|
|
500
|
+
completedAgents = 0;
|
|
501
|
+
|
|
502
|
+
// Get all completion status keys for this task
|
|
503
|
+
const completionKeys = await this.redisClient.keys(
|
|
504
|
+
`${this.keyPrefixes.task}:${taskId}:agent:*:done`
|
|
505
|
+
);
|
|
506
|
+
|
|
507
|
+
// Count unique agents that have completed
|
|
508
|
+
const uniqueAgents = new Set<string>();
|
|
509
|
+
for (const key of completionKeys) {
|
|
510
|
+
// Extract agent ID from key like: cfn_docker:task:test-task-001:agent:agent-001:done
|
|
511
|
+
const parts = key.split(':');
|
|
512
|
+
if (parts.length >= 5) {
|
|
513
|
+
const agentId = parts[4]; // agent-001
|
|
514
|
+
uniqueAgents.add(agentId);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
completedAgents = uniqueAgents.size;
|
|
519
|
+
|
|
520
|
+
if (completedAgents >= agentCount) {
|
|
521
|
+
const executionTime = Date.now() - startTime;
|
|
522
|
+
const message = `Loop ${loopNumber} completed (${completedAgents}/${agentCount} agents)`;
|
|
523
|
+
this.logger.log(message);
|
|
524
|
+
return {
|
|
525
|
+
success: true,
|
|
526
|
+
completedAgents,
|
|
527
|
+
expectedAgents: agentCount,
|
|
528
|
+
executionTime,
|
|
529
|
+
message,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (verbose) {
|
|
534
|
+
this.logger.log(
|
|
535
|
+
`Progress: ${completedAgents}/${agentCount} agents completed`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Sleep 5 seconds before next check
|
|
540
|
+
await this.sleep(5000);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
throw new TimeoutError(
|
|
544
|
+
`Loop ${loopNumber} timeout: only ${completedAgents}/${agentCount} agents completed`,
|
|
545
|
+
{ completedAgents, expectedAgents: agentCount, timeout }
|
|
546
|
+
);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
const executionTime = Date.now() - startTime;
|
|
549
|
+
const message =
|
|
550
|
+
error instanceof Error ? error.message : String(error);
|
|
551
|
+
this.logger.error(`Wait loop failed: ${message}`);
|
|
552
|
+
|
|
553
|
+
if (error instanceof TimeoutError) {
|
|
554
|
+
return {
|
|
555
|
+
success: false,
|
|
556
|
+
completedAgents, // Return last-known value instead of 0
|
|
557
|
+
expectedAgents: params.agentCount,
|
|
558
|
+
executionTime,
|
|
559
|
+
message: error.message,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
throw error;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Collect consensus from validators
|
|
569
|
+
*/
|
|
570
|
+
async collectConsensus(
|
|
571
|
+
params: CollectConsensusParams
|
|
572
|
+
): Promise<CollectConsensusResult> {
|
|
573
|
+
const startTime = Date.now();
|
|
574
|
+
// Hoist progress tracking outside try block so it's available in catch
|
|
575
|
+
let responsesReceived = 0;
|
|
576
|
+
let totalConfidence = 0;
|
|
577
|
+
let totalValidators = 0;
|
|
578
|
+
|
|
579
|
+
try {
|
|
580
|
+
const {
|
|
581
|
+
taskId,
|
|
582
|
+
loopNumber,
|
|
583
|
+
requiredConsensus,
|
|
584
|
+
timeout = this.defaultTimeout,
|
|
585
|
+
verbose = false,
|
|
586
|
+
} = params;
|
|
587
|
+
|
|
588
|
+
// Validate inputs
|
|
589
|
+
if (!isValidTaskId(taskId)) {
|
|
590
|
+
throw new ValidationError('Invalid task ID format', { taskId });
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (loopNumber < 1 || loopNumber > 4) {
|
|
594
|
+
throw new ValidationError('Loop number must be between 1 and 4', {
|
|
595
|
+
loopNumber,
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (!isValidConfidence(requiredConsensus)) {
|
|
600
|
+
throw new ValidationError(
|
|
601
|
+
'Required consensus must be between 0.0 and 1.0',
|
|
602
|
+
{ requiredConsensus }
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (timeout < this.securityLimits.timeoutMin ||
|
|
607
|
+
timeout > this.securityLimits.timeoutMax) {
|
|
608
|
+
throw new ValidationError(
|
|
609
|
+
`Timeout must be between ${this.securityLimits.timeoutMin} and ${this.securityLimits.timeoutMax}`,
|
|
610
|
+
{ timeout }
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
this.logger.log(
|
|
615
|
+
`Collecting Loop ${loopNumber} consensus (threshold: ${requiredConsensus})`
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
const endTime = startTime + timeout * 1000;
|
|
619
|
+
|
|
620
|
+
while (Date.now() < endTime) {
|
|
621
|
+
responsesReceived = 0;
|
|
622
|
+
totalConfidence = 0;
|
|
623
|
+
|
|
624
|
+
// Get all confidence keys for this task
|
|
625
|
+
const confidenceKeys = await this.redisClient.keys(
|
|
626
|
+
`${this.keyPrefixes.confidence}:${taskId}:confidence:*`
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
// Collect validator responses
|
|
630
|
+
for (const confidenceKey of confidenceKeys) {
|
|
631
|
+
const confidence = await this.redisClient.hget(
|
|
632
|
+
confidenceKey,
|
|
633
|
+
'confidence'
|
|
634
|
+
);
|
|
635
|
+
|
|
636
|
+
if (confidence !== null && confidence !== undefined) {
|
|
637
|
+
const confidenceValue = parseFloat(confidence);
|
|
638
|
+
if (!isNaN(confidenceValue) && isValidConfidence(confidenceValue)) {
|
|
639
|
+
totalConfidence += confidenceValue;
|
|
640
|
+
responsesReceived++;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (responsesReceived > 0) {
|
|
646
|
+
totalValidators = responsesReceived; // Update totalValidators
|
|
647
|
+
const averageConfidence =
|
|
648
|
+
totalConfidence / responsesReceived;
|
|
649
|
+
|
|
650
|
+
if (verbose) {
|
|
651
|
+
this.logger.log(
|
|
652
|
+
`Responses: ${responsesReceived}, Average confidence: ${averageConfidence.toFixed(3)}`
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (averageConfidence >= requiredConsensus) {
|
|
657
|
+
// Determine decision based on confidence
|
|
658
|
+
const decision =
|
|
659
|
+
averageConfidence >= 0.95
|
|
660
|
+
? 'COMPLETE'
|
|
661
|
+
: 'PROCEED';
|
|
662
|
+
|
|
663
|
+
// Store consensus result
|
|
664
|
+
const consensusKey = `${this.keyPrefixes.consensus}:${taskId}:loop:${loopNumber}:consensus`;
|
|
665
|
+
await this.redisClient.hset(consensusKey, {
|
|
666
|
+
total_validators: String(totalValidators),
|
|
667
|
+
responses_received: String(responsesReceived),
|
|
668
|
+
average_confidence: averageConfidence.toFixed(3),
|
|
669
|
+
consensus_reached: 'true',
|
|
670
|
+
decision,
|
|
671
|
+
collected_at: new Date().toISOString(),
|
|
672
|
+
});
|
|
673
|
+
await this.redisClient.expire(consensusKey, this.defaultTTL);
|
|
674
|
+
|
|
675
|
+
const executionTime = Date.now() - startTime;
|
|
676
|
+
const message = `Consensus reached: ${averageConfidence.toFixed(3)} >= ${requiredConsensus}`;
|
|
677
|
+
this.logger.log(message);
|
|
678
|
+
|
|
679
|
+
return {
|
|
680
|
+
success: true,
|
|
681
|
+
totalValidators,
|
|
682
|
+
responsesReceived,
|
|
683
|
+
averageConfidence,
|
|
684
|
+
consensusReached: true,
|
|
685
|
+
decision,
|
|
686
|
+
executionTime,
|
|
687
|
+
message,
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// Sleep 5 seconds before next check
|
|
693
|
+
await this.sleep(5000);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
throw new TimeoutError(
|
|
697
|
+
`Consensus collection timeout: ${responsesReceived} responses, average: ${
|
|
698
|
+
responsesReceived > 0 ? (totalConfidence / responsesReceived).toFixed(3) : 'N/A'
|
|
699
|
+
}`,
|
|
700
|
+
{
|
|
701
|
+
responsesReceived,
|
|
702
|
+
timeout,
|
|
703
|
+
averageConfidence: responsesReceived > 0 ? totalConfidence / responsesReceived : 0,
|
|
704
|
+
}
|
|
705
|
+
);
|
|
706
|
+
} catch (error) {
|
|
707
|
+
const executionTime = Date.now() - startTime;
|
|
708
|
+
const message =
|
|
709
|
+
error instanceof Error ? error.message : String(error);
|
|
710
|
+
this.logger.error(`Consensus collection failed: ${message}`);
|
|
711
|
+
|
|
712
|
+
if (error instanceof TimeoutError) {
|
|
713
|
+
const averageConfidence = responsesReceived > 0 ? totalConfidence / responsesReceived : 0;
|
|
714
|
+
return {
|
|
715
|
+
success: false,
|
|
716
|
+
totalValidators, // Return last-known value instead of 0
|
|
717
|
+
responsesReceived, // Return last-known value instead of 0
|
|
718
|
+
averageConfidence, // Return last-known value instead of 0
|
|
719
|
+
consensusReached: false,
|
|
720
|
+
decision: 'ABORT',
|
|
721
|
+
executionTime,
|
|
722
|
+
message: error.message,
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
throw error;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Health check Redis connection
|
|
732
|
+
*/
|
|
733
|
+
async healthCheck(): Promise<void> {
|
|
734
|
+
try {
|
|
735
|
+
// Test ping
|
|
736
|
+
const pong = await this.redisClient.ping();
|
|
737
|
+
if (pong !== 'PONG') {
|
|
738
|
+
throw new Error('Redis ping failed');
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Get memory info
|
|
742
|
+
const info = await this.redisClient.info('memory');
|
|
743
|
+
if (info) {
|
|
744
|
+
this.logger.log(`Redis health check passed`);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Get key count
|
|
748
|
+
const dbSize = await this.redisClient.dbsize();
|
|
749
|
+
this.logger.log(`Total Redis keys: ${dbSize}`);
|
|
750
|
+
} catch (error) {
|
|
751
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
752
|
+
this.logger.error(`Redis health check failed: ${message}`);
|
|
753
|
+
throw error;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Cleanup expired data
|
|
759
|
+
*/
|
|
760
|
+
async cleanup(): Promise<void> {
|
|
761
|
+
try {
|
|
762
|
+
const taskId = this.config.taskId;
|
|
763
|
+
|
|
764
|
+
// Delete task-related keys
|
|
765
|
+
const taskKeys = await this.redisClient.keys(`${this.keyPrefixes.task}:${taskId}:*`);
|
|
766
|
+
for (const key of taskKeys) {
|
|
767
|
+
await this.redisClient.del(key);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
this.logger.log(`Cleanup completed for task: ${taskId}`);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
773
|
+
this.logger.error(`Cleanup failed: ${message}`);
|
|
774
|
+
throw error;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Close Redis connection
|
|
780
|
+
*/
|
|
781
|
+
async disconnect(): Promise<void> {
|
|
782
|
+
try {
|
|
783
|
+
await this.redisClient.quit();
|
|
784
|
+
this.logger.log('Disconnected from Redis');
|
|
785
|
+
} catch (error) {
|
|
786
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
787
|
+
this.logger.error(`Failed to disconnect: ${message}`);
|
|
788
|
+
throw error;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Sleep utility function
|
|
794
|
+
*/
|
|
795
|
+
private sleep(ms: number): Promise<void> {
|
|
796
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Export for use in other modules
|
|
801
|
+
export default RedisCoordinator;
|