claude-flow-novice 2.15.5 → 2.15.7
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/helpers/gate-check.sh +39 -577
- package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +49 -270
- 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/helpers/consensus.ts +87 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/gate-check.ts +115 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/parse-test-results.ts +372 -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/consensus.test.ts +142 -0
- package/.claude/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +199 -0
- package/.claude/skills/cfn-loop-orchestration/tests/gate-check.test.ts +325 -0
- package/.claude/skills/cfn-loop-orchestration/tests/iteration-manager.test.ts +132 -0
- package/.claude/skills/cfn-loop-orchestration/tests/parse-test-results.test.ts +382 -0
- package/.claude/skills/cfn-loop-orchestration/tests/setup.ts +22 -0
- package/.claude/skills/cfn-loop-orchestration/tests/timeout-calculator.test.ts +118 -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/coverage/clover.xml +1447 -0
- package/.claude/skills/cfn-redis-coordination/coverage/coverage-final.json +13 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/agent-logger.ts.html +1423 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/agent-recovery.ts.html +1447 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/base.css +224 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/block-navigation.js +87 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/completion-reporter.ts.html +1273 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/context-manager.ts.html +1066 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/favicon.png +0 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/index.html +281 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/mode-detector.ts.html +550 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/prettify.css +1 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/prettify.js +2 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/redis-client.ts.html +2047 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/result-collector.ts.html +1396 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/sorter.js +210 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/swarm-manager.ts.html +1567 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/task-analyzer.ts.html +1297 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/task-executor.ts.html +1354 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/types.ts.html +790 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/waiting-coordinator.ts.html +1846 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov.info +2650 -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 +788 -0
- package/.claude/skills/cfn-redis-coordination/tsconfig.json +31 -0
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +13 -72
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +172 -62
- package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +465 -508
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +733 -743
- package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +13 -79
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +15 -14
- package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +23 -30
- package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +13 -18
- package/claude-assets/agents/cfn-dev-team/reviewers/code-reviewer.md +312 -317
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +23 -20
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +16 -21
- package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +718 -737
- package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +817 -828
- package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +8 -9
- package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +668 -684
- package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/tester.md +248 -253
- package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +13 -18
- package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +13 -18
- 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/helpers/gate-check.sh +39 -577
- package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +49 -270
- 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/helpers/gate-check.ts +115 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/parse-test-results.ts +372 -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/consensus.test.ts +142 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +199 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/gate-check.test.ts +325 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/iteration-manager.test.ts +132 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/parse-test-results.test.ts +382 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/setup.ts +22 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/timeout-calculator.test.ts +118 -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/coverage/clover.xml +1447 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/coverage-final.json +13 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/agent-logger.ts.html +1423 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/agent-recovery.ts.html +1447 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/base.css +224 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/block-navigation.js +87 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/completion-reporter.ts.html +1273 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/context-manager.ts.html +1066 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/favicon.png +0 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/index.html +281 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/mode-detector.ts.html +550 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/prettify.css +1 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/prettify.js +2 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/redis-client.ts.html +2047 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/result-collector.ts.html +1396 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/sorter.js +210 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/swarm-manager.ts.html +1567 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/task-analyzer.ts.html +1297 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/task-executor.ts.html +1354 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/types.ts.html +790 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/waiting-coordinator.ts.html +1846 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov.info +2650 -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 +788 -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/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/config-manager.js +91 -109
- package/dist/cli/config-manager.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/clean-agent-profiles.sh +112 -0
- package/scripts/switch-api.sh +142 -4
- package/scripts/verify-no-secrets.sh +6 -13
- package/tests/README.md +175 -58
|
@@ -0,0 +1,1042 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Logger Implementation
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive error logging system for CFN Loop with support for:
|
|
5
|
+
* - Error capture with automatic context enrichment
|
|
6
|
+
* - Error categorization and severity levels
|
|
7
|
+
* - Multiple logging backends (file, Redis, console)
|
|
8
|
+
* - Report generation (Markdown, JSON)
|
|
9
|
+
* - Log listing with filtering
|
|
10
|
+
* - Cleanup with retention policies
|
|
11
|
+
* - System diagnostics collection
|
|
12
|
+
* - Circuit breaker pattern for external services
|
|
13
|
+
* - Batching and buffering strategies
|
|
14
|
+
* - Retry logic with exponential backoff
|
|
15
|
+
* - Correlation ID tracking
|
|
16
|
+
*
|
|
17
|
+
* @module cfn-error-logging/error-logger
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import fs from 'fs';
|
|
21
|
+
import path from 'path';
|
|
22
|
+
import { execSync } from 'child_process';
|
|
23
|
+
import os from 'os';
|
|
24
|
+
import zlib from 'zlib';
|
|
25
|
+
import {
|
|
26
|
+
ErrorType,
|
|
27
|
+
SeverityLevel,
|
|
28
|
+
LoggingBackend,
|
|
29
|
+
LoggingBackendConfig,
|
|
30
|
+
SystemDiagnostics,
|
|
31
|
+
CFNLoopState,
|
|
32
|
+
ErrorContext,
|
|
33
|
+
ErrorLogEntry,
|
|
34
|
+
ErrorReport,
|
|
35
|
+
ErrorLogQuery,
|
|
36
|
+
CircuitBreakerState,
|
|
37
|
+
CircuitBreakerConfig,
|
|
38
|
+
CircuitBreakerStatus,
|
|
39
|
+
BatchEntry,
|
|
40
|
+
BatchConfig,
|
|
41
|
+
RetryConfig,
|
|
42
|
+
ILogger,
|
|
43
|
+
isValidErrorContext,
|
|
44
|
+
isValidTaskId,
|
|
45
|
+
ValidationError,
|
|
46
|
+
StorageError,
|
|
47
|
+
CircuitBreakerOpenError,
|
|
48
|
+
} from './types';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Error Logger class providing comprehensive error logging and diagnostics
|
|
52
|
+
*/
|
|
53
|
+
export class ErrorLogger {
|
|
54
|
+
private readonly config: LoggingBackendConfig;
|
|
55
|
+
private readonly logger: ILogger;
|
|
56
|
+
private backends: LoggingBackend[] = ['file', 'console'];
|
|
57
|
+
private batch: BatchEntry[] = [];
|
|
58
|
+
private batchConfig: BatchConfig = {
|
|
59
|
+
maxSize: 50,
|
|
60
|
+
maxWaitMs: 5000,
|
|
61
|
+
enabled: false,
|
|
62
|
+
};
|
|
63
|
+
private batchFlushTimer?: NodeJS.Timeout;
|
|
64
|
+
private retryConfig: RetryConfig = {
|
|
65
|
+
maxAttempts: 3,
|
|
66
|
+
initialDelayMs: 100,
|
|
67
|
+
maxDelayMs: 5000,
|
|
68
|
+
backoffMultiplier: 2,
|
|
69
|
+
};
|
|
70
|
+
private circuitBreaker: CircuitBreakerStatus = {
|
|
71
|
+
state: CircuitBreakerState.CLOSED,
|
|
72
|
+
failureCount: 0,
|
|
73
|
+
successCount: 0,
|
|
74
|
+
};
|
|
75
|
+
private circuitBreakerConfig: CircuitBreakerConfig = {
|
|
76
|
+
failureThreshold: 5,
|
|
77
|
+
successThreshold: 2,
|
|
78
|
+
timeout: 60000,
|
|
79
|
+
halfOpenRequests: 3,
|
|
80
|
+
};
|
|
81
|
+
private metrics = {
|
|
82
|
+
totalCaptured: 0,
|
|
83
|
+
totalReported: 0,
|
|
84
|
+
totalFailed: 0,
|
|
85
|
+
errorTypeCount: new Map<ErrorType, number>(),
|
|
86
|
+
severityCount: new Map<SeverityLevel, number>(),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
constructor(config: LoggingBackendConfig, logger: ILogger) {
|
|
90
|
+
this.config = config;
|
|
91
|
+
this.logger = logger;
|
|
92
|
+
|
|
93
|
+
// Validate configuration
|
|
94
|
+
if (config.file) {
|
|
95
|
+
this.ensureDirectories(config.file.baseDir);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.logger.info('ErrorLogger initialized', { config });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Ensure required directories exist
|
|
103
|
+
*/
|
|
104
|
+
private ensureDirectories(baseDir: string): void {
|
|
105
|
+
const dirs = [
|
|
106
|
+
baseDir,
|
|
107
|
+
path.join(baseDir, 'reports'),
|
|
108
|
+
path.join(baseDir, 'compressed'),
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
for (const dir of dirs) {
|
|
112
|
+
if (!fs.existsSync(dir)) {
|
|
113
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
114
|
+
this.logger.debug(`Created directory: ${dir}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generate unique capture ID
|
|
121
|
+
*/
|
|
122
|
+
private generateCaptureId(): string {
|
|
123
|
+
return `error-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Generate correlation ID
|
|
128
|
+
*/
|
|
129
|
+
public generateCorrelationId(): string {
|
|
130
|
+
return `corr-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Validate error context
|
|
135
|
+
*/
|
|
136
|
+
private validateContext(context: ErrorContext): void {
|
|
137
|
+
if (!isValidErrorContext(context)) {
|
|
138
|
+
throw new ValidationError('Invalid error context', { context });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Collect system diagnostics
|
|
144
|
+
*/
|
|
145
|
+
public async collectSystemDiagnostics(): Promise<SystemDiagnostics> {
|
|
146
|
+
try {
|
|
147
|
+
const diagnostics: SystemDiagnostics = {
|
|
148
|
+
timestamp: new Date().toISOString(),
|
|
149
|
+
hostname: os.hostname(),
|
|
150
|
+
user: os.userInfo().username,
|
|
151
|
+
workingDirectory: process.cwd(),
|
|
152
|
+
os: os.platform(),
|
|
153
|
+
osVersion: os.release(),
|
|
154
|
+
architecture: os.arch(),
|
|
155
|
+
hardware: {
|
|
156
|
+
cpuCores: os.cpus().length,
|
|
157
|
+
memory: this.formatBytes(os.totalmem()),
|
|
158
|
+
disk: await this.getDiskInfo(),
|
|
159
|
+
},
|
|
160
|
+
software: {
|
|
161
|
+
nodeVersion: process.version,
|
|
162
|
+
npxVersion: this.getCommandVersion('npx --version'),
|
|
163
|
+
dockerVersion: this.getCommandVersion('docker --version'),
|
|
164
|
+
redisAvailable: this.commandExists('redis-cli'),
|
|
165
|
+
redisConnected: await this.checkRedisConnection(),
|
|
166
|
+
},
|
|
167
|
+
environment: {
|
|
168
|
+
path: process.env.PATH || '',
|
|
169
|
+
home: process.env.HOME || '',
|
|
170
|
+
shell: process.env.SHELL || '',
|
|
171
|
+
lang: process.env.LANG || '',
|
|
172
|
+
},
|
|
173
|
+
processes: {
|
|
174
|
+
cfnRunning: this.countProcesses('claude-flow-novice|cfn-'),
|
|
175
|
+
totalProcesses: this.countAllProcesses(),
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
this.logger.debug('Collected system diagnostics', { hostname: diagnostics.hostname });
|
|
180
|
+
return diagnostics;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
this.logger.warn('Failed to collect diagnostics', { error });
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Collect CFN Loop state
|
|
189
|
+
*/
|
|
190
|
+
public async collectCFNLoopState(taskId: string): Promise<CFNLoopState> {
|
|
191
|
+
try {
|
|
192
|
+
const state: CFNLoopState = {
|
|
193
|
+
taskId,
|
|
194
|
+
timestamp: new Date().toISOString(),
|
|
195
|
+
errorType: '',
|
|
196
|
+
errorMessage: '',
|
|
197
|
+
exitCode: null,
|
|
198
|
+
redisState: {
|
|
199
|
+
connected: false,
|
|
200
|
+
trackedAgents: 0,
|
|
201
|
+
recentSignals: 0,
|
|
202
|
+
},
|
|
203
|
+
checkpoint: {
|
|
204
|
+
available: false,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// Check Redis state
|
|
209
|
+
if (await this.checkRedisConnection()) {
|
|
210
|
+
state.redisState.connected = true;
|
|
211
|
+
// Would query Redis for task context here
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Check checkpoint
|
|
215
|
+
const checkpointFile = `/tmp/cfn_loop_${taskId}_checkpoint.json`;
|
|
216
|
+
if (fs.existsSync(checkpointFile)) {
|
|
217
|
+
state.checkpoint.available = true;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Check temp files
|
|
221
|
+
const tempDir = `/tmp/cfn_loop_${taskId}`;
|
|
222
|
+
if (fs.existsSync(tempDir)) {
|
|
223
|
+
const files = fs.readdirSync(tempDir);
|
|
224
|
+
state.tempFiles = {
|
|
225
|
+
directory: tempDir,
|
|
226
|
+
fileCount: files.length,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
this.logger.debug('Collected CFN Loop state', { taskId });
|
|
231
|
+
return state;
|
|
232
|
+
} catch (error) {
|
|
233
|
+
this.logger.warn('Failed to collect CFN state', { error, taskId });
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Capture error with full context
|
|
240
|
+
*/
|
|
241
|
+
public async captureError(context: ErrorContext): Promise<ErrorLogEntry> {
|
|
242
|
+
// Validate circuit breaker
|
|
243
|
+
if (this.circuitBreaker.state === CircuitBreakerState.OPEN) {
|
|
244
|
+
throw new CircuitBreakerOpenError(
|
|
245
|
+
'Circuit breaker is open',
|
|
246
|
+
this.circuitBreaker.nextRetryTime
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Validate context
|
|
251
|
+
this.validateContext(context);
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
// Enrich context
|
|
255
|
+
const enrichedContext = { ...context };
|
|
256
|
+
if (!enrichedContext.correlationId) {
|
|
257
|
+
enrichedContext.correlationId = this.generateCorrelationId();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Collect diagnostics
|
|
261
|
+
const systemDiagnostics = await this.collectSystemDiagnostics();
|
|
262
|
+
const taskId = enrichedContext.taskId || 'unknown';
|
|
263
|
+
const cfnState = await this.collectCFNLoopState(taskId);
|
|
264
|
+
|
|
265
|
+
// Create log entry
|
|
266
|
+
const logEntry: ErrorLogEntry = {
|
|
267
|
+
captureId: this.generateCaptureId(),
|
|
268
|
+
timestamp: new Date().toISOString(),
|
|
269
|
+
unixTimestamp: Date.now(),
|
|
270
|
+
error: {
|
|
271
|
+
type: enrichedContext.errorType,
|
|
272
|
+
message: enrichedContext.message,
|
|
273
|
+
exitCode: enrichedContext.exitCode,
|
|
274
|
+
taskId: enrichedContext.taskId,
|
|
275
|
+
},
|
|
276
|
+
systemDiagnostics,
|
|
277
|
+
cfnState,
|
|
278
|
+
correlationId: enrichedContext.correlationId,
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// Store in batch if batching enabled
|
|
282
|
+
if (this.batchConfig.enabled) {
|
|
283
|
+
this.addToBatch({ error: enrichedContext, addedAt: Date.now() });
|
|
284
|
+
} else {
|
|
285
|
+
await this.storeError(logEntry);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Update metrics
|
|
289
|
+
this.metrics.totalCaptured++;
|
|
290
|
+
this.incrementMetric(
|
|
291
|
+
this.metrics.errorTypeCount,
|
|
292
|
+
enrichedContext.errorType as ErrorType
|
|
293
|
+
);
|
|
294
|
+
this.incrementMetric(this.metrics.severityCount, enrichedContext.severity);
|
|
295
|
+
|
|
296
|
+
// Record success in circuit breaker
|
|
297
|
+
await this.recordSuccess();
|
|
298
|
+
|
|
299
|
+
this.logger.info('Error captured', {
|
|
300
|
+
captureId: logEntry.captureId,
|
|
301
|
+
correlationId: enrichedContext.correlationId,
|
|
302
|
+
errorType: enrichedContext.errorType,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
return logEntry;
|
|
306
|
+
} catch (error) {
|
|
307
|
+
this.metrics.totalFailed++;
|
|
308
|
+
await this.recordFailure();
|
|
309
|
+
|
|
310
|
+
if (error instanceof ValidationError || error instanceof CircuitBreakerOpenError) {
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
throw new StorageError('Failed to capture error', 'file');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Store error to backends
|
|
320
|
+
*/
|
|
321
|
+
private async storeError(entry: ErrorLogEntry): Promise<void> {
|
|
322
|
+
const errors: Error[] = [];
|
|
323
|
+
|
|
324
|
+
for (const backend of this.backends) {
|
|
325
|
+
try {
|
|
326
|
+
switch (backend) {
|
|
327
|
+
case 'file':
|
|
328
|
+
await this.storeToFile(entry);
|
|
329
|
+
break;
|
|
330
|
+
case 'redis':
|
|
331
|
+
await this.storeToRedis(entry);
|
|
332
|
+
break;
|
|
333
|
+
case 'console':
|
|
334
|
+
await this.storeToConsole(entry);
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
} catch (error) {
|
|
338
|
+
errors.push(error instanceof Error ? error : new Error(String(error)));
|
|
339
|
+
this.logger.warn(`Failed to store to ${backend}`, { error });
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (errors.length === this.backends.length) {
|
|
344
|
+
throw new StorageError('All backends failed', 'all');
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Store error to file backend
|
|
350
|
+
*/
|
|
351
|
+
private async storeToFile(entry: ErrorLogEntry): Promise<void> {
|
|
352
|
+
if (!this.config.file) {
|
|
353
|
+
throw new StorageError('File backend not configured', 'file');
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const filename = path.join(
|
|
357
|
+
this.config.file.baseDir,
|
|
358
|
+
`cfn-error-${entry.error.taskId}-${entry.unixTimestamp}.json`
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
fs.writeFileSync(filename, JSON.stringify(entry, null, 2));
|
|
362
|
+
this.logger.debug(`Stored error to file: ${filename}`);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Store error to Redis backend (stub)
|
|
367
|
+
*/
|
|
368
|
+
private async storeToRedis(entry: ErrorLogEntry): Promise<void> {
|
|
369
|
+
if (!this.config.redis) {
|
|
370
|
+
throw new StorageError('Redis backend not configured', 'redis');
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const key = `${this.config.redis.keyPrefix}:${entry.captureId}`;
|
|
374
|
+
this.logger.debug(`Would store to Redis key: ${key}`);
|
|
375
|
+
// Redis implementation would go here
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Store error to console backend
|
|
380
|
+
*/
|
|
381
|
+
private async storeToConsole(entry: ErrorLogEntry): Promise<void> {
|
|
382
|
+
if (this.config.console?.enabled) {
|
|
383
|
+
if (this.config.console.formatJson) {
|
|
384
|
+
console.error(JSON.stringify(entry, null, 2));
|
|
385
|
+
} else {
|
|
386
|
+
console.error(`[${entry.error.type}] ${entry.error.message}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Get errors by correlation ID
|
|
393
|
+
*/
|
|
394
|
+
public async getErrorsByCorrelationId(correlationId: string): Promise<ErrorLogQuery[]> {
|
|
395
|
+
if (!this.config.file) {
|
|
396
|
+
return [];
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
try {
|
|
400
|
+
const files = fs.readdirSync(this.config.file.baseDir);
|
|
401
|
+
const errorLogs = files.filter((f) => f.startsWith('cfn-error-') && f.endsWith('.json'));
|
|
402
|
+
|
|
403
|
+
const matching: ErrorLogQuery[] = [];
|
|
404
|
+
for (const file of errorLogs) {
|
|
405
|
+
const filepath = path.join(this.config.file.baseDir, file);
|
|
406
|
+
try {
|
|
407
|
+
const content = fs.readFileSync(filepath, 'utf-8');
|
|
408
|
+
const entry = JSON.parse(content) as ErrorLogEntry;
|
|
409
|
+
if (entry.correlationId === correlationId) {
|
|
410
|
+
matching.push({
|
|
411
|
+
taskId: entry.error.taskId || 'unknown',
|
|
412
|
+
errorType: entry.error.type,
|
|
413
|
+
timestamp: entry.timestamp,
|
|
414
|
+
message: entry.error.message,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
} catch {
|
|
418
|
+
// Skip files that can't be parsed
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return matching;
|
|
422
|
+
} catch (error) {
|
|
423
|
+
this.logger.warn('Failed to get errors by correlation ID', { error });
|
|
424
|
+
return [];
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Get errors by minimum severity
|
|
430
|
+
*/
|
|
431
|
+
public async getErrorsByMinSeverity(_severity: SeverityLevel): Promise<ErrorLogQuery[]> {
|
|
432
|
+
const logs = await this.listErrorLogs();
|
|
433
|
+
return logs; // Would filter by severity in real implementation
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Generate error report
|
|
438
|
+
*/
|
|
439
|
+
public async generateReport(
|
|
440
|
+
taskId: string,
|
|
441
|
+
format: 'markdown' | 'json' = 'markdown'
|
|
442
|
+
): Promise<ErrorReport> {
|
|
443
|
+
if (!isValidTaskId(taskId)) {
|
|
444
|
+
throw new ValidationError('Invalid task ID', { taskId });
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
try {
|
|
448
|
+
const report: ErrorReport = {
|
|
449
|
+
taskId,
|
|
450
|
+
errorType: 'unknown',
|
|
451
|
+
message: 'Error occurred',
|
|
452
|
+
timestamp: new Date().toISOString(),
|
|
453
|
+
exitCode: 'unknown',
|
|
454
|
+
summary: 'CFN Loop encountered an error',
|
|
455
|
+
likelyCause: 'See troubleshooting steps below',
|
|
456
|
+
recommendedAction: 'Follow troubleshooting guide',
|
|
457
|
+
troubleshootingSteps: this.generateTroubleshootingSteps('unknown'),
|
|
458
|
+
systemState: {
|
|
459
|
+
nodeVersion: process.version,
|
|
460
|
+
npxVersion: 'unknown',
|
|
461
|
+
redisConnected: await this.checkRedisConnection(),
|
|
462
|
+
memoryAvailable: this.formatBytes(os.freemem()),
|
|
463
|
+
diskAvailable: await this.getDiskInfo(),
|
|
464
|
+
},
|
|
465
|
+
format,
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
this.metrics.totalReported++;
|
|
469
|
+
this.logger.info('Generated error report', { taskId, format });
|
|
470
|
+
|
|
471
|
+
return report;
|
|
472
|
+
} catch (error) {
|
|
473
|
+
this.logger.error('Failed to generate report', { error, taskId });
|
|
474
|
+
throw error;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Generate troubleshooting steps based on error type
|
|
480
|
+
*/
|
|
481
|
+
private generateTroubleshootingSteps(errorType: string) {
|
|
482
|
+
const steps = [
|
|
483
|
+
{ number: 1, action: 'Check system resources (memory/disk)', status: 'pending' as const },
|
|
484
|
+
{ number: 2, action: 'Verify dependencies installed', status: 'pending' as const },
|
|
485
|
+
{ number: 3, action: 'Review error logs for details', status: 'pending' as const },
|
|
486
|
+
{ number: 4, action: 'Check network connectivity', status: 'pending' as const },
|
|
487
|
+
];
|
|
488
|
+
|
|
489
|
+
switch (errorType) {
|
|
490
|
+
case ErrorType.ORCHESTRATOR:
|
|
491
|
+
return [
|
|
492
|
+
{ number: 1, action: 'Check task configuration parameters', status: 'pending' as const },
|
|
493
|
+
{ number: 2, action: 'Verify orchestrator script permissions', status: 'pending' as const },
|
|
494
|
+
{ number: 3, action: 'Check system resources (memory/disk)', status: 'pending' as const },
|
|
495
|
+
{ number: 4, action: 'Validate agent availability', status: 'pending' as const },
|
|
496
|
+
];
|
|
497
|
+
case ErrorType.AGENT_SPAWN:
|
|
498
|
+
return [
|
|
499
|
+
{ number: 1, action: 'Check Node.js installation: node --version', status: 'pending' as const },
|
|
500
|
+
{ number: 2, action: 'Check npx availability: npx --version', status: 'pending' as const },
|
|
501
|
+
{ number: 3, action: 'Check Redis connection: redis-cli ping', status: 'pending' as const },
|
|
502
|
+
{ number: 4, action: 'Check available memory: free -h', status: 'pending' as const },
|
|
503
|
+
];
|
|
504
|
+
case ErrorType.TIMEOUT:
|
|
505
|
+
return [
|
|
506
|
+
{ number: 1, action: 'Check system load: top', status: 'pending' as const },
|
|
507
|
+
{ number: 2, action: 'Verify network connectivity', status: 'pending' as const },
|
|
508
|
+
{ number: 3, action: 'Increase timeout values if needed', status: 'pending' as const },
|
|
509
|
+
{ number: 4, action: 'Check for stuck processes', status: 'pending' as const },
|
|
510
|
+
];
|
|
511
|
+
case ErrorType.RESOURCE:
|
|
512
|
+
return [
|
|
513
|
+
{ number: 1, action: 'Check available memory: free -h', status: 'pending' as const },
|
|
514
|
+
{ number: 2, action: 'Check disk space: df -h', status: 'pending' as const },
|
|
515
|
+
{ number: 3, action: 'Close unnecessary applications', status: 'pending' as const },
|
|
516
|
+
{ number: 4, action: 'Check process limits: ulimit -a', status: 'pending' as const },
|
|
517
|
+
];
|
|
518
|
+
default:
|
|
519
|
+
return steps;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Format report as markdown string
|
|
525
|
+
*/
|
|
526
|
+
public async formatReportAsMarkdown(taskId: string): Promise<string> {
|
|
527
|
+
const report = await this.generateReport(taskId, 'markdown');
|
|
528
|
+
|
|
529
|
+
let md = '# CFN Loop Error Report\n\n';
|
|
530
|
+
md += '## Error Summary\n';
|
|
531
|
+
md += `- **Task ID**: ${report.taskId}\n`;
|
|
532
|
+
md += `- **Error Type**: ${report.errorType}\n`;
|
|
533
|
+
md += `- **Message**: ${report.message}\n`;
|
|
534
|
+
md += `- **Timestamp**: ${report.timestamp}\n`;
|
|
535
|
+
md += `- **Exit Code**: ${report.exitCode}\n\n`;
|
|
536
|
+
|
|
537
|
+
md += '## Quick Diagnosis\n';
|
|
538
|
+
md += `**Most Likely Cause**: ${report.likelyCause}\n`;
|
|
539
|
+
md += `**Recommended Action**: ${report.recommendedAction}\n\n`;
|
|
540
|
+
|
|
541
|
+
md += '## Troubleshooting Steps\n';
|
|
542
|
+
for (const step of report.troubleshootingSteps) {
|
|
543
|
+
md += `${step.number}. ${step.action}\n`;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
md += '\n## System State\n';
|
|
547
|
+
md += `- **Node.js**: ${report.systemState.nodeVersion}\n`;
|
|
548
|
+
md += `- **Redis Connected**: ${report.systemState.redisConnected}\n`;
|
|
549
|
+
md += `- **Memory Available**: ${report.systemState.memoryAvailable}\n`;
|
|
550
|
+
|
|
551
|
+
return md;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Format report as JSON string
|
|
556
|
+
*/
|
|
557
|
+
public async formatReportAsJson(taskId: string): Promise<string> {
|
|
558
|
+
const report = await this.generateReport(taskId, 'json');
|
|
559
|
+
return JSON.stringify(report, null, 2);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* List error logs
|
|
564
|
+
*/
|
|
565
|
+
public async listErrorLogs(): Promise<ErrorLogQuery[]> {
|
|
566
|
+
if (!this.config.file) {
|
|
567
|
+
return [];
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
try {
|
|
571
|
+
const files = fs.readdirSync(this.config.file.baseDir);
|
|
572
|
+
const errorLogs = files.filter((f) => f.startsWith('cfn-error-') && f.endsWith('.json'));
|
|
573
|
+
|
|
574
|
+
return errorLogs.map((_file) => ({
|
|
575
|
+
taskId: 'unknown',
|
|
576
|
+
errorType: 'unknown',
|
|
577
|
+
timestamp: new Date().toISOString(),
|
|
578
|
+
message: 'Error log',
|
|
579
|
+
}));
|
|
580
|
+
} catch (error) {
|
|
581
|
+
this.logger.warn('Failed to list error logs', { error });
|
|
582
|
+
return [];
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* List error logs since specific time
|
|
588
|
+
*/
|
|
589
|
+
public async listErrorLogsSince(_since: Date): Promise<ErrorLogQuery[]> {
|
|
590
|
+
const all = await this.listErrorLogs();
|
|
591
|
+
return all;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* List error logs by type
|
|
596
|
+
*/
|
|
597
|
+
public async listErrorLogsByType(_errorType: ErrorType): Promise<ErrorLogQuery[]> {
|
|
598
|
+
const all = await this.listErrorLogs();
|
|
599
|
+
return all;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* List error logs by task
|
|
604
|
+
*/
|
|
605
|
+
public async listErrorLogsByTask(_taskId: string): Promise<ErrorLogQuery[]> {
|
|
606
|
+
const all = await this.listErrorLogs();
|
|
607
|
+
return all;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Format logs as table
|
|
612
|
+
*/
|
|
613
|
+
public async formatLogsAsTable(): Promise<string> {
|
|
614
|
+
const logs = await this.listErrorLogs();
|
|
615
|
+
|
|
616
|
+
let table = 'Task ID | Error Type | Timestamp | Message\n';
|
|
617
|
+
table += '--------------------+-----------. ----+------------------------+------------------------------\n';
|
|
618
|
+
|
|
619
|
+
for (const log of logs) {
|
|
620
|
+
table += `${log.taskId.padEnd(19)} | ${log.errorType.padEnd(16)} | ${log.timestamp.padEnd(22)} | ${log.message.substring(0, 30)}\n`;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return table;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Cleanup old logs
|
|
628
|
+
*/
|
|
629
|
+
public async cleanupOldLogs(retentionDays: number): Promise<{ removedCount: number; compressedCount: number }> {
|
|
630
|
+
if (!this.config.file) {
|
|
631
|
+
return { removedCount: 0, compressedCount: 0 };
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
try {
|
|
635
|
+
const cutoffTime = Date.now() - retentionDays * 24 * 3600 * 1000;
|
|
636
|
+
let removedCount = 0;
|
|
637
|
+
let compressedCount = 0;
|
|
638
|
+
|
|
639
|
+
const files = fs.readdirSync(this.config.file.baseDir);
|
|
640
|
+
for (const file of files) {
|
|
641
|
+
const filepath = path.join(this.config.file.baseDir, file);
|
|
642
|
+
const stat = fs.statSync(filepath);
|
|
643
|
+
|
|
644
|
+
if (stat.mtimeMs < cutoffTime) {
|
|
645
|
+
if (file.endsWith('.json')) {
|
|
646
|
+
// Compress
|
|
647
|
+
const gzPath = `${filepath}.gz`;
|
|
648
|
+
const source = fs.createReadStream(filepath);
|
|
649
|
+
const destination = fs.createWriteStream(gzPath);
|
|
650
|
+
source.pipe(zlib.createGzip()).pipe(destination);
|
|
651
|
+
compressedCount++;
|
|
652
|
+
} else if (file.endsWith('.gz')) {
|
|
653
|
+
// Remove very old compressed files
|
|
654
|
+
const veryOldCutoff = Date.now() - 30 * 24 * 3600 * 1000;
|
|
655
|
+
if (stat.mtimeMs < veryOldCutoff) {
|
|
656
|
+
fs.unlinkSync(filepath);
|
|
657
|
+
removedCount++;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
this.logger.info('Cleaned up old logs', { removedCount, compressedCount });
|
|
664
|
+
return { removedCount, compressedCount };
|
|
665
|
+
} catch (error) {
|
|
666
|
+
this.logger.error('Failed to cleanup logs', { error });
|
|
667
|
+
return { removedCount: 0, compressedCount: 0 };
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Enforce maximum directory size
|
|
673
|
+
*/
|
|
674
|
+
public async enforceMaxDirSize(_maxMb: number): Promise<{ removedCount: number }> {
|
|
675
|
+
if (!this.config.file) {
|
|
676
|
+
return { removedCount: 0 };
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
let removedCount = 0;
|
|
680
|
+
// Implementation for enforcing max size
|
|
681
|
+
return { removedCount };
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Add error to batch
|
|
686
|
+
*/
|
|
687
|
+
private addToBatch(entry: BatchEntry): void {
|
|
688
|
+
this.batch.push(entry);
|
|
689
|
+
|
|
690
|
+
if (this.batch.length >= this.batchConfig.maxSize) {
|
|
691
|
+
this.flushBuffer();
|
|
692
|
+
} else if (!this.batchFlushTimer) {
|
|
693
|
+
this.batchFlushTimer = setTimeout(
|
|
694
|
+
() => this.flushBuffer(),
|
|
695
|
+
this.batchConfig.maxWaitMs
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Enable batching
|
|
702
|
+
*/
|
|
703
|
+
public enableBatching(config: BatchConfig): void {
|
|
704
|
+
this.batchConfig = config;
|
|
705
|
+
if (config.enabled && !this.batchFlushTimer) {
|
|
706
|
+
this.batchFlushTimer = setTimeout(
|
|
707
|
+
() => this.flushBuffer(),
|
|
708
|
+
config.maxWaitMs
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Flush batch buffer
|
|
715
|
+
*/
|
|
716
|
+
public async flushBuffer(): Promise<ErrorLogEntry[]> {
|
|
717
|
+
if (this.batchFlushTimer) {
|
|
718
|
+
clearTimeout(this.batchFlushTimer);
|
|
719
|
+
this.batchFlushTimer = undefined;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const entries: ErrorLogEntry[] = [];
|
|
723
|
+
const toProcess = [...this.batch];
|
|
724
|
+
this.batch = [];
|
|
725
|
+
|
|
726
|
+
this.logger.debug(`Flushing buffer with ${toProcess.length} entries`);
|
|
727
|
+
|
|
728
|
+
return entries;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Get current buffer size
|
|
733
|
+
*/
|
|
734
|
+
public getBufferSize(): number {
|
|
735
|
+
return this.batch.length;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Set retry configuration
|
|
740
|
+
*/
|
|
741
|
+
public setRetryConfig(config: RetryConfig): void {
|
|
742
|
+
this.retryConfig = config;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* Get backoff delays
|
|
747
|
+
*/
|
|
748
|
+
public getBackoffDelays(attempts: number): number[] {
|
|
749
|
+
const delays: number[] = [];
|
|
750
|
+
let delay = this.retryConfig.initialDelayMs;
|
|
751
|
+
|
|
752
|
+
for (let i = 0; i < attempts; i++) {
|
|
753
|
+
delays.push(Math.min(delay, this.retryConfig.maxDelayMs));
|
|
754
|
+
delay *= this.retryConfig.backoffMultiplier;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
return delays;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Get circuit breaker status
|
|
762
|
+
*/
|
|
763
|
+
public getCircuitBreakerStatus(): CircuitBreakerStatus {
|
|
764
|
+
return { ...this.circuitBreaker };
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Record failure for circuit breaker
|
|
769
|
+
*/
|
|
770
|
+
public async recordFailure(): Promise<void> {
|
|
771
|
+
this.circuitBreaker.failureCount++;
|
|
772
|
+
this.circuitBreaker.lastFailureTime = Date.now();
|
|
773
|
+
|
|
774
|
+
if (this.circuitBreaker.failureCount >= this.circuitBreakerConfig.failureThreshold) {
|
|
775
|
+
this.circuitBreaker.state = CircuitBreakerState.OPEN;
|
|
776
|
+
this.circuitBreaker.nextRetryTime =
|
|
777
|
+
Date.now() + this.circuitBreakerConfig.timeout;
|
|
778
|
+
this.logger.warn('Circuit breaker opened due to failures');
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Record success for circuit breaker
|
|
784
|
+
*/
|
|
785
|
+
public async recordSuccess(): Promise<void> {
|
|
786
|
+
if (this.circuitBreaker.state === CircuitBreakerState.HALF_OPEN) {
|
|
787
|
+
this.circuitBreaker.successCount++;
|
|
788
|
+
|
|
789
|
+
if (this.circuitBreaker.successCount >= this.circuitBreakerConfig.successThreshold) {
|
|
790
|
+
this.circuitBreaker.state = CircuitBreakerState.CLOSED;
|
|
791
|
+
this.circuitBreaker.failureCount = 0;
|
|
792
|
+
this.circuitBreaker.successCount = 0;
|
|
793
|
+
this.logger.info('Circuit breaker closed after successful operations');
|
|
794
|
+
}
|
|
795
|
+
} else if (this.circuitBreaker.state === CircuitBreakerState.CLOSED) {
|
|
796
|
+
this.circuitBreaker.failureCount = Math.max(0, this.circuitBreaker.failureCount - 1);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// Check if should transition from OPEN to HALF_OPEN
|
|
800
|
+
if (
|
|
801
|
+
this.circuitBreaker.state === CircuitBreakerState.OPEN &&
|
|
802
|
+
this.circuitBreaker.nextRetryTime &&
|
|
803
|
+
Date.now() >= this.circuitBreaker.nextRetryTime
|
|
804
|
+
) {
|
|
805
|
+
this.circuitBreaker.state = CircuitBreakerState.HALF_OPEN;
|
|
806
|
+
this.circuitBreaker.successCount = 0;
|
|
807
|
+
this.logger.info('Circuit breaker transitioned to HALF_OPEN');
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Set backends
|
|
813
|
+
*/
|
|
814
|
+
public setBackends(backends: LoggingBackend[]): void {
|
|
815
|
+
this.backends = backends;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Enrich error with task context
|
|
820
|
+
*/
|
|
821
|
+
public async enrichWithTaskContext(
|
|
822
|
+
error: ErrorContext,
|
|
823
|
+
context?: Record<string, unknown>
|
|
824
|
+
): Promise<void> {
|
|
825
|
+
if (context) {
|
|
826
|
+
error.metadata = { ...error.metadata, ...context };
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* Enrich error with agent context
|
|
832
|
+
*/
|
|
833
|
+
public async enrichWithAgentContext(
|
|
834
|
+
error: ErrorContext,
|
|
835
|
+
context?: Record<string, unknown>
|
|
836
|
+
): Promise<void> {
|
|
837
|
+
if (context) {
|
|
838
|
+
error.metadata = { ...error.metadata, agent: context };
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Enrich error with environment context
|
|
844
|
+
*/
|
|
845
|
+
public async enrichWithEnvironmentContext(
|
|
846
|
+
error: ErrorContext,
|
|
847
|
+
context?: Record<string, unknown>
|
|
848
|
+
): Promise<void> {
|
|
849
|
+
if (context) {
|
|
850
|
+
error.metadata = { ...error.metadata, environment: context };
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Run system diagnostics
|
|
856
|
+
*/
|
|
857
|
+
public async runSystemDiagnostics(): Promise<SystemDiagnostics> {
|
|
858
|
+
return this.collectSystemDiagnostics();
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Check dependencies
|
|
863
|
+
*/
|
|
864
|
+
public async checkDependencies(): Promise<{
|
|
865
|
+
available: string[];
|
|
866
|
+
missing: string[];
|
|
867
|
+
}> {
|
|
868
|
+
const required = ['node', 'npx', 'jq', 'bc'];
|
|
869
|
+
const available: string[] = [];
|
|
870
|
+
const missing: string[] = [];
|
|
871
|
+
|
|
872
|
+
for (const dep of required) {
|
|
873
|
+
if (this.commandExists(dep)) {
|
|
874
|
+
available.push(dep);
|
|
875
|
+
} else {
|
|
876
|
+
missing.push(dep);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
return { available, missing };
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Validate Redis connection
|
|
885
|
+
*/
|
|
886
|
+
public async validateRedisConnection(): Promise<boolean> {
|
|
887
|
+
return this.checkRedisConnection();
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Get system resource status
|
|
892
|
+
*/
|
|
893
|
+
public async getSystemResourceStatus(): Promise<{
|
|
894
|
+
memory: string;
|
|
895
|
+
disk: string;
|
|
896
|
+
cpu: number;
|
|
897
|
+
}> {
|
|
898
|
+
return {
|
|
899
|
+
memory: this.formatBytes(os.freemem()),
|
|
900
|
+
disk: await this.getDiskInfo(),
|
|
901
|
+
cpu: os.cpus().length,
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Get metrics
|
|
907
|
+
*/
|
|
908
|
+
public getMetrics(): typeof this.metrics {
|
|
909
|
+
return { ...this.metrics };
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* Get error type distribution
|
|
914
|
+
*/
|
|
915
|
+
public getErrorTypeDistribution(): Record<string, number> {
|
|
916
|
+
const dist: Record<string, number> = {};
|
|
917
|
+
this.metrics.errorTypeCount.forEach((count, type) => {
|
|
918
|
+
dist[type] = count;
|
|
919
|
+
});
|
|
920
|
+
return dist;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Get severity distribution
|
|
925
|
+
*/
|
|
926
|
+
public getSeverityDistribution(): Record<string, number> {
|
|
927
|
+
const dist: Record<string, number> = {};
|
|
928
|
+
this.metrics.severityCount.forEach((count, level) => {
|
|
929
|
+
dist[level] = count;
|
|
930
|
+
});
|
|
931
|
+
return dist;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// ===== HELPER METHODS =====
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* Check if command exists
|
|
938
|
+
*/
|
|
939
|
+
private commandExists(command: string): boolean {
|
|
940
|
+
try {
|
|
941
|
+
execSync(`command -v ${command}`, { stdio: 'ignore' });
|
|
942
|
+
return true;
|
|
943
|
+
} catch {
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* Get command version
|
|
950
|
+
*/
|
|
951
|
+
private getCommandVersion(command: string): string {
|
|
952
|
+
try {
|
|
953
|
+
const output = execSync(command, { encoding: 'utf-8' });
|
|
954
|
+
return output.trim();
|
|
955
|
+
} catch {
|
|
956
|
+
return 'not found';
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Count processes matching pattern
|
|
962
|
+
*/
|
|
963
|
+
private countProcesses(pattern: string): number {
|
|
964
|
+
try {
|
|
965
|
+
const output = execSync(`pgrep -f "${pattern}" 2>/dev/null | wc -l`, {
|
|
966
|
+
encoding: 'utf-8',
|
|
967
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
968
|
+
});
|
|
969
|
+
return parseInt(output.trim(), 10) || 0;
|
|
970
|
+
} catch {
|
|
971
|
+
return 0;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* Count all processes
|
|
977
|
+
*/
|
|
978
|
+
private countAllProcesses(): number {
|
|
979
|
+
try {
|
|
980
|
+
const output = execSync('ps aux 2>/dev/null | wc -l', {
|
|
981
|
+
encoding: 'utf-8',
|
|
982
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
983
|
+
});
|
|
984
|
+
return parseInt(output.trim(), 10) || 0;
|
|
985
|
+
} catch {
|
|
986
|
+
return 0;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* Check Redis connection
|
|
992
|
+
*/
|
|
993
|
+
private async checkRedisConnection(): Promise<boolean> {
|
|
994
|
+
try {
|
|
995
|
+
execSync('redis-cli ping', { stdio: 'ignore' });
|
|
996
|
+
return true;
|
|
997
|
+
} catch {
|
|
998
|
+
return false;
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Get disk info
|
|
1004
|
+
*/
|
|
1005
|
+
private async getDiskInfo(): Promise<string> {
|
|
1006
|
+
try {
|
|
1007
|
+
const output = execSync('df -h / 2>/dev/null | tail -1', {
|
|
1008
|
+
encoding: 'utf-8',
|
|
1009
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
1010
|
+
});
|
|
1011
|
+
return output.trim();
|
|
1012
|
+
} catch {
|
|
1013
|
+
return 'unknown';
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Format bytes to human readable
|
|
1019
|
+
*/
|
|
1020
|
+
private formatBytes(bytes: number): string {
|
|
1021
|
+
const units = ['B', 'KB', 'MB', 'GB'];
|
|
1022
|
+
let size = bytes;
|
|
1023
|
+
let unitIndex = 0;
|
|
1024
|
+
|
|
1025
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
1026
|
+
size /= 1024;
|
|
1027
|
+
unitIndex++;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* Increment metric counter
|
|
1035
|
+
*/
|
|
1036
|
+
private incrementMetric<T>(map: Map<T, number>, key: T): void {
|
|
1037
|
+
map.set(key, (map.get(key) || 0) + 1);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
// Export types
|
|
1042
|
+
export * from './types';
|