claude-flow-novice 2.15.6 → 2.15.8
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/agents/google-sheets/google-sheets-coordinator.md +1 -1
- package/.claude/cfn-extras/docs/GOOGLE_SHEETS_CFN_LOOP.md +13 -11
- package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +39 -577
- package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +49 -270
- package/.claude/skills/cfn-loop-orchestration/src/helpers/consensus.ts +87 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/deliverable-verifier.ts +103 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/gate-check.ts +115 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/iteration-manager.ts +45 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/parse-test-results.ts +372 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/timeout-calculator.ts +41 -0
- package/.claude/skills/cfn-loop-orchestration/tests/consensus.test.ts +142 -0
- package/.claude/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +197 -0
- package/.claude/skills/cfn-loop-orchestration/tests/gate-check.test.ts +325 -0
- package/.claude/skills/cfn-loop-orchestration/tests/iteration-manager.test.ts +132 -0
- package/.claude/skills/cfn-loop-orchestration/tests/parse-test-results.test.ts +382 -0
- package/.claude/skills/cfn-loop-orchestration/tests/timeout-calculator.test.ts +118 -0
- package/.claude/skills/cfn-redis-coordination/coverage/clover.xml +1447 -0
- package/.claude/skills/cfn-redis-coordination/coverage/coverage-final.json +13 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/agent-logger.ts.html +1423 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/agent-recovery.ts.html +1447 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/base.css +224 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/block-navigation.js +87 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/completion-reporter.ts.html +1273 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/context-manager.ts.html +1066 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/favicon.png +0 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/index.html +281 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/mode-detector.ts.html +550 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/prettify.css +1 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/prettify.js +2 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/redis-client.ts.html +2047 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/result-collector.ts.html +1396 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/sorter.js +210 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/swarm-manager.ts.html +1567 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/task-analyzer.ts.html +1297 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/task-executor.ts.html +1354 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/types.ts.html +790 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/waiting-coordinator.ts.html +1846 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov.info +2650 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-analyzer.js +1 -1
- package/.claude/skills/cfn-redis-coordination/src/task-analyzer.ts +1 -1
- package/.claude/skills/cfn-redis-coordination/tests/coordination.test.ts +18 -9
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +13 -72
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +5 -65
- package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +465 -508
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +733 -743
- package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +13 -79
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +15 -14
- package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +23 -30
- package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +13 -18
- package/claude-assets/agents/cfn-dev-team/reviewers/code-reviewer.md +312 -317
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +23 -20
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +718 -737
- package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +817 -828
- package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +8 -9
- package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +668 -684
- package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/tester.md +248 -253
- package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +13 -18
- package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +13 -18
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-coordinator.md +1 -1
- package/claude-assets/cfn-extras/docs/GOOGLE_SHEETS_CFN_LOOP.md +13 -11
- package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +39 -577
- package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +49 -270
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/consensus.ts +87 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/deliverable-verifier.ts +103 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/gate-check.ts +115 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/iteration-manager.ts +45 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/parse-test-results.ts +372 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/timeout-calculator.ts +41 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/consensus.test.ts +142 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +197 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/gate-check.test.ts +325 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/iteration-manager.test.ts +132 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/parse-test-results.test.ts +382 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/timeout-calculator.test.ts +118 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/clover.xml +1447 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/coverage-final.json +13 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/agent-logger.ts.html +1423 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/agent-recovery.ts.html +1447 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/base.css +224 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/block-navigation.js +87 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/completion-reporter.ts.html +1273 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/context-manager.ts.html +1066 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/favicon.png +0 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/index.html +281 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/mode-detector.ts.html +550 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/prettify.css +1 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/prettify.js +2 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/redis-client.ts.html +2047 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/result-collector.ts.html +1396 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/sorter.js +210 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/swarm-manager.ts.html +1567 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/task-analyzer.ts.html +1297 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/task-executor.ts.html +1354 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/types.ts.html +790 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/waiting-coordinator.ts.html +1846 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov.info +2650 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-analyzer.js +1 -1
- package/claude-assets/skills/cfn-redis-coordination/src/task-analyzer.ts +1 -1
- package/claude-assets/skills/cfn-redis-coordination/tests/coordination.test.ts +18 -9
- package/dist/agents/agent-loader.js +165 -146
- package/dist/agents/agent-loader.js.map +1 -1
- package/package.json +1 -1
- package/scripts/clean-agent-profiles.sh +112 -0
|
@@ -100,7 +100,7 @@ npx claude-flow-novice cfn-spawn cfn-v3-coordinator \
|
|
|
100
100
|
|
|
101
101
|
**Agent Communication Pattern:**
|
|
102
102
|
- Coordinator receives broadcast messages via coordination layer
|
|
103
|
-
- Agents signal completion via
|
|
103
|
+
- Agents signal completion via Redis coordination (CLI mode only)
|
|
104
104
|
- Validators wait for gate pass signal before starting
|
|
105
105
|
- Product Owner receives summary and makes decision
|
|
106
106
|
|
|
@@ -318,12 +318,15 @@ automation_001 (depends on all above)
|
|
|
318
318
|
# 3. Signal completion
|
|
319
319
|
coordination-signal "swarm:${TASK_ID}:${AGENT_ID}:done" "complete"
|
|
320
320
|
|
|
321
|
-
# 4. Report results
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
321
|
+
# 4. Report results (CLI Mode - uses Redis coordination)
|
|
322
|
+
# Task Mode: Simply return structured JSON output instead
|
|
323
|
+
if [[ -n "${TASK_ID:-}" && -n "${AGENT_ID:-}" ]]; then
|
|
324
|
+
redis-cli HSET "swarm:${TASK_ID}:${AGENT_ID}:result" \
|
|
325
|
+
confidence 0.95 \
|
|
326
|
+
deliverables '["sheet_created"]' \
|
|
327
|
+
tests_passed 5 \
|
|
328
|
+
tests_total 5
|
|
329
|
+
fi
|
|
327
330
|
```
|
|
328
331
|
|
|
329
332
|
### Loop 2 Validation
|
|
@@ -336,11 +339,10 @@ coordination-wait "swarm:${TASK_ID}:gate-passed"
|
|
|
336
339
|
--sprint-id "$SPRINT_ID" \
|
|
337
340
|
--validation-type comprehensive
|
|
338
341
|
|
|
339
|
-
# 3. Report confidence score
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
--confidence 0.92
|
|
342
|
+
# 3. Report confidence score (CLI Mode)
|
|
343
|
+
if [[ -n "${TASK_ID:-}" && -n "${AGENT_ID:-}" ]]; then
|
|
344
|
+
redis-cli HSET "swarm:${TASK_ID}:${AGENT_ID}:result" confidence 0.92
|
|
345
|
+
fi
|
|
344
346
|
```
|
|
345
347
|
|
|
346
348
|
## API Quota Management
|
|
@@ -1,594 +1,56 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
2
|
##############################################################################
|
|
4
|
-
# Gate Check
|
|
5
|
-
# Validates Loop 3 self-assessment using test
|
|
3
|
+
# Gate Check - TypeScript Wrapper
|
|
4
|
+
# Validates Loop 3 self-assessment using test pass rate thresholds
|
|
5
|
+
#
|
|
6
|
+
# This is a wrapper script that delegates to the TypeScript implementation
|
|
7
|
+
# for better type safety and maintainability.
|
|
6
8
|
#
|
|
7
9
|
# Usage:
|
|
8
|
-
# gate-check.sh --
|
|
9
|
-
# --
|
|
10
|
-
# --
|
|
11
|
-
# --min-quorum <n|n%|0.n> \
|
|
12
|
-
# [--mode <mvp|standard|enterprise>] \
|
|
13
|
-
# [--success-criteria <json>] \
|
|
14
|
-
# [--strategy <test-driven|confidence|auto>]
|
|
10
|
+
# gate-check.sh --pass-rate <0.0-1.0> \
|
|
11
|
+
# [--threshold <0.0-1.0>] \
|
|
12
|
+
# [--mode <mvp|standard|enterprise>]
|
|
15
13
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
14
|
+
# Mode-Specific Thresholds:
|
|
15
|
+
# - mvp: 0.70 (70% pass rate)
|
|
16
|
+
# - standard: 0.95 (95% pass rate) [default]
|
|
17
|
+
# - enterprise: 0.98 (98% pass rate)
|
|
18
18
|
#
|
|
19
|
-
# Returns:
|
|
20
|
-
#
|
|
21
|
-
#
|
|
19
|
+
# Returns JSON:
|
|
20
|
+
# {
|
|
21
|
+
# "passed": true|false,
|
|
22
|
+
# "passRate": 0.96,
|
|
23
|
+
# "threshold": 0.95,
|
|
24
|
+
# "mode": "standard",
|
|
25
|
+
# "gap": 0.0,
|
|
26
|
+
# "reason": "Gate PASSED: ..."
|
|
27
|
+
# }
|
|
28
|
+
#
|
|
29
|
+
# Exit Codes:
|
|
30
|
+
# 0: Gate passed
|
|
31
|
+
# 1: Gate failed
|
|
22
32
|
##############################################################################
|
|
23
33
|
|
|
24
34
|
set -euo pipefail
|
|
25
35
|
|
|
26
|
-
# Script directory for helper resolution
|
|
27
36
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
28
|
-
|
|
37
|
+
SKILL_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
29
38
|
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
EXPECTED_PREFIX="/home/user/claude-flow-novice"
|
|
33
|
-
if [[ ! "$PROJECT_ROOT" =~ ^${EXPECTED_PREFIX//./\\.} ]]; then
|
|
34
|
-
echo "❌ SECURITY ERROR: Invalid project root detected" >&2
|
|
35
|
-
echo " Expected prefix: $EXPECTED_PREFIX" >&2
|
|
36
|
-
echo " Actual path: $PROJECT_ROOT" >&2
|
|
37
|
-
echo " Risk: Path traversal / symlink attack" >&2
|
|
38
|
-
exit 1
|
|
39
|
-
fi
|
|
39
|
+
# Path to compiled TypeScript
|
|
40
|
+
TS_DIST="$SKILL_ROOT/dist/helpers/gate-check.js"
|
|
40
41
|
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
MIN_QUORUM=""
|
|
46
|
-
MODE="standard"
|
|
47
|
-
SUCCESS_CRITERIA=""
|
|
48
|
-
STRATEGY="${CFN_GATE_STRATEGY:-auto}"
|
|
49
|
-
|
|
50
|
-
# Parse arguments
|
|
51
|
-
while [[ $# -gt 0 ]]; do
|
|
52
|
-
case $1 in
|
|
53
|
-
--task-id) TASK_ID="$2"; shift 2 ;;
|
|
54
|
-
--agents) AGENTS="$2"; shift 2 ;;
|
|
55
|
-
--threshold) THRESHOLD="$2"; shift 2 ;;
|
|
56
|
-
--min-quorum) MIN_QUORUM="$2"; shift 2 ;;
|
|
57
|
-
--mode) MODE="$2"; shift 2 ;;
|
|
58
|
-
--success-criteria) SUCCESS_CRITERIA="$2"; shift 2 ;;
|
|
59
|
-
--strategy) STRATEGY="$2"; shift 2 ;;
|
|
60
|
-
*) echo "Unknown option: $1"; exit 1 ;;
|
|
61
|
-
esac
|
|
62
|
-
done
|
|
63
|
-
|
|
64
|
-
# Validation
|
|
65
|
-
if [ -z "$TASK_ID" ] || [ -z "$AGENTS" ] || [ -z "$THRESHOLD" ] || [ -z "$MIN_QUORUM" ]; then
|
|
66
|
-
echo "Error: Missing required parameters" >&2
|
|
42
|
+
# Check if TypeScript implementation exists
|
|
43
|
+
if [ ! -f "$TS_DIST" ]; then
|
|
44
|
+
echo "❌ Error: TypeScript implementation not found at: $TS_DIST" >&2
|
|
45
|
+
echo " Run 'npm run build' in .claude/skills/cfn-loop-orchestration/" >&2
|
|
67
46
|
exit 1
|
|
68
47
|
fi
|
|
69
48
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
# SECURITY FIX #2: JSON Schema Validation (CWE-400)
|
|
76
|
-
# Prevents DoS via excessively large test suite arrays and invalid field values
|
|
77
|
-
validate_success_criteria() {
|
|
78
|
-
local CRITERIA="$1"
|
|
79
|
-
local MAX_TEST_SUITES=50 # DoS prevention: max 50 test suites
|
|
80
|
-
local MAX_FIELD_LENGTH=256 # Field name length limit
|
|
81
|
-
local PASS_THRESHOLD_MIN=0.0
|
|
82
|
-
local PASS_THRESHOLD_MAX=1.0
|
|
83
|
-
local TIMEOUT_MIN=1
|
|
84
|
-
local TIMEOUT_MAX=3600
|
|
85
|
-
|
|
86
|
-
if [ -z "$CRITERIA" ]; then
|
|
87
|
-
echo "❌ No success criteria provided" >&2
|
|
88
|
-
return 1
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
# Validate JSON structure
|
|
92
|
-
if ! echo "$CRITERIA" | jq empty 2>/dev/null; then
|
|
93
|
-
echo "❌ Invalid JSON in success criteria" >&2
|
|
94
|
-
return 1
|
|
95
|
-
fi
|
|
96
|
-
|
|
97
|
-
# Check for required fields
|
|
98
|
-
if ! echo "$CRITERIA" | jq -e '.test_suites' >/dev/null 2>&1; then
|
|
99
|
-
echo "❌ Missing test_suites array in success criteria" >&2
|
|
100
|
-
return 1
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
# SECURITY FIX #2a: Array size validation - prevent DoS
|
|
104
|
-
local TEST_SUITE_COUNT
|
|
105
|
-
TEST_SUITE_COUNT=$(echo "$CRITERIA" | jq '.test_suites | length')
|
|
106
|
-
|
|
107
|
-
if [ -z "$TEST_SUITE_COUNT" ] || [ "$TEST_SUITE_COUNT" -lt 0 ]; then
|
|
108
|
-
echo "❌ Invalid test_suites array" >&2
|
|
109
|
-
return 1
|
|
110
|
-
fi
|
|
111
|
-
|
|
112
|
-
if [ "$TEST_SUITE_COUNT" -gt "$MAX_TEST_SUITES" ]; then
|
|
113
|
-
echo "❌ SECURITY ERROR: test_suites array exceeds maximum size" >&2
|
|
114
|
-
echo " Count: $TEST_SUITE_COUNT (max: $MAX_TEST_SUITES)" >&2
|
|
115
|
-
echo " Risk: DoS via resource exhaustion" >&2
|
|
116
|
-
return 1
|
|
117
|
-
fi
|
|
118
|
-
|
|
119
|
-
# SECURITY FIX #2b: Field-level validation
|
|
120
|
-
local SUITE_INDEX=0
|
|
121
|
-
while [ "$SUITE_INDEX" -lt "$TEST_SUITE_COUNT" ]; do
|
|
122
|
-
local SUITE
|
|
123
|
-
SUITE=$(echo "$CRITERIA" | jq ".test_suites[$SUITE_INDEX]")
|
|
124
|
-
|
|
125
|
-
# Validate pass_threshold (0.0-1.0)
|
|
126
|
-
local PASS_THRESHOLD
|
|
127
|
-
PASS_THRESHOLD=$(echo "$SUITE" | jq -r '.pass_threshold // 0.5')
|
|
128
|
-
|
|
129
|
-
if ! [[ "$PASS_THRESHOLD" =~ ^[0-9]+\.?[0-9]*$ ]]; then
|
|
130
|
-
echo "❌ Invalid pass_threshold in test suite $SUITE_INDEX: $PASS_THRESHOLD" >&2
|
|
131
|
-
return 1
|
|
132
|
-
fi
|
|
133
|
-
|
|
134
|
-
# Use bc for floating point comparison
|
|
135
|
-
if (( $(echo "$PASS_THRESHOLD < $PASS_THRESHOLD_MIN" | bc -l) )) || \
|
|
136
|
-
(( $(echo "$PASS_THRESHOLD > $PASS_THRESHOLD_MAX" | bc -l) )); then
|
|
137
|
-
echo "❌ pass_threshold out of range [0.0-1.0] in suite $SUITE_INDEX: $PASS_THRESHOLD" >&2
|
|
138
|
-
return 1
|
|
139
|
-
fi
|
|
140
|
-
|
|
141
|
-
# SECURITY FIX #2c: Timeout range validation (1-3600 seconds)
|
|
142
|
-
local TIMEOUT
|
|
143
|
-
TIMEOUT=$(echo "$SUITE" | jq -r '.timeout // 300')
|
|
144
|
-
|
|
145
|
-
if ! [[ "$TIMEOUT" =~ ^[0-9]+$ ]]; then
|
|
146
|
-
echo "❌ Invalid timeout in test suite $SUITE_INDEX: $TIMEOUT (must be integer)" >&2
|
|
147
|
-
return 1
|
|
148
|
-
fi
|
|
149
|
-
|
|
150
|
-
if [ "$TIMEOUT" -lt "$TIMEOUT_MIN" ] || [ "$TIMEOUT" -gt "$TIMEOUT_MAX" ]; then
|
|
151
|
-
echo "❌ Timeout out of range [${TIMEOUT_MIN}-${TIMEOUT_MAX}s] in suite $SUITE_INDEX: ${TIMEOUT}s" >&2
|
|
152
|
-
return 1
|
|
153
|
-
fi
|
|
154
|
-
|
|
155
|
-
# Validate suite name length
|
|
156
|
-
local SUITE_NAME
|
|
157
|
-
SUITE_NAME=$(echo "$SUITE" | jq -r '.name // "unnamed"')
|
|
158
|
-
|
|
159
|
-
if [ ${#SUITE_NAME} -gt "$MAX_FIELD_LENGTH" ]; then
|
|
160
|
-
echo "❌ Test suite name exceeds maximum length in suite $SUITE_INDEX" >&2
|
|
161
|
-
return 1
|
|
162
|
-
fi
|
|
163
|
-
|
|
164
|
-
SUITE_INDEX=$((SUITE_INDEX + 1))
|
|
165
|
-
done
|
|
166
|
-
|
|
167
|
-
return 0
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
# Check if success criteria exists and is valid
|
|
171
|
-
has_success_criteria() {
|
|
172
|
-
if [ -z "$SUCCESS_CRITERIA" ]; then
|
|
173
|
-
return 1
|
|
174
|
-
fi
|
|
175
|
-
|
|
176
|
-
validate_success_criteria "$SUCCESS_CRITERIA" >/dev/null 2>&1
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
# Get mode-specific test pass threshold
|
|
180
|
-
get_mode_threshold() {
|
|
181
|
-
local MODE="$1"
|
|
182
|
-
|
|
183
|
-
case "$MODE" in
|
|
184
|
-
mvp) echo "0.80" ;;
|
|
185
|
-
standard) echo "0.95" ;;
|
|
186
|
-
enterprise) echo "0.99" ;;
|
|
187
|
-
*) echo "0.95" ;; # Default to standard
|
|
188
|
-
esac
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
# Validate command safety (prevent shell injection)
|
|
192
|
-
validate_command_safety() {
|
|
193
|
-
local COMMAND="$1"
|
|
194
|
-
|
|
195
|
-
# Check for dangerous shell patterns
|
|
196
|
-
# Allow: && (AND operator), || (OR operator)
|
|
197
|
-
# Block: ; (command separator), | (pipe), > < (redirects), ` (backticks), $() (command substitution), {} (brace expansion)
|
|
198
|
-
|
|
199
|
-
# Remove safe operators first
|
|
200
|
-
local SANITIZED="${COMMAND//&&/}"
|
|
201
|
-
SANITIZED="${SANITIZED//||/}"
|
|
202
|
-
|
|
203
|
-
# Now check for remaining dangerous metacharacters
|
|
204
|
-
if [[ "$SANITIZED" =~ [\;\|\>\<\`\$\(\)\{\}] ]]; then
|
|
205
|
-
echo "❌ Unsafe command detected: contains dangerous shell metacharacters" >&2
|
|
206
|
-
echo " Blocked patterns: ; | > < \` \$() {}" >&2
|
|
207
|
-
return 1
|
|
208
|
-
fi
|
|
209
|
-
|
|
210
|
-
return 0
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
# Check if command is required or optional
|
|
214
|
-
is_required() {
|
|
215
|
-
local SUITE_JSON="$1"
|
|
216
|
-
local REQUIRED=$(echo "$SUITE_JSON" | jq -r '.required // true')
|
|
217
|
-
|
|
218
|
-
[ "$REQUIRED" = "true" ]
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
# Execute a single test suite
|
|
222
|
-
execute_test_suite() {
|
|
223
|
-
local SUITE_JSON="$1"
|
|
224
|
-
local SUITE_NAME=$(echo "$SUITE_JSON" | jq -r '.name // "unnamed"')
|
|
225
|
-
local COMMAND=$(echo "$SUITE_JSON" | jq -r '.command')
|
|
226
|
-
local TIMEOUT=$(echo "$SUITE_JSON" | jq -r '.timeout // 300')
|
|
227
|
-
local FRAMEWORK=$(echo "$SUITE_JSON" | jq -r '.framework // "auto"')
|
|
228
|
-
|
|
229
|
-
echo " Executing test suite: $SUITE_NAME" >&2
|
|
230
|
-
|
|
231
|
-
# Validate command safety
|
|
232
|
-
if ! validate_command_safety "$COMMAND"; then
|
|
233
|
-
echo " ❌ Command validation failed" >&2
|
|
234
|
-
return 1
|
|
235
|
-
fi
|
|
236
|
-
|
|
237
|
-
# Execute with timeout
|
|
238
|
-
local OUTPUT
|
|
239
|
-
local EXIT_CODE=0
|
|
240
|
-
|
|
241
|
-
OUTPUT=$(cd "$PROJECT_ROOT" && timeout "$TIMEOUT" bash -c "$COMMAND" 2>&1) || EXIT_CODE=$?
|
|
242
|
-
|
|
243
|
-
if [ $EXIT_CODE -eq 124 ]; then
|
|
244
|
-
echo " ⚠️ Test execution timed out after ${TIMEOUT}s" >&2
|
|
245
|
-
echo '{"pass_rate": 0.0, "passed": 0, "failed": 0, "total": 0, "status": "timeout"}'
|
|
246
|
-
return 1
|
|
247
|
-
elif [ $EXIT_CODE -ne 0 ]; then
|
|
248
|
-
echo " ⚠️ Test execution failed with exit code $EXIT_CODE" >&2
|
|
249
|
-
fi
|
|
250
|
-
|
|
251
|
-
# Parse test results
|
|
252
|
-
local RESULTS
|
|
253
|
-
if [ -x "$PROJECT_ROOT/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh" ]; then
|
|
254
|
-
# Use dedicated parser if available (expects positional params: framework, output)
|
|
255
|
-
RESULTS=$("$PROJECT_ROOT/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh" \
|
|
256
|
-
"$FRAMEWORK" \
|
|
257
|
-
"$OUTPUT" 2>/dev/null) || {
|
|
258
|
-
echo " ⚠️ Failed to parse test results" >&2
|
|
259
|
-
RESULTS='{"pass_rate": 0.0, "passed": 0, "failed": 0, "total": 0, "status": "parse_error"}'
|
|
260
|
-
}
|
|
261
|
-
else
|
|
262
|
-
# Fallback: simple pattern matching
|
|
263
|
-
RESULTS=$(parse_test_results_fallback "$OUTPUT" "$FRAMEWORK" "$EXIT_CODE")
|
|
264
|
-
fi
|
|
265
|
-
|
|
266
|
-
local PASS_RATE=$(echo "$RESULTS" | jq -r '.pass_rate // 0.0')
|
|
267
|
-
local PASSED=$(echo "$RESULTS" | jq -r '.passed // 0')
|
|
268
|
-
local TOTAL=$(echo "$RESULTS" | jq -r '.total // 0')
|
|
269
|
-
|
|
270
|
-
echo " Pass rate: $PASS_RATE ($PASSED/$TOTAL tests)" >&2
|
|
271
|
-
|
|
272
|
-
echo "$RESULTS"
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
# Fallback test result parser (simple pattern matching)
|
|
276
|
-
parse_test_results_fallback() {
|
|
277
|
-
local OUTPUT="$1"
|
|
278
|
-
local FRAMEWORK="$2"
|
|
279
|
-
local EXIT_CODE="$3"
|
|
280
|
-
|
|
281
|
-
local PASSED=0
|
|
282
|
-
local FAILED=0
|
|
283
|
-
local TOTAL=0
|
|
284
|
-
|
|
285
|
-
# Try common test output patterns
|
|
286
|
-
if echo "$OUTPUT" | grep -qE "([0-9]+) passed.*([0-9]+) failed"; then
|
|
287
|
-
PASSED=$(echo "$OUTPUT" | grep -oE "([0-9]+) passed" | grep -oE "[0-9]+" | head -1)
|
|
288
|
-
FAILED=$(echo "$OUTPUT" | grep -oE "([0-9]+) failed" | grep -oE "[0-9]+" | head -1)
|
|
289
|
-
elif echo "$OUTPUT" | grep -qE "([0-9]+)/([0-9]+) tests? passed"; then
|
|
290
|
-
PASSED=$(echo "$OUTPUT" | grep -oE "([0-9]+)/([0-9]+)" | cut -d'/' -f1)
|
|
291
|
-
TOTAL=$(echo "$OUTPUT" | grep -oE "([0-9]+)/([0-9]+)" | cut -d'/' -f2)
|
|
292
|
-
FAILED=$((TOTAL - PASSED))
|
|
293
|
-
fi
|
|
294
|
-
|
|
295
|
-
TOTAL=$((PASSED + FAILED))
|
|
296
|
-
|
|
297
|
-
# Calculate pass rate
|
|
298
|
-
local PASS_RATE="0.0"
|
|
299
|
-
if [ $TOTAL -gt 0 ]; then
|
|
300
|
-
PASS_RATE=$(echo "scale=2; $PASSED / $TOTAL" | bc -l)
|
|
301
|
-
elif [ $EXIT_CODE -eq 0 ]; then
|
|
302
|
-
# No test output but exit code 0 - assume success
|
|
303
|
-
PASS_RATE="1.0"
|
|
304
|
-
PASSED=1
|
|
305
|
-
TOTAL=1
|
|
306
|
-
fi
|
|
307
|
-
|
|
308
|
-
echo "{\"pass_rate\": $PASS_RATE, \"passed\": $PASSED, \"failed\": $FAILED, \"total\": $TOTAL, \"status\": \"parsed\"}"
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
# Calculate aggregate pass rate from multiple test suites
|
|
312
|
-
calculate_aggregate_pass_rate() {
|
|
313
|
-
local RESULTS_FILE="$1"
|
|
314
|
-
|
|
315
|
-
local TOTAL_PASSED=0
|
|
316
|
-
local TOTAL_TESTS=0
|
|
317
|
-
|
|
318
|
-
while IFS= read -r RESULT; do
|
|
319
|
-
local PASSED=$(echo "$RESULT" | jq -r '.passed // 0')
|
|
320
|
-
local TOTAL=$(echo "$RESULT" | jq -r '.total // 0')
|
|
321
|
-
|
|
322
|
-
TOTAL_PASSED=$((TOTAL_PASSED + PASSED))
|
|
323
|
-
TOTAL_TESTS=$((TOTAL_TESTS + TOTAL))
|
|
324
|
-
done < "$RESULTS_FILE"
|
|
325
|
-
|
|
326
|
-
if [ $TOTAL_TESTS -eq 0 ]; then
|
|
327
|
-
echo "0.0"
|
|
328
|
-
else
|
|
329
|
-
echo "scale=4; $TOTAL_PASSED / $TOTAL_TESTS" | bc -l
|
|
330
|
-
fi
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
# Store test results (Redis for CLI mode, file for Task mode)
|
|
334
|
-
store_test_results() {
|
|
335
|
-
local TASK_ID="$1"
|
|
336
|
-
local PASS_RATE="$2"
|
|
337
|
-
local RESULTS_FILE="$3"
|
|
338
|
-
|
|
339
|
-
# Check if running in CLI mode (Redis available)
|
|
340
|
-
if command -v redis-cli >/dev/null 2>&1 && redis-cli ping >/dev/null 2>&1; then
|
|
341
|
-
# Store in Redis
|
|
342
|
-
redis-cli HSET "task:$TASK_ID:gate" "test_pass_rate" "$PASS_RATE" >/dev/null
|
|
343
|
-
redis-cli HSET "task:$TASK_ID:gate" "test_results" "$(cat "$RESULTS_FILE")" >/dev/null
|
|
344
|
-
redis-cli EXPIRE "task:$TASK_ID:gate" 86400 >/dev/null # 24h TTL
|
|
345
|
-
else
|
|
346
|
-
# Task mode: store in temp file for coordinator to read
|
|
347
|
-
local OUTPUT_DIR="/tmp/cfn-gate-results"
|
|
348
|
-
mkdir -p "$OUTPUT_DIR"
|
|
349
|
-
echo "$PASS_RATE" > "$OUTPUT_DIR/$TASK_ID.pass_rate"
|
|
350
|
-
cp "$RESULTS_FILE" "$OUTPUT_DIR/$TASK_ID.results.json"
|
|
351
|
-
fi
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
# Generate iteration context for failed gate
|
|
355
|
-
generate_iteration_context() {
|
|
356
|
-
local TASK_ID="$1"
|
|
357
|
-
local PASS_RATE="$2"
|
|
358
|
-
local THRESHOLD="$3"
|
|
359
|
-
local RESULTS_FILE="$4"
|
|
360
|
-
|
|
361
|
-
local CONTEXT_FILE="/tmp/cfn-iteration-context-$TASK_ID.json"
|
|
362
|
-
|
|
363
|
-
# Extract failed test details
|
|
364
|
-
local FAILED_TESTS=$(jq -s '[.[] | select(.pass_rate < 1.0)]' "$RESULTS_FILE")
|
|
365
|
-
|
|
366
|
-
# Generate context
|
|
367
|
-
cat > "$CONTEXT_FILE" <<EOF
|
|
368
|
-
{
|
|
369
|
-
"gate_status": "failed",
|
|
370
|
-
"pass_rate": $PASS_RATE,
|
|
371
|
-
"threshold": $THRESHOLD,
|
|
372
|
-
"gap": $(echo "$THRESHOLD - $PASS_RATE" | bc -l),
|
|
373
|
-
"failed_tests": $FAILED_TESTS,
|
|
374
|
-
"recommendations": [
|
|
375
|
-
"Review failed test suites",
|
|
376
|
-
"Fix implementation issues",
|
|
377
|
-
"Re-run validation"
|
|
378
|
-
]
|
|
379
|
-
}
|
|
380
|
-
EOF
|
|
381
|
-
|
|
382
|
-
echo " Iteration context saved to: $CONTEXT_FILE" >&2
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
##############################################################################
|
|
386
|
-
# Test-Driven Gate Check
|
|
387
|
-
##############################################################################
|
|
388
|
-
|
|
389
|
-
gate_check_test_driven() {
|
|
390
|
-
local TASK_ID="$1"
|
|
391
|
-
local MODE="$2"
|
|
392
|
-
local SUCCESS_CRITERIA="$3"
|
|
393
|
-
|
|
394
|
-
# SECURITY FIX #3: DoS Prevention - Total Time Limit
|
|
395
|
-
# Prevent unbounded test execution time (default 30 min, configurable)
|
|
396
|
-
local MAX_TOTAL_TIME=${CFN_MAX_GATE_TIME:-1800} # Default 30 minutes (1800 seconds)
|
|
397
|
-
local START_TIME=$(date +%s)
|
|
398
|
-
|
|
399
|
-
echo "🧪 Test-Driven Gate Check"
|
|
400
|
-
echo " Task ID: $TASK_ID"
|
|
401
|
-
echo " Mode: $MODE"
|
|
402
|
-
echo " Max Total Time: ${MAX_TOTAL_TIME}s"
|
|
403
|
-
echo ""
|
|
404
|
-
|
|
405
|
-
# Validate success criteria
|
|
406
|
-
if ! validate_success_criteria "$SUCCESS_CRITERIA"; then
|
|
407
|
-
echo "❌ Invalid success criteria" >&2
|
|
408
|
-
return 1
|
|
409
|
-
fi
|
|
410
|
-
|
|
411
|
-
# Extract test suites
|
|
412
|
-
local TEST_SUITES=$(echo "$SUCCESS_CRITERIA" | jq -c '.test_suites[]')
|
|
413
|
-
|
|
414
|
-
if [ -z "$TEST_SUITES" ]; then
|
|
415
|
-
echo "❌ No test suites defined in success criteria" >&2
|
|
416
|
-
return 1
|
|
417
|
-
fi
|
|
418
|
-
|
|
419
|
-
# Temporary file for results
|
|
420
|
-
# SECURITY FIX #4: Secure Temp File Permissions
|
|
421
|
-
# Set restrictive permissions (owner read/write only) to prevent information disclosure
|
|
422
|
-
local RESULTS_FILE=$(mktemp)
|
|
423
|
-
chmod 600 "$RESULTS_FILE"
|
|
424
|
-
trap "rm -f '$RESULTS_FILE'" EXIT
|
|
425
|
-
|
|
426
|
-
# Execute each test suite
|
|
427
|
-
local SUITE_COUNT=0
|
|
428
|
-
local FAILED_REQUIRED=0
|
|
429
|
-
|
|
430
|
-
while IFS= read -r SUITE; do
|
|
431
|
-
SUITE_COUNT=$((SUITE_COUNT + 1))
|
|
432
|
-
|
|
433
|
-
# SECURITY FIX #3 (continued): Check total execution time
|
|
434
|
-
local CURRENT_TIME=$(date +%s)
|
|
435
|
-
local ELAPSED=$((CURRENT_TIME - START_TIME))
|
|
436
|
-
|
|
437
|
-
if [ $ELAPSED -gt $MAX_TOTAL_TIME ]; then
|
|
438
|
-
echo "❌ SECURITY ERROR: Total execution time exceeded" >&2
|
|
439
|
-
echo " Elapsed: ${ELAPSED}s > Max: ${MAX_TOTAL_TIME}s" >&2
|
|
440
|
-
echo " Risk: DoS via unbounded execution" >&2
|
|
441
|
-
return 1
|
|
442
|
-
fi
|
|
443
|
-
|
|
444
|
-
local RESULT
|
|
445
|
-
RESULT=$(execute_test_suite "$SUITE") || {
|
|
446
|
-
if is_required "$SUITE"; then
|
|
447
|
-
FAILED_REQUIRED=$((FAILED_REQUIRED + 1))
|
|
448
|
-
echo " ❌ Required test suite failed" >&2
|
|
449
|
-
fi
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
echo "$RESULT" >> "$RESULTS_FILE"
|
|
453
|
-
done <<< "$TEST_SUITES"
|
|
454
|
-
|
|
455
|
-
# If any required test suite failed completely, gate fails immediately
|
|
456
|
-
if [ $FAILED_REQUIRED -gt 0 ]; then
|
|
457
|
-
echo ""
|
|
458
|
-
echo "❌ Gate FAILED: $FAILED_REQUIRED required test suite(s) failed completely" >&2
|
|
459
|
-
generate_iteration_context "$TASK_ID" "0.0" "$(get_mode_threshold "$MODE")" "$RESULTS_FILE"
|
|
460
|
-
return 1
|
|
461
|
-
fi
|
|
462
|
-
|
|
463
|
-
# Calculate aggregate pass rate
|
|
464
|
-
local TOTAL_PASS_RATE
|
|
465
|
-
TOTAL_PASS_RATE=$(calculate_aggregate_pass_rate "$RESULTS_FILE")
|
|
466
|
-
|
|
467
|
-
# Store results
|
|
468
|
-
store_test_results "$TASK_ID" "$TOTAL_PASS_RATE" "$RESULTS_FILE"
|
|
469
|
-
|
|
470
|
-
# Get threshold for mode
|
|
471
|
-
local TEST_THRESHOLD
|
|
472
|
-
TEST_THRESHOLD=$(get_mode_threshold "$MODE")
|
|
473
|
-
|
|
474
|
-
echo ""
|
|
475
|
-
echo "Test Results Summary:"
|
|
476
|
-
echo " Aggregate Pass Rate: $TOTAL_PASS_RATE"
|
|
477
|
-
echo " Required Threshold: $TEST_THRESHOLD ($MODE mode)"
|
|
478
|
-
echo ""
|
|
479
|
-
|
|
480
|
-
# Check threshold
|
|
481
|
-
if (( $(echo "$TOTAL_PASS_RATE >= $TEST_THRESHOLD" | bc -l) )); then
|
|
482
|
-
echo "✅ Gate PASSED: Test-driven validation successful"
|
|
483
|
-
return 0
|
|
484
|
-
else
|
|
485
|
-
echo "❌ Gate FAILED: Pass rate below threshold"
|
|
486
|
-
echo " Gap: $(echo "$TEST_THRESHOLD - $TOTAL_PASS_RATE" | bc -l)"
|
|
487
|
-
generate_iteration_context "$TASK_ID" "$TOTAL_PASS_RATE" "$TEST_THRESHOLD" "$RESULTS_FILE"
|
|
488
|
-
return 1
|
|
489
|
-
fi
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
##############################################################################
|
|
493
|
-
# Confidence-Based Gate Check (Original Implementation)
|
|
494
|
-
##############################################################################
|
|
495
|
-
|
|
496
|
-
gate_check_confidence() {
|
|
497
|
-
local TASK_ID="$1"
|
|
498
|
-
local AGENTS="$2"
|
|
499
|
-
local THRESHOLD="$3"
|
|
500
|
-
local MIN_QUORUM="$4"
|
|
501
|
-
|
|
502
|
-
# Deprecation warning
|
|
503
|
-
echo "⚠️ Using legacy confidence-based gate check" >&2
|
|
504
|
-
echo " Consider migrating to test-driven validation" >&2
|
|
505
|
-
echo ""
|
|
506
|
-
|
|
507
|
-
# Use Redis Coordination skill to collect confidence scores
|
|
508
|
-
local REDIS_COORD_SKILL="$PROJECT_ROOT/.claude/skills/cfn-redis-coordination"
|
|
509
|
-
|
|
510
|
-
echo "Gate Check Configuration:"
|
|
511
|
-
echo " Task ID: $TASK_ID"
|
|
512
|
-
echo " Agent IDs: $AGENTS"
|
|
513
|
-
echo " Min Quorum: $MIN_QUORUM"
|
|
514
|
-
echo ""
|
|
515
|
-
|
|
516
|
-
# Collect Loop 3 confidence scores
|
|
517
|
-
local CONSENSUS
|
|
518
|
-
CONSENSUS=$("$REDIS_COORD_SKILL/invoke-waiting-mode.sh" collect \
|
|
519
|
-
--task-id "$TASK_ID" \
|
|
520
|
-
--agent-ids "$AGENTS" \
|
|
521
|
-
--min-quorum "$MIN_QUORUM" 2>/dev/null) || {
|
|
522
|
-
echo "❌ Error: Failed to collect Loop 3 confidence scores" >&2
|
|
523
|
-
echo " Agent IDs: $AGENTS" >&2
|
|
524
|
-
return 1
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
# Validate consensus is a valid number
|
|
528
|
-
if ! [[ "$CONSENSUS" =~ ^[0-9]+\.?[0-9]*$ ]]; then
|
|
529
|
-
echo "⚠️ WARNING: Invalid consensus value: $CONSENSUS (expected numeric)" >&2
|
|
530
|
-
echo " Defaulting to 0.0" >&2
|
|
531
|
-
CONSENSUS="0.0"
|
|
532
|
-
fi
|
|
533
|
-
|
|
534
|
-
echo "Loop 3 Gate Check:"
|
|
535
|
-
echo " Consensus: $CONSENSUS"
|
|
536
|
-
echo " Threshold: $THRESHOLD"
|
|
537
|
-
echo " Required: >= $THRESHOLD"
|
|
538
|
-
echo ""
|
|
539
|
-
|
|
540
|
-
# Compare consensus to gate threshold
|
|
541
|
-
if (( $(echo "$CONSENSUS >= $THRESHOLD" | bc -l) )); then
|
|
542
|
-
echo "✅ Gate PASSED - Loop 3 self-validation successful"
|
|
543
|
-
return 0
|
|
544
|
-
else
|
|
545
|
-
echo "❌ Gate FAILED - Loop 3 needs improvement"
|
|
546
|
-
echo " Gap: $(echo "$THRESHOLD - $CONSENSUS" | bc -l)"
|
|
547
|
-
return 1
|
|
548
|
-
fi
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
##############################################################################
|
|
552
|
-
# Main Execution - Strategy Selection
|
|
553
|
-
##############################################################################
|
|
554
|
-
|
|
555
|
-
echo "========================================="
|
|
556
|
-
echo "CFN Loop Gate Check v2.0"
|
|
557
|
-
echo "Strategy: $STRATEGY"
|
|
558
|
-
echo "========================================="
|
|
559
|
-
echo ""
|
|
560
|
-
|
|
561
|
-
case "$STRATEGY" in
|
|
562
|
-
test-driven)
|
|
563
|
-
if [ -z "$SUCCESS_CRITERIA" ]; then
|
|
564
|
-
echo "❌ Error: test-driven strategy requires --success-criteria" >&2
|
|
565
|
-
exit 1
|
|
566
|
-
fi
|
|
567
|
-
gate_check_test_driven "$TASK_ID" "$MODE" "$SUCCESS_CRITERIA"
|
|
568
|
-
;;
|
|
569
|
-
|
|
570
|
-
confidence)
|
|
571
|
-
gate_check_confidence "$TASK_ID" "$AGENTS" "$THRESHOLD" "$MIN_QUORUM"
|
|
572
|
-
;;
|
|
573
|
-
|
|
574
|
-
auto)
|
|
575
|
-
# Hybrid mode: prefer test-driven if criteria exists, fallback to confidence
|
|
576
|
-
if has_success_criteria; then
|
|
577
|
-
echo "Auto-detected: Using test-driven validation" >&2
|
|
578
|
-
echo ""
|
|
579
|
-
gate_check_test_driven "$TASK_ID" "$MODE" "$SUCCESS_CRITERIA"
|
|
580
|
-
else
|
|
581
|
-
echo "Auto-detected: Using confidence-based validation (no success criteria)" >&2
|
|
582
|
-
echo ""
|
|
583
|
-
gate_check_confidence "$TASK_ID" "$AGENTS" "$THRESHOLD" "$MIN_QUORUM"
|
|
584
|
-
fi
|
|
585
|
-
;;
|
|
586
|
-
|
|
587
|
-
*)
|
|
588
|
-
echo "❌ Error: Invalid strategy '$STRATEGY'" >&2
|
|
589
|
-
echo " Valid options: test-driven, confidence, auto" >&2
|
|
590
|
-
exit 1
|
|
591
|
-
;;
|
|
592
|
-
esac
|
|
49
|
+
# Check if node is available
|
|
50
|
+
if ! command -v node &>/dev/null; then
|
|
51
|
+
echo "❌ Error: Node.js is required but not found in PATH" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
593
54
|
|
|
594
|
-
|
|
55
|
+
# Execute TypeScript implementation
|
|
56
|
+
exec node "$TS_DIST" "$@"
|