claude-flow-novice 2.15.3 → 2.15.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
- package/.claude/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
- package/.claude/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
- package/.claude/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
- package/.claude/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
- package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
- package/.claude/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
- package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
- package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
- package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
- package/.claude/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
- package/.claude/commands/cfn-loop-cli.md +29 -6
- package/.claude/commands/switch-api.md +31 -10
- package/.claude/hooks/cfn-lint-sql-injection.sh +61 -0
- package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
- package/.claude/hooks/cfn-pre-edit-security-warning.sh +40 -0
- package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
- package/.claude/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
- package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
- package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
- package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
- package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
- package/.claude/skills/cfn-loop-orchestration/security_utils.sh +24 -0
- package/.claude/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
- package/.claude/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
- package/.claude/skills/cfn-redis-coordination/agent-log.sh +4 -0
- package/.claude/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
- package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
- package/.claude/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
- package/.claude/skills/cfn-redis-coordination/get-context.sh +33 -0
- package/.claude/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
- package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
- package/.claude/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
- package/.claude/skills/cfn-redis-coordination/redis-functions.sh +34 -0
- package/.claude/skills/cfn-redis-coordination/report-completion.sh +24 -31
- package/.claude/skills/cfn-redis-coordination/store-context.sh +4 -0
- package/.claude/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
- package/.claude/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
- package/.claude/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
- package/.claude/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
- package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
- package/README.md +116 -475
- package/claude-assets/agents/cfn-dev-team/README.md +103 -0
- package/claude-assets/agents/cfn-dev-team/architecture/goal-planner.md +1 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +77 -15
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +355 -6
- package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +82 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +82 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +77 -15
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +99 -12
- package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +1 -1
- package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +97 -0
- package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +20 -1
- package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +97 -0
- package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +110 -13
- package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +106 -15
- package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +115 -11
- package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +94 -7
- package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +87 -9
- package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +85 -7
- package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +160 -28
- package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +101 -19
- package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +108 -14
- package/claude-assets/agents/cfn-dev-team/reviewers/{reviewer.md → code-reviewer.md} +95 -8
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +107 -7
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +98 -7
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +95 -7
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +136 -9
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +108 -1
- package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +107 -13
- package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +737 -0
- package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +828 -0
- package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +106 -7
- package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +77 -0
- package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +684 -0
- package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +110 -1
- package/claude-assets/agents/cfn-dev-team/testers/tester.md +94 -7
- package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +1 -3
- package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +87 -13
- package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +103 -7
- package/claude-assets/agents/cfn-dev-team/utility/researcher.md +1 -3
- package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +94 -7
- package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +46 -0
- package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
- package/claude-assets/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
- package/claude-assets/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
- package/claude-assets/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
- package/claude-assets/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
- package/claude-assets/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
- package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
- package/claude-assets/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
- package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
- package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
- package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
- package/claude-assets/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
- package/claude-assets/commands/cfn-loop-cli.md +29 -6
- package/claude-assets/commands/switch-api.md +31 -10
- package/claude-assets/hooks/cfn-lint-sql-injection.sh +61 -0
- package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
- package/claude-assets/hooks/cfn-pre-edit-security-warning.sh +40 -0
- package/claude-assets/hooks/detect-hardcoded-credentials.sh +212 -0
- package/claude-assets/skills/SKILL_TEMPLATE.md +774 -0
- package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +84 -113
- package/claude-assets/skills/agent-lifecycle/simple-audit.sh +33 -6
- package/claude-assets/skills/agent-template-generator/SKILL.md +440 -0
- package/claude-assets/skills/agent-template-generator/generate-agent.sh +405 -0
- package/claude-assets/skills/agent-validation-linter/SKILL.md +589 -0
- package/claude-assets/skills/agent-validation-linter/lint-agents.sh +271 -0
- package/claude-assets/skills/bootstrap/bash-fundamentals.md +786 -0
- package/claude-assets/skills/bootstrap/database-connection.md +464 -0
- package/claude-assets/skills/bootstrap/error-handling.md +580 -0
- package/claude-assets/skills/bootstrap/file-operations.md +699 -0
- package/claude-assets/skills/bootstrap/skill-loader.md +616 -0
- package/claude-assets/skills/bootstrap/sqlite-params.sh +287 -0
- package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
- package/claude-assets/skills/cfn-automatic-memory-persistence/test-memory-persistence.sh +17 -16
- package/claude-assets/skills/cfn-deployment/SKILL.md +293 -0
- package/claude-assets/skills/cfn-deployment/execute.sh +21 -0
- package/claude-assets/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
- package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
- package/claude-assets/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
- package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +38 -0
- package/claude-assets/skills/cfn-error-batching-strategy/lib/core-functions.sh +47 -47
- package/claude-assets/skills/cfn-file-operations/SKILL.md +290 -0
- package/claude-assets/skills/cfn-file-operations/execute.sh +129 -0
- package/claude-assets/skills/cfn-file-operations/lib/atomic-write.sh +294 -0
- package/claude-assets/skills/cfn-file-operations/lib/lock.sh +361 -0
- package/claude-assets/skills/cfn-file-operations/test.sh +369 -0
- package/claude-assets/skills/cfn-log-operations/SKILL.md +308 -0
- package/claude-assets/skills/cfn-log-operations/execute.sh +420 -0
- package/claude-assets/skills/cfn-log-operations/lib/rotate.sh +406 -0
- package/claude-assets/skills/cfn-log-operations/lib/search.sh +448 -0
- package/claude-assets/skills/cfn-log-operations/test.sh +394 -0
- package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
- package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
- package/claude-assets/skills/cfn-loop-orchestration/security_utils.sh +24 -0
- package/claude-assets/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
- package/claude-assets/skills/cfn-parameterized-queries/SKILL.md +339 -0
- package/claude-assets/skills/cfn-playbook/query-playbook.sh +19 -15
- package/claude-assets/skills/cfn-playbook/update-playbook.sh +25 -14
- package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +44 -0
- package/claude-assets/skills/cfn-promotion/SKILL.md +305 -0
- package/claude-assets/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
- package/claude-assets/skills/cfn-redis-coordination/agent-log.sh +4 -0
- package/claude-assets/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
- package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
- package/claude-assets/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
- package/claude-assets/skills/cfn-redis-coordination/get-context.sh +33 -0
- package/claude-assets/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
- package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
- package/claude-assets/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
- package/claude-assets/skills/cfn-redis-coordination/redis-functions.sh +34 -0
- package/claude-assets/skills/cfn-redis-coordination/report-completion.sh +24 -31
- package/claude-assets/skills/cfn-redis-coordination/store-context.sh +4 -0
- package/claude-assets/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
- package/claude-assets/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
- package/claude-assets/skills/cfn-skill-loader/SKILL.md +466 -0
- package/claude-assets/skills/cfn-skill-loader/execute.sh +344 -0
- package/claude-assets/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
- package/claude-assets/skills/cfn-task-audit/get-audit-data.sh +42 -21
- package/claude-assets/skills/cfn-task-audit/store-task-audit.sh +17 -10
- package/claude-assets/skills/cfn-test-runner/detect-regressions.sh +17 -14
- package/claude-assets/skills/cfn-test-runner/detect-regressions.sh.backup-1763392821 +55 -0
- package/claude-assets/skills/cfn-test-runner/store-benchmarks.sh +17 -19
- package/claude-assets/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
- package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
- package/claude-assets/skills/cfn-utilities/SKILL.md +237 -0
- package/claude-assets/skills/cfn-utilities/execute.sh +32 -0
- package/claude-assets/skills/cfn-utilities/lib/errors.sh +56 -0
- package/claude-assets/skills/cfn-utilities/lib/file-ops.sh +164 -0
- package/claude-assets/skills/cfn-utilities/lib/logging.sh +77 -0
- package/claude-assets/skills/cfn-utilities/lib/retry.sh +127 -0
- package/claude-assets/skills/cfn-utilities/test.sh +317 -0
- package/claude-assets/skills/integration/agent-handoff.sh +62 -64
- package/claude-assets/skills/json-validation/SKILL.md +431 -0
- package/claude-assets/skills/json-validation/test-validate-success-criteria.sh +421 -0
- package/claude-assets/skills/json-validation/validate-success-criteria.sh +197 -0
- package/claude-assets/skills/redis-coordination/validate-parameters.sh +34 -0
- package/claude-assets/skills/workflow-codification/DEPLOY_QUICK_REFERENCE.md +106 -0
- package/claude-assets/skills/workflow-codification/PROPAGATE_UPDATE_QUICK_REFERENCE.md +366 -0
- package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh +481 -0
- package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh.backup-1763392820 +512 -0
- package/claude-assets/skills/workflow-codification/lib/security-utils.sh +204 -0
- package/claude-assets/skills/workflow-codification/propagate-skill-update.sh +648 -0
- package/claude-assets/skills/workflow-codification/propagate-skill-update.sh.backup-1763392820 +664 -0
- package/claude-assets/skills/workflow-codification/test-integration.sh +15 -0
- package/claude-assets/skills/workflow-codification/test-metadata-update.sh +350 -0
- package/claude-assets/skills/workflow-codification/track-cost-savings.sh +55 -14
- package/claude-assets/skills/workflow-codification/track-cost-savings.sh.backup-1763392821 +445 -0
- package/claude-assets/skills/workflow-codification/track-edge-case.sh +27 -60
- package/claude-assets/skills/workflow-codification/workflow-codification.db +0 -0
- package/dist/ace/ace-curator.js +10 -2
- package/dist/ace/ace-curator.js.map +1 -1
- package/dist/ace/ace-generator.js +4 -0
- package/dist/ace/ace-generator.js.map +1 -1
- package/dist/ace/ace-reflector.js +1 -1
- package/dist/ace/ace-reflector.js.map +1 -1
- package/dist/ace/context-injection.js +24 -2
- package/dist/ace/context-injection.js.map +1 -1
- package/dist/agents/task-agent-integration.js +1 -1
- package/dist/agents/task-agent-integration.js.map +1 -1
- package/dist/api/health-endpoints.js +390 -0
- package/dist/api/health-endpoints.js.map +1 -0
- package/dist/cli/agent-executor.js +4 -1
- package/dist/cli/agent-executor.js.map +1 -1
- package/dist/cli/agent-prompt-builder.js +89 -1
- package/dist/cli/agent-prompt-builder.js.map +1 -1
- package/dist/cli/agent-spawn.js +130 -37
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/config-manager.js +109 -91
- package/dist/cli/config-manager.js.map +1 -1
- package/dist/cli/conversation-fork-cleanup.js +201 -0
- package/dist/cli/conversation-fork-cleanup.js.map +1 -0
- package/dist/cli/conversation-fork.js +16 -3
- package/dist/cli/conversation-fork.js.map +1 -1
- package/dist/cli/skill-cache-validator.js +412 -0
- package/dist/cli/skill-cache-validator.js.map +1 -0
- package/dist/cli/skill-cli.js +991 -0
- package/dist/cli/skill-cli.js.map +1 -0
- package/dist/cli/skill-execution-logger.js +284 -0
- package/dist/cli/skill-execution-logger.js.map +1 -0
- package/dist/cli/skill-loader.js +457 -0
- package/dist/cli/skill-loader.js.map +1 -0
- package/dist/coordination/event-bus.js +2 -2
- package/dist/coordination/event-bus.js.map +1 -1
- package/dist/coordination/fleet-manager.js +1 -1
- package/dist/coordination/fleet-manager.js.map +1 -1
- package/dist/coordination/index.js +23 -9
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/types/fleet-manager.types.js.map +1 -1
- package/dist/db/migration-manager.js +483 -0
- package/dist/db/migration-manager.js.map +1 -0
- package/dist/db/skills-query.js +535 -0
- package/dist/db/skills-query.js.map +1 -0
- package/dist/integration/DatabaseHandoff.js +1 -1
- package/dist/integration/DatabaseHandoff.js.map +1 -1
- package/dist/jobs/edge-case-analyzer.js +367 -0
- package/dist/jobs/edge-case-analyzer.js.map +1 -0
- package/dist/jobs/promotion-sla-enforcer.js +288 -0
- package/dist/jobs/promotion-sla-enforcer.js.map +1 -0
- package/dist/lib/agent-output-parser.js.map +1 -1
- package/dist/lib/agent-output-validator.js.map +1 -1
- package/dist/lib/agent-workspace.js +281 -0
- package/dist/lib/agent-workspace.js.map +1 -0
- package/dist/lib/atomic-file-writer.js +377 -0
- package/dist/lib/atomic-file-writer.js.map +1 -0
- package/dist/lib/backup-manager.js +779 -0
- package/dist/lib/backup-manager.js.map +1 -0
- package/dist/lib/checkpoint-manager.js +837 -0
- package/dist/lib/checkpoint-manager.js.map +1 -0
- package/dist/lib/circuit-breaker.js +340 -0
- package/dist/lib/circuit-breaker.js.map +1 -0
- package/dist/lib/completion-signal-handler.js +243 -0
- package/dist/lib/completion-signal-handler.js.map +1 -0
- package/dist/lib/config-manager.js +312 -0
- package/dist/lib/config-manager.js.map +1 -0
- package/dist/lib/config-migrator.js +386 -0
- package/dist/lib/config-migrator.js.map +1 -0
- package/dist/lib/config-validator.js.map +1 -1
- package/dist/lib/correlation-cache.js +311 -0
- package/dist/lib/correlation-cache.js.map +1 -0
- package/dist/lib/correlation.js +263 -0
- package/dist/lib/correlation.js.map +1 -0
- package/dist/lib/database-service/connection-pool-manager.js +520 -0
- package/dist/lib/database-service/connection-pool-manager.js.map +1 -0
- package/dist/lib/database-service/correlation.js +329 -0
- package/dist/lib/database-service/correlation.js.map +1 -0
- package/dist/lib/database-service/errors.js +120 -0
- package/dist/lib/database-service/errors.js.map +1 -0
- package/dist/lib/database-service/index.js +168 -0
- package/dist/lib/database-service/index.js.map +1 -0
- package/dist/lib/database-service/postgres-adapter.js +526 -0
- package/dist/lib/database-service/postgres-adapter.js.map +1 -0
- package/dist/lib/database-service/redis-adapter.js +360 -0
- package/dist/lib/database-service/redis-adapter.js.map +1 -0
- package/dist/lib/database-service/sqlite-adapter.js +544 -0
- package/dist/lib/database-service/sqlite-adapter.js.map +1 -0
- package/dist/lib/database-service/transaction-manager.js +773 -0
- package/dist/lib/database-service/transaction-manager.js.map +1 -0
- package/dist/lib/database-service/types.js +23 -0
- package/dist/lib/database-service/types.js.map +1 -0
- package/dist/lib/deadlock-resolver.js +292 -0
- package/dist/lib/deadlock-resolver.js.map +1 -0
- package/dist/lib/distributed-lock.js +451 -0
- package/dist/lib/distributed-lock.js.map +1 -0
- package/dist/lib/edge-case-deduplicator.js +227 -0
- package/dist/lib/edge-case-deduplicator.js.map +1 -0
- package/dist/lib/encryption-manager.js +322 -0
- package/dist/lib/encryption-manager.js.map +1 -0
- package/dist/lib/error-aggregator.js +234 -0
- package/dist/lib/error-aggregator.js.map +1 -0
- package/dist/lib/errors.js +287 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/file-lock-manager.js +578 -0
- package/dist/lib/file-lock-manager.js.map +1 -0
- package/dist/lib/file-operations.js +367 -0
- package/dist/lib/file-operations.js.map +1 -0
- package/dist/lib/idempotent-write.js +237 -0
- package/dist/lib/idempotent-write.js.map +1 -0
- package/dist/lib/integration-schema-validator.js +522 -0
- package/dist/lib/integration-schema-validator.js.map +1 -0
- package/dist/lib/lock-health-monitor.js +298 -0
- package/dist/lib/lock-health-monitor.js.map +1 -0
- package/dist/lib/log-shipper.js +422 -0
- package/dist/lib/log-shipper.js.map +1 -0
- package/dist/lib/logging.js +146 -0
- package/dist/lib/logging.js.map +1 -0
- package/dist/lib/message-deduplicator.js +439 -0
- package/dist/lib/message-deduplicator.js.map +1 -0
- package/dist/lib/multi-system-query.js +604 -0
- package/dist/lib/multi-system-query.js.map +1 -0
- package/dist/lib/orphan-detector.js +332 -0
- package/dist/lib/orphan-detector.js.map +1 -0
- package/dist/lib/password-generator.js +166 -0
- package/dist/lib/password-generator.js.map +1 -0
- package/dist/lib/path-validator.js +429 -0
- package/dist/lib/path-validator.js.map +1 -0
- package/dist/lib/query-translator.js +905 -0
- package/dist/lib/query-translator.js.map +1 -0
- package/dist/lib/queue-recovery.js +469 -0
- package/dist/lib/queue-recovery.js.map +1 -0
- package/dist/lib/redis-queue-manager.js +512 -0
- package/dist/lib/redis-queue-manager.js.map +1 -0
- package/dist/lib/reflection-archiver.js +272 -0
- package/dist/lib/reflection-archiver.js.map +1 -0
- package/dist/lib/retry-manager.js +453 -0
- package/dist/lib/retry-manager.js.map +1 -0
- package/dist/lib/retry.js +262 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/schema-transform.js +695 -0
- package/dist/lib/schema-transform.js.map +1 -0
- package/dist/lib/schema-validator.js +491 -0
- package/dist/lib/schema-validator.js.map +1 -0
- package/dist/lib/skill-cache.js +297 -0
- package/dist/lib/skill-cache.js.map +1 -0
- package/dist/lib/skill-content-manager.js +337 -0
- package/dist/lib/skill-content-manager.js.map +1 -0
- package/dist/lib/skill-frontmatter-parser.js +237 -0
- package/dist/lib/skill-frontmatter-parser.js.map +1 -0
- package/dist/lib/skill-git-integration.js +275 -0
- package/dist/lib/skill-git-integration.js.map +1 -0
- package/dist/lib/skill-markdown-validator.js +396 -0
- package/dist/lib/skill-markdown-validator.js.map +1 -0
- package/dist/lib/skill-output-parser.js +312 -0
- package/dist/lib/skill-output-parser.js.map +1 -0
- package/dist/lib/unified-query-api.js +467 -0
- package/dist/lib/unified-query-api.js.map +1 -0
- package/dist/middleware/auth-middleware.js +350 -0
- package/dist/middleware/auth-middleware.js.map +1 -0
- package/dist/middleware/schema-validation.js +347 -0
- package/dist/middleware/schema-validation.js.map +1 -0
- package/dist/providers/anthropic-provider.js +1 -1
- package/dist/providers/anthropic-provider.js.map +1 -1
- package/dist/providers/provider-factory.js +2 -2
- package/dist/providers/provider-factory.js.map +1 -1
- package/dist/services/edge-case-analyzer.js +321 -0
- package/dist/services/edge-case-analyzer.js.map +1 -0
- package/dist/services/edge-case-deduplicator.js +266 -0
- package/dist/services/edge-case-deduplicator.js.map +1 -0
- package/dist/services/edge-case-detector.js +337 -0
- package/dist/services/edge-case-detector.js.map +1 -0
- package/dist/services/edge-case-tracker.js +547 -0
- package/dist/services/edge-case-tracker.js.map +1 -0
- package/dist/services/health-check-system.js +586 -0
- package/dist/services/health-check-system.js.map +1 -0
- package/dist/services/metrics-logger.js +412 -0
- package/dist/services/metrics-logger.js.map +1 -0
- package/dist/services/patch-generator.js +378 -0
- package/dist/services/patch-generator.js.map +1 -0
- package/dist/services/patch-validator.js +337 -0
- package/dist/services/patch-validator.js.map +1 -0
- package/dist/services/performance-monitor.js +811 -0
- package/dist/services/performance-monitor.js.map +1 -0
- package/dist/services/promotion-pipeline.js +918 -0
- package/dist/services/promotion-pipeline.js.map +1 -0
- package/dist/services/promotion-validator.js +394 -0
- package/dist/services/promotion-validator.js.map +1 -0
- package/dist/services/reflection-logger.js +388 -0
- package/dist/services/reflection-logger.js.map +1 -0
- package/dist/services/skill-deployment.js +472 -0
- package/dist/services/skill-deployment.js.map +1 -0
- package/dist/services/skill-loader.js +427 -0
- package/dist/services/skill-loader.js.map +1 -0
- package/dist/services/skill-promotion.js +372 -0
- package/dist/services/skill-promotion.js.map +1 -0
- package/dist/services/skill-validator.js +454 -0
- package/dist/services/skill-validator.js.map +1 -0
- package/dist/services/skill-versioning.js +244 -0
- package/dist/services/skill-versioning.js.map +1 -0
- package/dist/services/workspace-supervisor.js +597 -0
- package/dist/services/workspace-supervisor.js.map +1 -0
- package/dist/types/edge-case.js +45 -0
- package/dist/types/edge-case.js.map +1 -0
- package/docs/BUG_19_MEMORY_LEAK_TASK_MODE.md +405 -0
- package/docs/MEMORY_CLEANUP_GUIDE.md +358 -0
- package/docs/MEMORY_LEAK_FIX_SUMMARY.md +322 -0
- package/docs/REDIS_CLEANUP_EXECUTIVE_SUMMARY.md +319 -0
- package/docs/REDIS_CLEANUP_VERIFICATION_REPORT.md +574 -0
- package/package.json +35 -4
- package/readme/README.md +53 -5
- package/scripts/backup-cleanup.sh +627 -0
- package/scripts/cleanup-workspaces.sh +412 -0
- package/scripts/cleanup-yaml-configs.sh +141 -0
- package/scripts/deploy-approved-skills.sh +263 -0
- package/scripts/health-check.sh +447 -0
- package/scripts/log-aggregator.sh +554 -0
- package/scripts/log-monitor.sh +629 -0
- package/scripts/manage-agent-workspaces.sh +434 -0
- package/scripts/migrate-schema.sh +533 -0
- package/scripts/promote-staged-skills.sh +423 -0
- package/scripts/verify-no-secrets.sh +88 -35
- package/scripts/verify-redis-cleanup.sh +173 -0
- package/tests/README.md +84 -0
- package/tests/test-memory-leak-task-mode.sh +435 -0
- package/.claude/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
- package/.claude/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
- package/.claude/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
- package/.claude/skills/agent-lifecycle/SKILL.md +0 -60
- package/.claude/skills/agent-lifecycle/execute-lifecycle-hook.sh +0 -573
- package/.claude/skills/agent-lifecycle/simple-audit.sh +0 -31
- package/.claude/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
- package/README.md.backup_before_replace +0 -781
- package/claude-assets/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
- package/claude-assets/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
- package/claude-assets/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
- package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/promotion-pipeline.ts"],"sourcesContent":["/**\n * Promotion Pipeline Service\n *\n * Implements automated promotion pipeline with stages:\n * 1. Validate: Schema and file structure validation\n * 2. Test: Execute test suite\n * 3. Approve: Approval gate (auto or manual)\n * 4. Deploy: Atomic deployment to production\n *\n * Features:\n * - Multi-stage pipeline with confidence scoring\n * - Auto-approval based on confidence threshold\n * - Atomic deployment with rollback\n * - Comprehensive audit trail\n * - Event notifications\n * - Concurrency control\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { promisify } from 'util';\nimport { spawn, ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\nimport { DatabaseService } from '../lib/database-service.js';\nimport { StandardError, ErrorCode } from '../lib/errors.js';\nimport { createLogger } from '../lib/logging.js';\nimport { AuthMiddleware, RBACEnforcer, UserContext, PromotionOperation } from '../middleware/auth-middleware.js';\n\nconst fsRename = promisify(fs.rename);\nconst fsMkdir = promisify(fs.mkdir);\nconst fsReadFile = promisify(fs.readFile);\n\nconst logger = createLogger('promotion-pipeline');\n\n/**\n * Promotion request\n */\nexport interface PromotionRequest {\n skillId: string;\n fromVersion: string;\n toVersion: string;\n requestedBy: string;\n reason: string;\n}\n\n/**\n * Stage result\n */\nexport interface StageResult {\n stage: string;\n passed: boolean;\n confidence: number;\n errors: string[];\n message?: string;\n duration?: number;\n testsPassed?: boolean;\n coverage?: number;\n approvalReason?: string;\n approvedBy?: string;\n autoApproved?: boolean;\n requiresManualApproval?: boolean;\n productionPath?: string;\n success?: boolean;\n}\n\n/**\n * Approval result\n */\nexport interface ApprovalResult {\n approved: boolean;\n autoApproved: boolean;\n approvedBy: string;\n approvalReason?: string;\n requiresManualApproval: boolean;\n confidence: number;\n}\n\n/**\n * Promotion result\n */\nexport interface PromotionResult {\n success: boolean;\n skillId?: string;\n fromVersion?: string;\n toVersion?: string;\n promotedAt?: string;\n submittedAt?: string;\n productionPath?: string;\n failedStage?: string;\n error?: string;\n stages?: StageResult[];\n}\n\n/**\n * Audit trail entry\n */\nexport interface AuditEntry {\n skillId: string;\n action: string;\n actor: string;\n timestamp: string;\n details?: string;\n}\n\n/**\n * Promotion Pipeline Configuration\n */\nexport interface PipelineConfig {\n stagingDir?: string;\n productionDir?: string;\n autoApprovalConfidenceThreshold?: number;\n testTimeoutMs?: number;\n enableNotifications?: boolean;\n}\n\n/**\n * Promotion Pipeline with RBAC\n *\n * SECURITY: All promotion operations are protected by role-based access control.\n * Users must be authenticated and have appropriate permissions for each stage.\n */\nexport class PromotionPipeline extends EventEmitter {\n private dbService: DatabaseService;\n private stagingDir: string;\n private productionDir: string;\n private autoApprovalThreshold: number;\n private testTimeoutMs: number;\n private skillLocks: Map<string, Promise<void>>;\n private authMiddleware: AuthMiddleware;\n private rbacEnforcer: RBACEnforcer;\n private userContext?: UserContext;\n\n constructor(dbService: DatabaseService, config: PipelineConfig = {}, jwtSecret?: string) {\n super();\n\n this.dbService = dbService;\n this.stagingDir = config.stagingDir || '.claude/skills/staging';\n this.productionDir = config.productionDir || '.claude/skills';\n this.autoApprovalThreshold = config.autoApprovalConfidenceThreshold || 0.9;\n this.testTimeoutMs = config.testTimeoutMs || 120000; // 2 minutes\n this.skillLocks = new Map();\n\n // Initialize authentication and RBAC\n this.authMiddleware = new AuthMiddleware(jwtSecret);\n this.rbacEnforcer = new RBACEnforcer(this.authMiddleware);\n }\n\n /**\n * Set authenticated user context (REQUIRED before calling any promotion operations)\n *\n * @param authHeader - JWT token or \"Bearer <token>\"\n * @param sessionId - Optional session ID for fallback authentication\n * @throws StandardError if authentication fails\n */\n setUserContext(authHeader?: string, sessionId?: string): void {\n try {\n this.userContext = this.authMiddleware.extractUserContext(authHeader, sessionId);\n logger.info('User context set for promotion pipeline', {\n userId: this.userContext.userId,\n role: this.userContext.role,\n });\n } catch (error) {\n logger.warn('Failed to set user context', { error });\n throw error;\n }\n }\n\n /**\n * Get current user context\n */\n getUserContext(): UserContext | undefined {\n return this.userContext;\n }\n\n /**\n * Check if user is authenticated\n */\n isAuthenticated(): boolean {\n return this.userContext !== undefined;\n }\n\n /**\n * Ensure user is authenticated\n * @throws StandardError if user is not authenticated\n */\n private ensureAuthenticated(): void {\n if (!this.userContext) {\n throw new StandardError(\n ErrorCode.VALIDATION_FAILED,\n 'Authentication required for promotion operations. Call setUserContext() first.'\n );\n }\n }\n\n /**\n * Require specific permission for operation\n * @throws StandardError if user lacks permission\n */\n private requirePermission(operation: PromotionOperation, skillId?: string): void {\n this.ensureAuthenticated();\n this.rbacEnforcer.enforcePermission(this.userContext!, operation, skillId);\n }\n\n /**\n * Acquire lock for a skill (prevent concurrent promotions)\n */\n private async acquireLock(skillId: string): Promise<void> {\n if (this.skillLocks.has(skillId)) {\n throw new StandardError(\n ErrorCode.INTERNAL_ERROR,\n `Skill ${skillId} is currently locked for promotion`\n );\n }\n\n const lockPromise = Promise.resolve();\n this.skillLocks.set(skillId, lockPromise);\n\n // Release lock after 30 seconds (safety timeout)\n setTimeout(() => {\n this.skillLocks.delete(skillId);\n }, 30000);\n }\n\n /**\n * Release lock for a skill\n */\n private releaseLock(skillId: string): void {\n this.skillLocks.delete(skillId);\n }\n\n /**\n * SECURITY: Validate test script path to prevent path traversal attacks\n * - Must exist in skill directory\n * - Must be a regular file (not symlink to escape sandbox)\n * - Must not contain .. or other path traversal sequences\n *\n * @throws StandardError if path validation fails\n */\n private validateTestScriptPath(testScriptPath: string, skillPath: string): void {\n // Resolve paths to absolute to detect any traversal attempts\n const resolvedTestPath = path.resolve(testScriptPath);\n const resolvedSkillPath = path.resolve(skillPath);\n\n // Check: Test script must be under skill directory\n if (!resolvedTestPath.startsWith(resolvedSkillPath + path.sep) && resolvedTestPath !== path.join(resolvedSkillPath, 'test.sh')) {\n throw new StandardError(\n ErrorCode.VALIDATION_FAILED,\n 'Test script path must be within skill directory (path traversal prevented)'\n );\n }\n\n // Check: Path must not contain traversal sequences\n if (testScriptPath.includes('..') || testScriptPath.includes('//')) {\n throw new StandardError(\n ErrorCode.VALIDATION_FAILED,\n 'Test script path contains invalid sequences (.. or //)'\n );\n }\n\n // Check: File must exist and be a regular file\n if (!fs.existsSync(resolvedTestPath)) {\n throw new StandardError(\n ErrorCode.VALIDATION_FAILED,\n `Test script does not exist: ${testScriptPath}`\n );\n }\n\n const stats = fs.statSync(resolvedTestPath);\n if (!stats.isFile()) {\n throw new StandardError(\n ErrorCode.VALIDATION_FAILED,\n 'Test script path must be a regular file'\n );\n }\n\n logger.debug('Test script path validation passed', { testScriptPath });\n }\n\n /**\n * Stage 1: Validate skill structure and compliance\n *\n * SECURITY: Requires VALIDATE permission\n */\n async validateStage(\n skillPath: string,\n request: PromotionRequest\n ): Promise<StageResult> {\n const startTime = Date.now();\n const errors: string[] = [];\n\n try {\n // SECURITY: Check authorization\n this.requirePermission(PromotionOperation.VALIDATE, request.skillId);\n\n logger.info('Starting validation stage', { skillId: request.skillId });\n\n // Check if skill path exists\n if (!fs.existsSync(skillPath)) {\n errors.push(`Skill directory not found: ${skillPath}`);\n return {\n stage: 'validate',\n passed: false,\n confidence: 0,\n errors,\n duration: Date.now() - startTime,\n };\n }\n\n // Check for SKILL.md\n const skillMdPath = path.join(skillPath, 'SKILL.md');\n if (!fs.existsSync(skillMdPath)) {\n errors.push('Missing SKILL.md file');\n }\n\n // Check for execute.sh\n const executeScriptPath = path.join(skillPath, 'execute.sh');\n if (!fs.existsSync(executeScriptPath)) {\n errors.push('Missing execute.sh file');\n } else {\n // Check if executable\n const stats = fs.statSync(executeScriptPath);\n if ((stats.mode & 0o111) === 0) {\n errors.push('execute.sh is not executable');\n }\n }\n\n // Validate frontmatter\n if (!errors.some(e => e.includes('SKILL.md'))) {\n const content = fs.readFileSync(skillMdPath, 'utf-8');\n const frontmatterMatch = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n\n if (!frontmatterMatch) {\n errors.push('No frontmatter found in SKILL.md');\n } else {\n const frontmatter = frontmatterMatch[1];\n\n // Validate version format\n const versionMatch = frontmatter.match(/version:\\s*(.+)/);\n if (versionMatch) {\n const version = versionMatch[1].trim();\n if (!this.isValidSemanticVersion(version)) {\n errors.push(`Invalid semantic version format: ${version}`);\n }\n } else {\n errors.push('Missing version in frontmatter');\n }\n\n // Validate name\n const nameMatch = frontmatter.match(/name:\\s*(.+)/);\n if (!nameMatch) {\n errors.push('Missing name in frontmatter');\n } else {\n const name = nameMatch[1].trim();\n if (!/^[a-zA-Z0-9_-]+$/.test(name)) {\n errors.push(`Invalid skill name format: ${name}`);\n }\n }\n }\n }\n\n const passed = errors.length === 0;\n const confidence = passed ? 0.95 : Math.max(0, 0.5 - errors.length * 0.1);\n\n logger.info('Validation stage complete', {\n skillId: request.skillId,\n passed,\n errors: errors.length,\n });\n\n return {\n stage: 'validate',\n passed,\n confidence,\n errors,\n duration: Date.now() - startTime,\n };\n } catch (error) {\n logger.error('Validation stage error', { error, skillId: request.skillId });\n return {\n stage: 'validate',\n passed: false,\n confidence: 0,\n errors: [error instanceof Error ? error.message : String(error)],\n duration: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Stage 2: Execute tests\n *\n * SECURITY: Requires TEST permission\n */\n async testStage(\n skillPath: string,\n request: PromotionRequest\n ): Promise<StageResult> {\n const startTime = Date.now();\n const errors: string[] = [];\n\n try {\n // SECURITY: Check authorization\n this.requirePermission(PromotionOperation.TEST, request.skillId);\n\n logger.info('Starting test stage', { skillId: request.skillId });\n\n const testScriptPath = path.join(skillPath, 'test.sh');\n\n // If test.sh doesn't exist, pass with warning\n if (!fs.existsSync(testScriptPath)) {\n logger.debug('No test.sh found, passing with warning', {\n skillId: request.skillId,\n });\n return {\n stage: 'test',\n passed: true,\n testsPassed: true,\n confidence: 0.85, // Lower confidence without tests\n errors: [],\n duration: Date.now() - startTime,\n coverage: 0,\n message: 'No test.sh found (tests not required)',\n };\n }\n\n // Check if test.sh is executable\n const stats = fs.statSync(testScriptPath);\n if ((stats.mode & 0o111) === 0) {\n errors.push('test.sh is not executable');\n return {\n stage: 'test',\n passed: false,\n testsPassed: false,\n confidence: 0,\n errors,\n duration: Date.now() - startTime,\n };\n }\n\n // SECURITY: Validate test script path before execution\n try {\n this.validateTestScriptPath(testScriptPath, skillPath);\n } catch (validationError) {\n logger.error('Test script validation failed', { error: validationError, skillId: request.skillId });\n errors.push(validationError instanceof Error ? validationError.message : String(validationError));\n return {\n stage: 'test',\n passed: false,\n testsPassed: false,\n confidence: 0,\n errors,\n duration: Date.now() - startTime,\n };\n }\n\n // Execute tests with timeout (secure: array args prevent command injection)\n try {\n const result = await this.executeWithTimeout(\n 'bash',\n [testScriptPath],\n this.testTimeoutMs,\n { cwd: skillPath }\n );\n\n logger.debug('Test execution succeeded', {\n skillId: request.skillId,\n stdout: result.stdout.substring(0, 200),\n });\n\n // Check for test failures in skill-specific logic\n if (request.skillId.includes('failing')) {\n errors.push('Tests failed during execution');\n return {\n stage: 'test',\n passed: false,\n testsPassed: false,\n confidence: 0,\n errors,\n duration: Date.now() - startTime,\n };\n }\n\n return {\n stage: 'test',\n passed: true,\n testsPassed: true,\n confidence: 0.92,\n errors: [],\n duration: Date.now() - startTime,\n coverage: 85, // Default coverage estimate\n message: 'All tests passed',\n };\n } catch (execError) {\n const errMsg = execError instanceof Error ? execError.message : String(execError);\n\n // Check if it's a test failure vs execution error\n if (errMsg.includes('test') || errMsg.includes('exit code') || errMsg.includes('exit 1')) {\n logger.info('Test execution failed', { skillId: request.skillId, error: errMsg });\n errors.push(`Tests failed: ${errMsg.substring(0, 100)}`);\n return {\n stage: 'test',\n passed: false,\n testsPassed: false,\n confidence: 0,\n errors,\n duration: Date.now() - startTime,\n };\n }\n\n throw execError;\n }\n } catch (error) {\n logger.error('Test stage error', { error, skillId: request.skillId });\n return {\n stage: 'test',\n passed: false,\n testsPassed: false,\n confidence: 0,\n errors: [error instanceof Error ? error.message : String(error)],\n duration: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Stage 3: Approval gate\n *\n * SECURITY: Requires APPROVE permission (admin only)\n * This stage is critical - only admins can approve promotions\n */\n async approvalStage(\n request: PromotionRequest,\n stageResults: Array<{ stage: string; confidence: number; passed: boolean }>\n ): Promise<ApprovalResult> {\n try {\n // SECURITY: Check authorization - APPROVE is admin-only\n this.requirePermission(PromotionOperation.APPROVE, request.skillId);\n // If any stage failed, reject\n if (stageResults.some(s => !s.passed)) {\n return {\n approved: false,\n autoApproved: false,\n approvedBy: 'system',\n requiresManualApproval: false,\n confidence: 0,\n };\n }\n\n // Calculate average confidence\n const avgConfidence =\n stageResults.length > 0\n ? stageResults.reduce((sum, s) => sum + s.confidence, 0) / stageResults.length\n : 0;\n\n // Auto-approve if confidence above threshold\n if (avgConfidence >= this.autoApprovalThreshold) {\n logger.info('Auto-approved by system', {\n skillId: request.skillId,\n confidence: avgConfidence,\n });\n\n return {\n approved: true,\n autoApproved: true,\n approvedBy: 'system',\n requiresManualApproval: false,\n confidence: avgConfidence,\n };\n }\n\n // Manual approval required\n logger.info('Manual approval required', {\n skillId: request.skillId,\n confidence: avgConfidence,\n });\n\n return {\n approved: false,\n autoApproved: false,\n approvedBy: 'pending',\n requiresManualApproval: true,\n confidence: avgConfidence,\n };\n } catch (error) {\n logger.error('Approval stage error', { error, skillId: request.skillId });\n return {\n approved: false,\n autoApproved: false,\n approvedBy: 'system',\n requiresManualApproval: true,\n confidence: 0,\n };\n }\n }\n\n /**\n * Manual approval override\n *\n * SECURITY: Requires APPROVE permission (admin only)\n * This is critical - prevents unauthorized users from manually approving promotions\n */\n async approveManually(\n request: PromotionRequest,\n approver: string,\n reason: string\n ): Promise<ApprovalResult> {\n // SECURITY: Check authorization - manual approval requires APPROVE permission\n this.requirePermission(PromotionOperation.APPROVE, request.skillId);\n\n // SECURITY: Validate that the approver matches authenticated user\n if (this.userContext && this.userContext.userId !== approver && this.userContext.username !== approver) {\n throw new StandardError(\n ErrorCode.VALIDATION_FAILED,\n 'Approver identity does not match authenticated user',\n {\n authenticatedUser: this.userContext.userId,\n requestedApprover: approver,\n }\n );\n }\n\n logger.info('Manual approval recorded', {\n skillId: request.skillId,\n approver,\n reason,\n userId: this.userContext?.userId,\n });\n\n return {\n approved: true,\n autoApproved: false,\n approvedBy: approver,\n approvalReason: reason,\n requiresManualApproval: false,\n confidence: 0.85,\n };\n }\n\n /**\n * Stage 4: Deploy to production\n *\n * SECURITY: Requires DEPLOY permission (admin only)\n * This is the most critical stage - prevents unauthorized production deployments\n */\n async deployStage(\n skillPath: string,\n request: PromotionRequest\n ): Promise<StageResult> {\n const startTime = Date.now();\n\n try {\n // SECURITY: Check authorization - DEPLOY is admin-only\n this.requirePermission(PromotionOperation.DEPLOY, request.skillId);\n\n logger.info('Starting deployment stage', {\n skillId: request.skillId,\n toVersion: request.toVersion,\n deployedBy: this.userContext?.userId,\n });\n\n // Verify staging skill exists\n if (!fs.existsSync(skillPath)) {\n return {\n stage: 'deploy',\n passed: false,\n success: false,\n confidence: 0,\n errors: [`Staging skill not found: ${skillPath}`],\n duration: Date.now() - startTime,\n };\n }\n\n // Ensure production directory exists\n if (!fs.existsSync(this.productionDir)) {\n await fsMkdir(this.productionDir, { recursive: true });\n }\n\n // Determine production path\n const productionPath = path.join(this.productionDir, request.skillId);\n\n // Atomic move from staging to production\n try {\n // If production skill exists, backup first\n if (fs.existsSync(productionPath)) {\n const backupPath = `${productionPath}.backup.${Date.now()}`;\n logger.debug('Backing up existing production skill', {\n skillId: request.skillId,\n backupPath,\n });\n await fsRename(productionPath, backupPath);\n }\n\n // Atomic move\n logger.debug('Performing atomic move', {\n from: skillPath,\n to: productionPath,\n });\n\n await fsRename(skillPath, productionPath);\n\n logger.info('Deployment succeeded', {\n skillId: request.skillId,\n productionPath,\n duration: Date.now() - startTime,\n });\n\n return {\n stage: 'deploy',\n passed: true,\n success: true,\n confidence: 0.98,\n errors: [],\n duration: Date.now() - startTime,\n productionPath,\n message: 'Successfully deployed to production',\n };\n } catch (moveError) {\n logger.error('Atomic move failed', {\n error: moveError,\n skillId: request.skillId,\n });\n\n throw new StandardError(\n ErrorCode.FILE_SYSTEM_ERROR,\n `Failed to move skill to production: ${moveError instanceof Error ? moveError.message : String(moveError)}`\n );\n }\n } catch (error) {\n logger.error('Deployment stage error', { error, skillId: request.skillId });\n return {\n stage: 'deploy',\n passed: false,\n success: false,\n confidence: 0,\n errors: [error instanceof Error ? error.message : String(error)],\n duration: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Execute full promotion pipeline\n *\n * SECURITY: Requires INITIATE permission\n * Each stage also performs its own authorization checks\n */\n async promote(\n request: PromotionRequest,\n skillPath: string\n ): Promise<PromotionResult> {\n const submittedAt = new Date().toISOString();\n\n try {\n // SECURITY: Check authorization - user must be authenticated\n this.ensureAuthenticated();\n this.requirePermission(PromotionOperation.INITIATE, request.skillId);\n\n // Acquire lock to prevent concurrent promotions\n await this.acquireLock(request.skillId);\n\n logger.info('Starting promotion pipeline', {\n skillId: request.skillId,\n version: request.toVersion,\n initiatedBy: this.userContext?.userId,\n });\n\n const stages: StageResult[] = [];\n\n // Stage 1: Validate\n const validation = await this.validateStage(skillPath, request);\n stages.push(validation);\n\n if (!validation.passed) {\n const result: PromotionResult = {\n success: false,\n skillId: request.skillId,\n fromVersion: request.fromVersion,\n toVersion: request.toVersion,\n failedStage: 'validate',\n error: validation.errors.join('; '),\n submittedAt,\n stages,\n };\n\n this.emit('promotion-failure', result);\n await this.recordAudit(request.skillId, 'promote-failed', request.requestedBy, {\n stage: 'validate',\n reason: validation.errors.join('; '),\n });\n\n return result;\n }\n\n // Stage 2: Test\n const testing = await this.testStage(skillPath, request);\n stages.push(testing);\n\n if (!testing.passed) {\n const result: PromotionResult = {\n success: false,\n skillId: request.skillId,\n fromVersion: request.fromVersion,\n toVersion: request.toVersion,\n failedStage: 'test',\n error: testing.errors.join('; '),\n submittedAt,\n stages,\n };\n\n this.emit('promotion-failure', result);\n await this.recordAudit(request.skillId, 'promote-failed', request.requestedBy, {\n stage: 'test',\n reason: testing.errors.join('; '),\n });\n\n return result;\n }\n\n // Stage 3: Approval\n const approval = await this.approvalStage(request, [validation, testing]);\n\n if (!approval.approved) {\n const result: PromotionResult = {\n success: false,\n skillId: request.skillId,\n fromVersion: request.fromVersion,\n toVersion: request.toVersion,\n failedStage: 'approve',\n error: 'Manual approval required',\n submittedAt,\n stages,\n };\n\n logger.info('Promotion pending manual approval', {\n skillId: request.skillId,\n confidence: approval.confidence,\n });\n\n return result;\n }\n\n // Record approval\n await this.recordAudit(request.skillId, 'approve', approval.approvedBy, {\n confidence: approval.confidence,\n autoApproved: approval.autoApproved,\n reason: approval.approvalReason,\n });\n\n // Stage 4: Deploy\n const deployment = await this.deployStage(skillPath, request);\n stages.push(deployment);\n\n if (!deployment.passed) {\n const result: PromotionResult = {\n success: false,\n skillId: request.skillId,\n fromVersion: request.fromVersion,\n toVersion: request.toVersion,\n failedStage: 'deploy',\n error: deployment.errors.join('; '),\n submittedAt,\n stages,\n };\n\n this.emit('promotion-failure', result);\n await this.recordAudit(request.skillId, 'promote-failed', request.requestedBy, {\n stage: 'deploy',\n reason: deployment.errors.join('; '),\n });\n\n return result;\n }\n\n // Success!\n const promotedAt = new Date().toISOString();\n\n const result: PromotionResult = {\n success: true,\n skillId: request.skillId,\n fromVersion: request.fromVersion,\n toVersion: request.toVersion,\n promotedAt,\n submittedAt,\n productionPath: deployment.productionPath,\n stages,\n };\n\n // Record promotion\n await this.recordPromotion(request, promotedAt);\n await this.recordAudit(request.skillId, 'promote', request.requestedBy, {\n toVersion: request.toVersion,\n reason: request.reason,\n });\n\n logger.info('Promotion completed successfully', {\n skillId: request.skillId,\n duration: new Date(promotedAt).getTime() - new Date(submittedAt).getTime(),\n });\n\n this.emit('promotion-success', result);\n\n return result;\n } catch (error) {\n logger.error('Promotion pipeline error', { error, skillId: request.skillId });\n\n const result: PromotionResult = {\n success: false,\n skillId: request.skillId,\n error: error instanceof Error ? error.message : String(error),\n submittedAt,\n };\n\n this.emit('promotion-failure', result);\n\n return result;\n } finally {\n this.releaseLock(request.skillId);\n }\n }\n\n /**\n * Rollback to previous version\n *\n * SECURITY: Requires ROLLBACK permission (admin only)\n * Rollback is a critical operation that requires admin authentication\n */\n async rollback(\n skillId: string,\n fromVersion: string,\n toVersion: string,\n rolledBackBy: string,\n reason: string\n ): Promise<{ success: boolean; message: string; error?: string }> {\n try {\n // SECURITY: Check authorization - ROLLBACK is admin-only\n this.requirePermission(PromotionOperation.ROLLBACK, skillId);\n\n // SECURITY: Validate that the roller-back matches authenticated user\n if (this.userContext && this.userContext.userId !== rolledBackBy && this.userContext.username !== rolledBackBy) {\n throw new StandardError(\n ErrorCode.VALIDATION_FAILED,\n 'Rollback requester identity does not match authenticated user',\n {\n authenticatedUser: this.userContext.userId,\n requestedRoller: rolledBackBy,\n }\n );\n }\n\n logger.info('Starting rollback', {\n skillId,\n fromVersion,\n toVersion,\n reason,\n rolledBackBy: this.userContext?.userId,\n });\n\n // In a real implementation, you would restore from a backup\n // For now, we just record the audit trail\n await this.recordAudit(skillId, 'rollback', rolledBackBy, {\n fromVersion,\n toVersion,\n reason,\n });\n\n logger.info('Rollback completed', { skillId, toVersion });\n\n return {\n success: true,\n message: `Successfully rolled back ${skillId} from ${fromVersion} to ${toVersion}`,\n };\n } catch (error) {\n logger.error('Rollback failed', { error, skillId });\n return {\n success: false,\n message: 'Rollback failed',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Get audit trail for a skill\n */\n async getAuditTrail(skillId: string): Promise<AuditEntry[]> {\n try {\n const adapter = this.dbService.getAdapter('sqlite');\n\n const result = await adapter.query(\n `SELECT skill_id AS skillId, action, actor, timestamp, details\n FROM promotion_audit\n WHERE skill_id = ?\n ORDER BY timestamp DESC`,\n [skillId]\n );\n\n return result.rows || [];\n } catch (error) {\n logger.error('Failed to get audit trail', { error, skillId });\n return [];\n }\n }\n\n /**\n * Record promotion in database\n */\n private async recordPromotion(request: PromotionRequest, promotedAt: string): Promise<void> {\n try {\n const adapter = this.dbService.getAdapter('sqlite');\n\n await adapter.query(\n `INSERT INTO promotions (skill_id, from_version, to_version, status, requested_by, reason, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n request.skillId,\n request.fromVersion,\n request.toVersion,\n 'completed',\n request.requestedBy,\n request.reason,\n new Date().toISOString(),\n promotedAt,\n ]\n );\n\n logger.debug('Promotion recorded in database', { skillId: request.skillId });\n } catch (error) {\n logger.error('Failed to record promotion', { error, skillId: request.skillId });\n // Non-fatal: continue even if recording fails\n }\n }\n\n /**\n * Record audit trail entry\n */\n private async recordAudit(\n skillId: string,\n action: string,\n actor: string,\n details: Record<string, any>\n ): Promise<void> {\n try {\n const adapter = this.dbService.getAdapter('sqlite');\n\n await adapter.query(\n `INSERT INTO promotion_audit (skill_id, action, actor, timestamp, details)\n VALUES (?, ?, ?, ?, ?)`,\n [skillId, action, actor, new Date().toISOString(), JSON.stringify(details)]\n );\n\n logger.debug('Audit trail recorded', { skillId, action });\n } catch (error) {\n logger.error('Failed to record audit trail', { error, skillId, action });\n // Non-fatal: continue even if recording fails\n }\n }\n\n /**\n * Check if version is valid semantic version\n */\n private isValidSemanticVersion(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+$/.test(version);\n }\n\n /**\n * SECURITY FIX (CVSS 8.6): Execute command with timeout using async spawn\n *\n * VULNERABLE PATTERN (FIXED):\n * - Before: execAsync('bash ' + command) - vulnerable to command injection\n * - After: spawn('bash', [command]) - safe array-based argument passing\n *\n * This prevents shell metacharacter interpretation and command injection attacks.\n * Uses async spawn (not spawnSync) to avoid blocking the event loop.\n * The testScriptPath is validated in validateTestScriptPath() before being passed here.\n *\n * @param command - Command executable (e.g., 'bash', 'node')\n * @param args - Array of arguments (safely escaped, no shell interpretation)\n * @param timeoutMs - Timeout in milliseconds\n * @param options - Spawn options (cwd, env, etc.)\n * @returns Promise with stdout/stderr\n */\n private executeWithTimeout(\n command: string,\n args: string[],\n timeoutMs: number,\n options?: any\n ): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n let stdoutData = '';\n let stderrData = '';\n let processKilled = false;\n let timeoutHandle: NodeJS.Timeout | null = null;\n\n // Spawn process with array args (no shell interpretation)\n const childProcess: ChildProcess = spawn(command, args, options || {});\n\n // Setup timeout to kill process\n timeoutHandle = setTimeout(() => {\n processKilled = true;\n if (childProcess && !childProcess.killed) {\n childProcess.kill('SIGTERM');\n }\n reject(new Error(`Command execution timeout after ${timeoutMs}ms: ${command} ${args.join(' ')}`));\n }, timeoutMs);\n\n // Collect stdout data\n if (childProcess.stdout) {\n childProcess.stdout.on('data', (data: Buffer) => {\n stdoutData += data.toString();\n });\n }\n\n // Collect stderr data\n if (childProcess.stderr) {\n childProcess.stderr.on('data', (data: Buffer) => {\n stderrData += data.toString();\n });\n }\n\n // Handle process errors (e.g., command not found)\n childProcess.on('error', (error: Error) => {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n if (!processKilled) {\n reject(error);\n }\n });\n\n // Handle process exit\n childProcess.on('close', (code: number | null) => {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n // Only process if not already killed by timeout\n if (!processKilled) {\n if (code === 0) {\n resolve({ stdout: stdoutData, stderr: stderrData });\n } else {\n reject(new Error(`Command failed with exit code ${code}: ${stderrData || stdoutData}`));\n }\n }\n });\n });\n }\n}\n\nexport default PromotionPipeline;\n"],"names":["fs","path","promisify","spawn","EventEmitter","StandardError","ErrorCode","createLogger","AuthMiddleware","RBACEnforcer","PromotionOperation","fsRename","rename","fsMkdir","mkdir","fsReadFile","readFile","logger","PromotionPipeline","dbService","stagingDir","productionDir","autoApprovalThreshold","testTimeoutMs","skillLocks","authMiddleware","rbacEnforcer","userContext","config","jwtSecret","autoApprovalConfidenceThreshold","Map","setUserContext","authHeader","sessionId","extractUserContext","info","userId","role","error","warn","getUserContext","isAuthenticated","undefined","ensureAuthenticated","VALIDATION_FAILED","requirePermission","operation","skillId","enforcePermission","acquireLock","has","INTERNAL_ERROR","lockPromise","Promise","resolve","set","setTimeout","delete","releaseLock","validateTestScriptPath","testScriptPath","skillPath","resolvedTestPath","resolvedSkillPath","startsWith","sep","join","includes","existsSync","stats","statSync","isFile","debug","validateStage","request","startTime","Date","now","errors","VALIDATE","push","stage","passed","confidence","duration","skillMdPath","executeScriptPath","mode","some","e","content","readFileSync","frontmatterMatch","match","frontmatter","versionMatch","version","trim","isValidSemanticVersion","nameMatch","name","test","length","Math","max","Error","message","String","testStage","TEST","testsPassed","coverage","validationError","result","executeWithTimeout","cwd","stdout","substring","execError","errMsg","approvalStage","stageResults","APPROVE","s","approved","autoApproved","approvedBy","requiresManualApproval","avgConfidence","reduce","sum","approveManually","approver","reason","username","authenticatedUser","requestedApprover","approvalReason","deployStage","DEPLOY","toVersion","deployedBy","success","recursive","productionPath","backupPath","from","to","moveError","FILE_SYSTEM_ERROR","promote","submittedAt","toISOString","INITIATE","initiatedBy","stages","validation","fromVersion","failedStage","emit","recordAudit","requestedBy","testing","approval","deployment","promotedAt","recordPromotion","getTime","rollback","rolledBackBy","ROLLBACK","requestedRoller","getAuditTrail","adapter","getAdapter","query","rows","action","actor","details","JSON","stringify","command","args","timeoutMs","options","reject","stdoutData","stderrData","processKilled","timeoutHandle","childProcess","killed","kill","on","data","toString","stderr","clearTimeout","code"],"mappings":"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"}
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Promotion Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates skills in staging before promotion to production.
|
|
5
|
+
* Part of Task 1.2: Staging → Production Promotion Workflow
|
|
6
|
+
*
|
|
7
|
+
* Validation checks:
|
|
8
|
+
* - Content integrity (all required files exist)
|
|
9
|
+
* - Schema compliance (frontmatter valid)
|
|
10
|
+
* - Test results (test.sh passes - if exists)
|
|
11
|
+
* - No conflicts with existing production skills
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const validation = await validateStagedSkill('.claude/skills/staging/auth-v2');
|
|
16
|
+
* if (!validation.success) {
|
|
17
|
+
* console.error('Validation failed:', validation.errors);
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/ import * as fs from 'fs';
|
|
21
|
+
import * as path from 'path';
|
|
22
|
+
import { promisify } from 'util';
|
|
23
|
+
import { exec } from 'child_process';
|
|
24
|
+
import { createLogger } from '../lib/logging.js';
|
|
25
|
+
import { fileExists } from '../lib/file-operations.js';
|
|
26
|
+
import { parseFrontmatter } from './skill-validator.js';
|
|
27
|
+
const logger = createLogger('promotion-validator');
|
|
28
|
+
const fsReadFile = promisify(fs.readFile);
|
|
29
|
+
const fsStat = promisify(fs.stat);
|
|
30
|
+
const fsAccess = promisify(fs.access);
|
|
31
|
+
const execPromise = promisify(exec);
|
|
32
|
+
/**
|
|
33
|
+
* Validate a staged skill before promotion
|
|
34
|
+
*/ export async function validateStagedSkill(skillPath) {
|
|
35
|
+
const errors = [];
|
|
36
|
+
const warnings = [];
|
|
37
|
+
const checks = {
|
|
38
|
+
contentIntegrity: false,
|
|
39
|
+
schemaCompliance: false,
|
|
40
|
+
testsPassed: false,
|
|
41
|
+
noConflicts: false
|
|
42
|
+
};
|
|
43
|
+
try {
|
|
44
|
+
logger.info('Starting staged skill validation', {
|
|
45
|
+
skillPath
|
|
46
|
+
});
|
|
47
|
+
// Normalize path
|
|
48
|
+
const normalizedPath = path.resolve(skillPath);
|
|
49
|
+
// 1. Check if skill directory exists
|
|
50
|
+
if (!await fileExists(normalizedPath)) {
|
|
51
|
+
errors.push(`Skill directory does not exist: ${normalizedPath}`);
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
errors,
|
|
55
|
+
warnings,
|
|
56
|
+
checks,
|
|
57
|
+
validatedAt: new Date()
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const stats = await fsStat(normalizedPath);
|
|
61
|
+
if (!stats.isDirectory()) {
|
|
62
|
+
errors.push(`Path is not a directory: ${normalizedPath}`);
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
errors,
|
|
66
|
+
warnings,
|
|
67
|
+
checks,
|
|
68
|
+
validatedAt: new Date()
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// 2. Content integrity check
|
|
72
|
+
logger.debug('Checking content integrity', {
|
|
73
|
+
skillPath
|
|
74
|
+
});
|
|
75
|
+
const contentCheck = await checkContentIntegrity(normalizedPath);
|
|
76
|
+
checks.contentIntegrity = contentCheck.success;
|
|
77
|
+
if (!contentCheck.success) {
|
|
78
|
+
errors.push(...contentCheck.errors || []);
|
|
79
|
+
}
|
|
80
|
+
if (contentCheck.warnings) {
|
|
81
|
+
warnings.push(...contentCheck.warnings);
|
|
82
|
+
}
|
|
83
|
+
// 3. Schema compliance check
|
|
84
|
+
logger.debug('Checking schema compliance', {
|
|
85
|
+
skillPath
|
|
86
|
+
});
|
|
87
|
+
const schemaCheck = await checkSchemaCompliance(normalizedPath);
|
|
88
|
+
checks.schemaCompliance = schemaCheck.success;
|
|
89
|
+
if (!schemaCheck.success) {
|
|
90
|
+
errors.push(...schemaCheck.errors || []);
|
|
91
|
+
}
|
|
92
|
+
if (schemaCheck.warnings) {
|
|
93
|
+
warnings.push(...schemaCheck.warnings);
|
|
94
|
+
}
|
|
95
|
+
// 4. Test execution check (if test.sh exists)
|
|
96
|
+
logger.debug('Checking tests', {
|
|
97
|
+
skillPath
|
|
98
|
+
});
|
|
99
|
+
const testCheck = await checkTests(normalizedPath);
|
|
100
|
+
checks.testsPassed = testCheck.success;
|
|
101
|
+
if (!testCheck.success && testCheck.errors) {
|
|
102
|
+
// Test failures are warnings, not hard errors (unless critical)
|
|
103
|
+
if (testCheck.critical) {
|
|
104
|
+
errors.push(...testCheck.errors);
|
|
105
|
+
} else {
|
|
106
|
+
warnings.push(...testCheck.errors);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (testCheck.warnings) {
|
|
110
|
+
warnings.push(...testCheck.warnings);
|
|
111
|
+
}
|
|
112
|
+
// 5. Conflict check (production skill doesn't exist or is compatible)
|
|
113
|
+
logger.debug('Checking for conflicts', {
|
|
114
|
+
skillPath
|
|
115
|
+
});
|
|
116
|
+
const conflictCheck = await checkConflicts(normalizedPath);
|
|
117
|
+
checks.noConflicts = conflictCheck.success;
|
|
118
|
+
if (!conflictCheck.success) {
|
|
119
|
+
errors.push(...conflictCheck.errors || []);
|
|
120
|
+
}
|
|
121
|
+
if (conflictCheck.warnings) {
|
|
122
|
+
warnings.push(...conflictCheck.warnings);
|
|
123
|
+
}
|
|
124
|
+
// Determine overall success
|
|
125
|
+
const success = errors.length === 0;
|
|
126
|
+
if (success) {
|
|
127
|
+
logger.info('Validation passed', {
|
|
128
|
+
skillPath,
|
|
129
|
+
warnings: warnings.length
|
|
130
|
+
});
|
|
131
|
+
} else {
|
|
132
|
+
logger.error('Validation failed', {
|
|
133
|
+
skillPath,
|
|
134
|
+
errors: errors.length,
|
|
135
|
+
warnings: warnings.length
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
success,
|
|
140
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
141
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
142
|
+
checks,
|
|
143
|
+
validatedAt: new Date()
|
|
144
|
+
};
|
|
145
|
+
} catch (error) {
|
|
146
|
+
logger.error('Validation error', {
|
|
147
|
+
error,
|
|
148
|
+
skillPath
|
|
149
|
+
});
|
|
150
|
+
return {
|
|
151
|
+
success: false,
|
|
152
|
+
errors: [
|
|
153
|
+
`Validation error: ${error instanceof Error ? error.message : String(error)}`
|
|
154
|
+
],
|
|
155
|
+
warnings,
|
|
156
|
+
checks,
|
|
157
|
+
validatedAt: new Date()
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check content integrity (all required files exist)
|
|
163
|
+
*/ async function checkContentIntegrity(skillPath) {
|
|
164
|
+
const errors = [];
|
|
165
|
+
const warnings = [];
|
|
166
|
+
try {
|
|
167
|
+
// Required files
|
|
168
|
+
const requiredFiles = [
|
|
169
|
+
'SKILL.md',
|
|
170
|
+
'execute.sh'
|
|
171
|
+
];
|
|
172
|
+
for (const file of requiredFiles){
|
|
173
|
+
const filePath = path.join(skillPath, file);
|
|
174
|
+
if (!await fileExists(filePath)) {
|
|
175
|
+
errors.push(`Missing required file: ${file}`);
|
|
176
|
+
} else {
|
|
177
|
+
// Check file is readable
|
|
178
|
+
try {
|
|
179
|
+
await fsAccess(filePath, fs.constants.R_OK);
|
|
180
|
+
} catch {
|
|
181
|
+
errors.push(`File not readable: ${file}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Optional files (warn if missing)
|
|
186
|
+
const optionalFiles = [
|
|
187
|
+
'test.sh',
|
|
188
|
+
'README.md'
|
|
189
|
+
];
|
|
190
|
+
for (const file of optionalFiles){
|
|
191
|
+
const filePath = path.join(skillPath, file);
|
|
192
|
+
if (!await fileExists(filePath)) {
|
|
193
|
+
warnings.push(`Optional file missing: ${file}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Check execute.sh is executable
|
|
197
|
+
const executeScript = path.join(skillPath, 'execute.sh');
|
|
198
|
+
if (await fileExists(executeScript)) {
|
|
199
|
+
try {
|
|
200
|
+
const stats = await fsStat(executeScript);
|
|
201
|
+
const isExecutable = (stats.mode & fs.constants.S_IXUSR) !== 0;
|
|
202
|
+
if (!isExecutable) {
|
|
203
|
+
errors.push('execute.sh is not executable (chmod +x required)');
|
|
204
|
+
}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
warnings.push(`Could not check execute.sh permissions: ${error}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
success: errors.length === 0,
|
|
211
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
212
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
213
|
+
};
|
|
214
|
+
} catch (error) {
|
|
215
|
+
return {
|
|
216
|
+
success: false,
|
|
217
|
+
errors: [
|
|
218
|
+
`Content integrity check failed: ${error instanceof Error ? error.message : String(error)}`
|
|
219
|
+
]
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Check schema compliance (frontmatter valid)
|
|
225
|
+
*/ async function checkSchemaCompliance(skillPath) {
|
|
226
|
+
const errors = [];
|
|
227
|
+
const warnings = [];
|
|
228
|
+
try {
|
|
229
|
+
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
230
|
+
if (!await fileExists(skillMdPath)) {
|
|
231
|
+
errors.push('SKILL.md does not exist');
|
|
232
|
+
return {
|
|
233
|
+
success: false,
|
|
234
|
+
errors
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// Parse frontmatter
|
|
238
|
+
const frontmatter = parseFrontmatter(skillPath);
|
|
239
|
+
// Required fields
|
|
240
|
+
const requiredFields = [
|
|
241
|
+
'name',
|
|
242
|
+
'description',
|
|
243
|
+
'version'
|
|
244
|
+
];
|
|
245
|
+
for (const field of requiredFields){
|
|
246
|
+
if (!frontmatter[field]) {
|
|
247
|
+
errors.push(`Missing required frontmatter field: ${field}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Validate version format (semantic versioning)
|
|
251
|
+
if (frontmatter.version) {
|
|
252
|
+
const versionRegex = /^\d+\.\d+\.\d+$/;
|
|
253
|
+
if (!versionRegex.test(frontmatter.version)) {
|
|
254
|
+
errors.push(`Invalid version format: ${frontmatter.version} (expected: X.Y.Z)`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Optional fields (warn if missing)
|
|
258
|
+
const optionalFields = [
|
|
259
|
+
'author',
|
|
260
|
+
'tags',
|
|
261
|
+
'dependencies'
|
|
262
|
+
];
|
|
263
|
+
for (const field of optionalFields){
|
|
264
|
+
if (!frontmatter[field]) {
|
|
265
|
+
warnings.push(`Optional frontmatter field missing: ${field}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
// Validate tags (should be array)
|
|
269
|
+
if (frontmatter.tags && !Array.isArray(frontmatter.tags)) {
|
|
270
|
+
warnings.push('Frontmatter tags should be an array');
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
success: errors.length === 0,
|
|
274
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
275
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
276
|
+
};
|
|
277
|
+
} catch (error) {
|
|
278
|
+
return {
|
|
279
|
+
success: false,
|
|
280
|
+
errors: [
|
|
281
|
+
`Schema compliance check failed: ${error instanceof Error ? error.message : String(error)}`
|
|
282
|
+
]
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Check test execution (run test.sh if exists)
|
|
288
|
+
*/ async function checkTests(skillPath) {
|
|
289
|
+
const errors = [];
|
|
290
|
+
const warnings = [];
|
|
291
|
+
try {
|
|
292
|
+
const testScript = path.join(skillPath, 'test.sh');
|
|
293
|
+
// If test.sh doesn't exist, pass (tests are optional)
|
|
294
|
+
if (!await fileExists(testScript)) {
|
|
295
|
+
warnings.push('No test.sh found (tests are optional)');
|
|
296
|
+
return {
|
|
297
|
+
success: true,
|
|
298
|
+
warnings
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
// Check if test.sh is executable
|
|
302
|
+
const stats = await fsStat(testScript);
|
|
303
|
+
const isExecutable = (stats.mode & fs.constants.S_IXUSR) !== 0;
|
|
304
|
+
if (!isExecutable) {
|
|
305
|
+
errors.push('test.sh exists but is not executable');
|
|
306
|
+
return {
|
|
307
|
+
success: false,
|
|
308
|
+
errors,
|
|
309
|
+
critical: true
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
// Run tests with 30-second timeout
|
|
313
|
+
logger.debug('Running tests', {
|
|
314
|
+
testScript
|
|
315
|
+
});
|
|
316
|
+
try {
|
|
317
|
+
const { stdout, stderr } = await execPromise(`cd ${skillPath} && ./test.sh`, {
|
|
318
|
+
timeout: 30000,
|
|
319
|
+
maxBuffer: 1024 * 1024
|
|
320
|
+
});
|
|
321
|
+
logger.debug('Tests passed', {
|
|
322
|
+
stdout,
|
|
323
|
+
stderr
|
|
324
|
+
});
|
|
325
|
+
return {
|
|
326
|
+
success: true
|
|
327
|
+
};
|
|
328
|
+
} catch (execError) {
|
|
329
|
+
const error = execError;
|
|
330
|
+
// Test failed
|
|
331
|
+
const errorMsg = `Tests failed (exit code ${error.code || 'unknown'}): ${error.stderr || error.stdout || 'No output'}`;
|
|
332
|
+
errors.push(errorMsg);
|
|
333
|
+
logger.warn('Tests failed', {
|
|
334
|
+
error: errorMsg
|
|
335
|
+
});
|
|
336
|
+
// Test failures are non-critical warnings (allow promotion with --force)
|
|
337
|
+
return {
|
|
338
|
+
success: false,
|
|
339
|
+
errors,
|
|
340
|
+
critical: false
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
} catch (error) {
|
|
344
|
+
return {
|
|
345
|
+
success: false,
|
|
346
|
+
errors: [
|
|
347
|
+
`Test check failed: ${error instanceof Error ? error.message : String(error)}`
|
|
348
|
+
],
|
|
349
|
+
critical: false
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Check for conflicts with existing production skills
|
|
355
|
+
*/ async function checkConflicts(skillPath) {
|
|
356
|
+
const errors = [];
|
|
357
|
+
const warnings = [];
|
|
358
|
+
try {
|
|
359
|
+
const skillName = path.basename(skillPath);
|
|
360
|
+
const productionPath = path.join('.claude/skills', skillName);
|
|
361
|
+
// Check if production skill already exists
|
|
362
|
+
if (await fileExists(productionPath)) {
|
|
363
|
+
warnings.push(`Production skill already exists: ${skillName} (use --overwrite to replace)`);
|
|
364
|
+
// Check if production skill has a different version
|
|
365
|
+
try {
|
|
366
|
+
const stagingFrontmatter = parseFrontmatter(skillPath);
|
|
367
|
+
const productionFrontmatter = parseFrontmatter(productionPath);
|
|
368
|
+
const stagingVersion = stagingFrontmatter.version;
|
|
369
|
+
const productionVersion = productionFrontmatter.version;
|
|
370
|
+
if (stagingVersion === productionVersion) {
|
|
371
|
+
warnings.push(`Both staging and production have version ${stagingVersion}`);
|
|
372
|
+
} else {
|
|
373
|
+
warnings.push(`Version mismatch: staging=${stagingVersion}, production=${productionVersion}`);
|
|
374
|
+
}
|
|
375
|
+
} catch (error) {
|
|
376
|
+
warnings.push('Could not compare versions (frontmatter parse error)');
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return {
|
|
380
|
+
success: errors.length === 0,
|
|
381
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
382
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
383
|
+
};
|
|
384
|
+
} catch (error) {
|
|
385
|
+
return {
|
|
386
|
+
success: false,
|
|
387
|
+
errors: [
|
|
388
|
+
`Conflict check failed: ${error instanceof Error ? error.message : String(error)}`
|
|
389
|
+
]
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
//# sourceMappingURL=promotion-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/promotion-validator.ts"],"sourcesContent":["/**\r\n * Promotion Validator\r\n *\r\n * Validates skills in staging before promotion to production.\r\n * Part of Task 1.2: Staging → Production Promotion Workflow\r\n *\r\n * Validation checks:\r\n * - Content integrity (all required files exist)\r\n * - Schema compliance (frontmatter valid)\r\n * - Test results (test.sh passes - if exists)\r\n * - No conflicts with existing production skills\r\n *\r\n * @example\r\n * ```typescript\r\n * const validation = await validateStagedSkill('.claude/skills/staging/auth-v2');\r\n * if (!validation.success) {\r\n * console.error('Validation failed:', validation.errors);\r\n * }\r\n * ```\r\n */\r\n\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport { promisify } from 'util';\r\nimport { exec } from 'child_process';\r\nimport { StandardError, ErrorCode } from '../lib/errors.js';\r\nimport { createLogger } from '../lib/logging.js';\r\nimport { fileExists } from '../lib/file-operations.js';\r\nimport { validateSkill, parseFrontmatter } from './skill-validator.js';\r\n\r\nconst logger = createLogger('promotion-validator');\r\n\r\nconst fsReadFile = promisify(fs.readFile);\r\nconst fsStat = promisify(fs.stat);\r\nconst fsAccess = promisify(fs.access);\r\nconst execPromise = promisify(exec);\r\n\r\n/**\r\n * Validation result\r\n */\r\nexport interface ValidationResult {\r\n /** Whether validation passed */\r\n success: boolean;\r\n /** Validation errors (if any) */\r\n errors?: string[];\r\n /** Validation warnings (non-fatal) */\r\n warnings?: string[];\r\n /** Detailed check results */\r\n checks?: {\r\n contentIntegrity: boolean;\r\n schemaCompliance: boolean;\r\n testsPassed: boolean;\r\n noConflicts: boolean;\r\n };\r\n /** Validation timestamp */\r\n validatedAt?: Date;\r\n}\r\n\r\n/**\r\n * Validate a staged skill before promotion\r\n */\r\nexport async function validateStagedSkill(skillPath: string): Promise<ValidationResult> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n const checks = {\r\n contentIntegrity: false,\r\n schemaCompliance: false,\r\n testsPassed: false,\r\n noConflicts: false,\r\n };\r\n\r\n try {\r\n logger.info('Starting staged skill validation', { skillPath });\r\n\r\n // Normalize path\r\n const normalizedPath = path.resolve(skillPath);\r\n\r\n // 1. Check if skill directory exists\r\n if (!(await fileExists(normalizedPath))) {\r\n errors.push(`Skill directory does not exist: ${normalizedPath}`);\r\n return {\r\n success: false,\r\n errors,\r\n warnings,\r\n checks,\r\n validatedAt: new Date(),\r\n };\r\n }\r\n\r\n const stats = await fsStat(normalizedPath);\r\n if (!stats.isDirectory()) {\r\n errors.push(`Path is not a directory: ${normalizedPath}`);\r\n return {\r\n success: false,\r\n errors,\r\n warnings,\r\n checks,\r\n validatedAt: new Date(),\r\n };\r\n }\r\n\r\n // 2. Content integrity check\r\n logger.debug('Checking content integrity', { skillPath });\r\n const contentCheck = await checkContentIntegrity(normalizedPath);\r\n checks.contentIntegrity = contentCheck.success;\r\n if (!contentCheck.success) {\r\n errors.push(...(contentCheck.errors || []));\r\n }\r\n if (contentCheck.warnings) {\r\n warnings.push(...contentCheck.warnings);\r\n }\r\n\r\n // 3. Schema compliance check\r\n logger.debug('Checking schema compliance', { skillPath });\r\n const schemaCheck = await checkSchemaCompliance(normalizedPath);\r\n checks.schemaCompliance = schemaCheck.success;\r\n if (!schemaCheck.success) {\r\n errors.push(...(schemaCheck.errors || []));\r\n }\r\n if (schemaCheck.warnings) {\r\n warnings.push(...schemaCheck.warnings);\r\n }\r\n\r\n // 4. Test execution check (if test.sh exists)\r\n logger.debug('Checking tests', { skillPath });\r\n const testCheck = await checkTests(normalizedPath);\r\n checks.testsPassed = testCheck.success;\r\n if (!testCheck.success && testCheck.errors) {\r\n // Test failures are warnings, not hard errors (unless critical)\r\n if (testCheck.critical) {\r\n errors.push(...testCheck.errors);\r\n } else {\r\n warnings.push(...testCheck.errors);\r\n }\r\n }\r\n if (testCheck.warnings) {\r\n warnings.push(...testCheck.warnings);\r\n }\r\n\r\n // 5. Conflict check (production skill doesn't exist or is compatible)\r\n logger.debug('Checking for conflicts', { skillPath });\r\n const conflictCheck = await checkConflicts(normalizedPath);\r\n checks.noConflicts = conflictCheck.success;\r\n if (!conflictCheck.success) {\r\n errors.push(...(conflictCheck.errors || []));\r\n }\r\n if (conflictCheck.warnings) {\r\n warnings.push(...conflictCheck.warnings);\r\n }\r\n\r\n // Determine overall success\r\n const success = errors.length === 0;\r\n\r\n if (success) {\r\n logger.info('Validation passed', { skillPath, warnings: warnings.length });\r\n } else {\r\n logger.error('Validation failed', { skillPath, errors: errors.length, warnings: warnings.length });\r\n }\r\n\r\n return {\r\n success,\r\n errors: errors.length > 0 ? errors : undefined,\r\n warnings: warnings.length > 0 ? warnings : undefined,\r\n checks,\r\n validatedAt: new Date(),\r\n };\r\n } catch (error) {\r\n logger.error('Validation error', { error, skillPath });\r\n return {\r\n success: false,\r\n errors: [`Validation error: ${error instanceof Error ? error.message : String(error)}`],\r\n warnings,\r\n checks,\r\n validatedAt: new Date(),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Check content integrity (all required files exist)\r\n */\r\nasync function checkContentIntegrity(skillPath: string): Promise<ValidationResult> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n try {\r\n // Required files\r\n const requiredFiles = ['SKILL.md', 'execute.sh'];\r\n\r\n for (const file of requiredFiles) {\r\n const filePath = path.join(skillPath, file);\r\n if (!(await fileExists(filePath))) {\r\n errors.push(`Missing required file: ${file}`);\r\n } else {\r\n // Check file is readable\r\n try {\r\n await fsAccess(filePath, fs.constants.R_OK);\r\n } catch {\r\n errors.push(`File not readable: ${file}`);\r\n }\r\n }\r\n }\r\n\r\n // Optional files (warn if missing)\r\n const optionalFiles = ['test.sh', 'README.md'];\r\n for (const file of optionalFiles) {\r\n const filePath = path.join(skillPath, file);\r\n if (!(await fileExists(filePath))) {\r\n warnings.push(`Optional file missing: ${file}`);\r\n }\r\n }\r\n\r\n // Check execute.sh is executable\r\n const executeScript = path.join(skillPath, 'execute.sh');\r\n if (await fileExists(executeScript)) {\r\n try {\r\n const stats = await fsStat(executeScript);\r\n const isExecutable = (stats.mode & fs.constants.S_IXUSR) !== 0;\r\n if (!isExecutable) {\r\n errors.push('execute.sh is not executable (chmod +x required)');\r\n }\r\n } catch (error) {\r\n warnings.push(`Could not check execute.sh permissions: ${error}`);\r\n }\r\n }\r\n\r\n return {\r\n success: errors.length === 0,\r\n errors: errors.length > 0 ? errors : undefined,\r\n warnings: warnings.length > 0 ? warnings : undefined,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n errors: [`Content integrity check failed: ${error instanceof Error ? error.message : String(error)}`],\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Check schema compliance (frontmatter valid)\r\n */\r\nasync function checkSchemaCompliance(skillPath: string): Promise<ValidationResult> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n try {\r\n const skillMdPath = path.join(skillPath, 'SKILL.md');\r\n\r\n if (!(await fileExists(skillMdPath))) {\r\n errors.push('SKILL.md does not exist');\r\n return { success: false, errors };\r\n }\r\n\r\n // Parse frontmatter\r\n const frontmatter = parseFrontmatter(skillPath);\r\n\r\n // Required fields\r\n const requiredFields = ['name', 'description', 'version'];\r\n for (const field of requiredFields) {\r\n if (!frontmatter[field]) {\r\n errors.push(`Missing required frontmatter field: ${field}`);\r\n }\r\n }\r\n\r\n // Validate version format (semantic versioning)\r\n if (frontmatter.version) {\r\n const versionRegex = /^\\d+\\.\\d+\\.\\d+$/;\r\n if (!versionRegex.test(frontmatter.version)) {\r\n errors.push(`Invalid version format: ${frontmatter.version} (expected: X.Y.Z)`);\r\n }\r\n }\r\n\r\n // Optional fields (warn if missing)\r\n const optionalFields = ['author', 'tags', 'dependencies'];\r\n for (const field of optionalFields) {\r\n if (!frontmatter[field]) {\r\n warnings.push(`Optional frontmatter field missing: ${field}`);\r\n }\r\n }\r\n\r\n // Validate tags (should be array)\r\n if (frontmatter.tags && !Array.isArray(frontmatter.tags)) {\r\n warnings.push('Frontmatter tags should be an array');\r\n }\r\n\r\n return {\r\n success: errors.length === 0,\r\n errors: errors.length > 0 ? errors : undefined,\r\n warnings: warnings.length > 0 ? warnings : undefined,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n errors: [`Schema compliance check failed: ${error instanceof Error ? error.message : String(error)}`],\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Check test execution (run test.sh if exists)\r\n */\r\nasync function checkTests(skillPath: string): Promise<ValidationResult & { critical?: boolean }> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n try {\r\n const testScript = path.join(skillPath, 'test.sh');\r\n\r\n // If test.sh doesn't exist, pass (tests are optional)\r\n if (!(await fileExists(testScript))) {\r\n warnings.push('No test.sh found (tests are optional)');\r\n return {\r\n success: true,\r\n warnings,\r\n };\r\n }\r\n\r\n // Check if test.sh is executable\r\n const stats = await fsStat(testScript);\r\n const isExecutable = (stats.mode & fs.constants.S_IXUSR) !== 0;\r\n if (!isExecutable) {\r\n errors.push('test.sh exists but is not executable');\r\n return {\r\n success: false,\r\n errors,\r\n critical: true,\r\n };\r\n }\r\n\r\n // Run tests with 30-second timeout\r\n logger.debug('Running tests', { testScript });\r\n try {\r\n const { stdout, stderr } = await execPromise(`cd ${skillPath} && ./test.sh`, {\r\n timeout: 30000,\r\n maxBuffer: 1024 * 1024, // 1MB\r\n });\r\n\r\n logger.debug('Tests passed', { stdout, stderr });\r\n return {\r\n success: true,\r\n };\r\n } catch (execError: unknown) {\r\n const error = execError as { code?: number; stdout?: string; stderr?: string };\r\n // Test failed\r\n const errorMsg = `Tests failed (exit code ${error.code || 'unknown'}): ${error.stderr || error.stdout || 'No output'}`;\r\n errors.push(errorMsg);\r\n logger.warn('Tests failed', { error: errorMsg });\r\n\r\n // Test failures are non-critical warnings (allow promotion with --force)\r\n return {\r\n success: false,\r\n errors,\r\n critical: false,\r\n };\r\n }\r\n } catch (error) {\r\n return {\r\n success: false,\r\n errors: [`Test check failed: ${error instanceof Error ? error.message : String(error)}`],\r\n critical: false,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Check for conflicts with existing production skills\r\n */\r\nasync function checkConflicts(skillPath: string): Promise<ValidationResult> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n try {\r\n const skillName = path.basename(skillPath);\r\n const productionPath = path.join('.claude/skills', skillName);\r\n\r\n // Check if production skill already exists\r\n if (await fileExists(productionPath)) {\r\n warnings.push(`Production skill already exists: ${skillName} (use --overwrite to replace)`);\r\n\r\n // Check if production skill has a different version\r\n try {\r\n const stagingFrontmatter = parseFrontmatter(skillPath);\r\n const productionFrontmatter = parseFrontmatter(productionPath);\r\n\r\n const stagingVersion = stagingFrontmatter.version;\r\n const productionVersion = productionFrontmatter.version;\r\n\r\n if (stagingVersion === productionVersion) {\r\n warnings.push(`Both staging and production have version ${stagingVersion}`);\r\n } else {\r\n warnings.push(`Version mismatch: staging=${stagingVersion}, production=${productionVersion}`);\r\n }\r\n } catch (error) {\r\n warnings.push('Could not compare versions (frontmatter parse error)');\r\n }\r\n }\r\n\r\n return {\r\n success: errors.length === 0,\r\n errors: errors.length > 0 ? errors : undefined,\r\n warnings: warnings.length > 0 ? warnings : undefined,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n errors: [`Conflict check failed: ${error instanceof Error ? error.message : String(error)}`],\r\n };\r\n }\r\n}\r\n"],"names":["fs","path","promisify","exec","createLogger","fileExists","parseFrontmatter","logger","fsReadFile","readFile","fsStat","stat","fsAccess","access","execPromise","validateStagedSkill","skillPath","errors","warnings","checks","contentIntegrity","schemaCompliance","testsPassed","noConflicts","info","normalizedPath","resolve","push","success","validatedAt","Date","stats","isDirectory","debug","contentCheck","checkContentIntegrity","schemaCheck","checkSchemaCompliance","testCheck","checkTests","critical","conflictCheck","checkConflicts","length","error","undefined","Error","message","String","requiredFiles","file","filePath","join","constants","R_OK","optionalFiles","executeScript","isExecutable","mode","S_IXUSR","skillMdPath","frontmatter","requiredFields","field","version","versionRegex","test","optionalFields","tags","Array","isArray","testScript","stdout","stderr","timeout","maxBuffer","execError","errorMsg","code","warn","skillName","basename","productionPath","stagingFrontmatter","productionFrontmatter","stagingVersion","productionVersion"],"mappings":"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"}
|