claude-flow-novice 2.15.4 → 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.
@@ -21,26 +21,35 @@ MODE: Parse from --mode flag or default to "standard"
21
21
  MAX_ITERATIONS: Parse from --max-iterations flag or default to 10
22
22
  ```
23
23
 
24
- **Step 2: Generate Task ID**
24
+ **Step 2: Set Redis Environment Variables (REQUIRED for non-Docker environments)**
25
+ ```bash
26
+ # Set Redis connection parameters for CLI mode
27
+ export CFN_REDIS_HOST=localhost
28
+ export CFN_REDIS_PORT=6379
29
+
30
+ echo "✅ Redis environment: $CFN_REDIS_HOST:$CFN_REDIS_PORT"
31
+ ```
32
+
33
+ **Step 3: Generate Task ID**
25
34
  ```bash
26
35
  TASK_ID="cfn-cli-$(date +%s%N | tail -c 7)-${RANDOM}"
27
36
  ```
28
37
 
29
- **Step 2.5: Verify Redis Availability (REQUIRED for CLI mode coordination)**
38
+ **Step 4: Verify Redis Availability (REQUIRED for CLI mode coordination)**
30
39
  ```bash
31
40
  # Verify Redis availability (REQUIRED for CLI mode coordination)
32
- if ! redis-cli PING >/dev/null 2>&1; then
33
- echo "❌ ERROR: Redis not available"
41
+ if ! redis-cli -h "$CFN_REDIS_HOST" -p "$CFN_REDIS_PORT" PING >/dev/null 2>&1; then
42
+ echo "❌ ERROR: Redis not available at $CFN_REDIS_HOST:$CFN_REDIS_PORT"
34
43
  echo " CLI mode requires Redis for coordination"
35
44
  echo " Start Redis: redis-server"
36
45
  echo " Or use Task mode: /cfn-loop-task"
37
46
  exit 1
38
47
  fi
39
48
 
40
- echo "✅ Redis available"
49
+ echo "✅ Redis available at $CFN_REDIS_HOST:$CFN_REDIS_PORT"
41
50
  ```
42
51
 
43
- **Step 3: Spawn Coordinator (REQUIRED - Execute this command now via Bash tool)**
52
+ **Step 5: Spawn Coordinator (REQUIRED - Execute this command now via Bash tool)**
44
53
  ```bash
45
54
  npx claude-flow-novice agent cfn-v3-coordinator \
46
55
  --task-id "$TASK_ID" \
@@ -49,10 +58,10 @@ npx claude-flow-novice agent cfn-v3-coordinator \
49
58
  --background=true
50
59
  ```
51
60
 
52
- **Step 4: Inform User**
61
+ **Step 6: Inform User**
53
62
  After spawning coordinator, tell user:
54
63
  - ✅ CFN Loop coordinator spawned with task ID: $TASK_ID
55
- - 📊 Monitor progress: `redis-cli HGETALL "cfn_loop:task:$TASK_ID:context"`
64
+ - 📊 Monitor progress: `redis-cli -h $CFN_REDIS_HOST -p $CFN_REDIS_PORT HGETALL "cfn_loop:task:$TASK_ID:context"`
56
65
  - 🌐 Web dashboard: http://localhost:3000
57
66
 
58
67
  ---
@@ -61,6 +61,21 @@ mkdir -p "$CFN_TELEMETRY_DIR"
61
61
  # shellcheck source=./security_utils.sh
62
62
  source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/security_utils.sh"
63
63
 
64
+ ##############################################################################
65
+ # Input Sanitization (Security)
66
+ ##############################################################################
67
+ sanitize_input() {
68
+ local input="$1"
69
+ local max_length="${2:-256}" # Default max length 256 chars
70
+
71
+ # Truncate to max length
72
+ input="${input:0:$max_length}"
73
+
74
+ # Remove dangerous characters (only allow alphanumeric, dash, underscore, dot, comma, colon, space, forward slash)
75
+ # This covers task IDs, agent types, file paths, and JSON-like structures
76
+ echo "$input" | sed 's/[^a-zA-Z0-9._:, /-]//g'
77
+ }
78
+
64
79
  HELPERS_DIR="$SCRIPT_DIR/helpers"
65
80
  REDIS_COORD_SKILL="$PROJECT_ROOT/.claude/skills/cfn-redis-coordination"
66
81
 
@@ -142,6 +157,10 @@ while [[ $# -gt 0 ]]; do
142
157
  echo "Error: --loop3-agents requires a value"
143
158
  exit 1
144
159
  fi
160
+ if [[ -z "$2" ]]; then
161
+ echo "Error: --loop3-agents value cannot be empty"
162
+ exit 1
163
+ fi
145
164
  validate_agent_list "$2" || { echo "Invalid Loop 3 agent list"; exit 1; }
146
165
  LOOP3_AGENTS="$2"
147
166
  shift 2
@@ -151,6 +170,10 @@ while [[ $# -gt 0 ]]; do
151
170
  echo "Error: --loop2-agents requires a value"
152
171
  exit 1
153
172
  fi
173
+ if [[ -z "$2" ]]; then
174
+ echo "Error: --loop2-agents value cannot be empty"
175
+ exit 1
176
+ fi
154
177
  validate_agent_list "$2" || { echo "Invalid Loop 2 agent list"; exit 1; }
155
178
  LOOP2_AGENTS="$2"
156
179
  shift 2
@@ -160,6 +183,10 @@ while [[ $# -gt 0 ]]; do
160
183
  echo "Error: --product-owner requires a value"
161
184
  exit 1
162
185
  fi
186
+ if [[ -z "$2" ]]; then
187
+ echo "Error: --product-owner value cannot be empty"
188
+ exit 1
189
+ fi
163
190
  PRODUCT_OWNER=$(sanitize_input "$2") || { echo "Invalid product owner"; exit 1; }
164
191
  shift 2
165
192
  ;;
@@ -553,22 +580,43 @@ function spawn_loop3_agents() {
553
580
  safe_agent_id=$(sanitize_input "$UNIQUE_AGENT_ID") || continue
554
581
 
555
582
  # Dual-mode agent spawning: Docker or CLI
556
- # Docker mode: CFN_DOCKER_MODE=true or Docker socket available
557
- # CLI mode: Default (uses npx)
558
- if [[ "${CFN_DOCKER_MODE:-false}" == "true" ]] || [[ -S /var/run/docker.sock ]]; then
583
+ # Mode Selection Priority:
584
+ # 1. Explicit CFN_DOCKER_MODE='true'/'false' (highest priority - user override)
585
+ # 2. Automatic Docker socket detection (if CFN_DOCKER_MODE unset)
586
+ # 3. Default CLI mode (fallback if no Docker socket)
587
+ #
588
+ # BUG FIX: Respect CFN_DOCKER_MODE='false' even when Docker socket exists
589
+ SPAWN_MODE="cli" # Default
590
+ SPAWN_REASON=""
591
+
592
+ if [[ "${CFN_DOCKER_MODE:-}" == "true" ]]; then
593
+ SPAWN_MODE="docker"
594
+ SPAWN_REASON="explicit CFN_DOCKER_MODE=true"
595
+ elif [[ "${CFN_DOCKER_MODE:-}" == "false" ]]; then
596
+ SPAWN_MODE="cli"
597
+ SPAWN_REASON="explicit CFN_DOCKER_MODE=false (overrides Docker socket detection)"
598
+ elif [[ -S /var/run/docker.sock ]]; then
599
+ SPAWN_MODE="docker"
600
+ SPAWN_REASON="automatic Docker socket detection"
601
+ else
602
+ SPAWN_MODE="cli"
603
+ SPAWN_REASON="default (no Docker socket)"
604
+ fi
605
+
606
+ if [[ "$SPAWN_MODE" == "docker" ]]; then
559
607
  # Docker-based spawning (prevents WebAssembly OOM)
560
- echo " → Docker mode: spawning via container" >&2
608
+ echo " → Docker mode: ${SPAWN_REASON}" >&2
561
609
 
562
610
  # SECURITY FIX: Sanitize Docker environment variables to prevent command injection
563
- CFN_DOCKER_IMAGE_SAFE=$(sanitize_docker_var "${CFN_DOCKER_IMAGE:-claude-flow-novice:agent}") || {
611
+ CFN_DOCKER_IMAGE_SAFE=$(sanitize_input "${CFN_DOCKER_IMAGE:-claude-flow-novice:agent}") || {
564
612
  echo "❌ Invalid CFN_DOCKER_IMAGE" >&2
565
613
  exit 1
566
614
  }
567
- CFN_DOCKER_NETWORK_SAFE=$(sanitize_docker_var "${CFN_DOCKER_NETWORK:-mcp-network}") || {
615
+ CFN_DOCKER_NETWORK_SAFE=$(sanitize_input "${CFN_DOCKER_NETWORK:-mcp-network}") || {
568
616
  echo "❌ Invalid CFN_DOCKER_NETWORK" >&2
569
617
  exit 1
570
618
  }
571
- CFN_MEMORY_LIMIT_SAFE=$(sanitize_docker_var "${CFN_MEMORY_LIMIT:-2g}") || {
619
+ CFN_MEMORY_LIMIT_SAFE=$(sanitize_input "${CFN_MEMORY_LIMIT:-2g}") || {
572
620
  echo "❌ Invalid CFN_MEMORY_LIMIT" >&2
573
621
  exit 1
574
622
  }
@@ -619,7 +667,7 @@ function spawn_loop3_agents() {
619
667
  AGENT_PID=$!
620
668
  else
621
669
  # CLI-based spawning (traditional approach)
622
- echo " → CLI mode: spawning via npx" >&2
670
+ echo " → CLI mode: ${SPAWN_REASON}" >&2
623
671
 
624
672
  if command -v execute_instrumented >/dev/null 2>&1; then
625
673
  execute_instrumented "npx" "$CFN_VALIDATION_TIMEOUT" "$CFN_MEMORY_LIMIT" \
@@ -20,8 +20,9 @@ AGENT_ID=${3:-""}
20
20
  TIMEOUT=${4:-120}
21
21
 
22
22
  # Redis configuration
23
- REDIS_HOST=${REDIS_HOST:-"localhost"}
24
- REDIS_PORT=${REDIS_PORT:-6379}
23
+ # Support both REDIS_HOST and CFN_REDIS_HOST (TypeScript uses CFN_REDIS_HOST)
24
+ REDIS_HOST=${CFN_REDIS_HOST:-${REDIS_HOST:-"localhost"}}
25
+ REDIS_PORT=${CFN_REDIS_PORT:-${REDIS_PORT:-6379}}
25
26
  REDIS_DB=${REDIS_DB:-0}
26
27
 
27
28
  # Debug output
@@ -21,8 +21,9 @@ redis-cli() {
21
21
  export -f redis-cli
22
22
 
23
23
  # Optional: Set Redis connection defaults
24
- export REDIS_HOST="${REDIS_HOST:-localhost}"
25
- export REDIS_PORT="${REDIS_PORT:-6379}"
24
+ # Support both REDIS_HOST and CFN_REDIS_HOST (TypeScript uses CFN_REDIS_HOST)
25
+ export REDIS_HOST="${CFN_REDIS_HOST:-${REDIS_HOST:-localhost}}"
26
+ export REDIS_PORT="${CFN_REDIS_PORT:-${REDIS_PORT:-6379}}"
26
27
 
27
28
  # Helper: Check if Redis is available (useful for conditional logic)
28
29
  is_redis_available() {
@@ -21,26 +21,35 @@ MODE: Parse from --mode flag or default to "standard"
21
21
  MAX_ITERATIONS: Parse from --max-iterations flag or default to 10
22
22
  ```
23
23
 
24
- **Step 2: Generate Task ID**
24
+ **Step 2: Set Redis Environment Variables (REQUIRED for non-Docker environments)**
25
+ ```bash
26
+ # Set Redis connection parameters for CLI mode
27
+ export CFN_REDIS_HOST=localhost
28
+ export CFN_REDIS_PORT=6379
29
+
30
+ echo "✅ Redis environment: $CFN_REDIS_HOST:$CFN_REDIS_PORT"
31
+ ```
32
+
33
+ **Step 3: Generate Task ID**
25
34
  ```bash
26
35
  TASK_ID="cfn-cli-$(date +%s%N | tail -c 7)-${RANDOM}"
27
36
  ```
28
37
 
29
- **Step 2.5: Verify Redis Availability (REQUIRED for CLI mode coordination)**
38
+ **Step 4: Verify Redis Availability (REQUIRED for CLI mode coordination)**
30
39
  ```bash
31
40
  # Verify Redis availability (REQUIRED for CLI mode coordination)
32
- if ! redis-cli PING >/dev/null 2>&1; then
33
- echo "❌ ERROR: Redis not available"
41
+ if ! redis-cli -h "$CFN_REDIS_HOST" -p "$CFN_REDIS_PORT" PING >/dev/null 2>&1; then
42
+ echo "❌ ERROR: Redis not available at $CFN_REDIS_HOST:$CFN_REDIS_PORT"
34
43
  echo " CLI mode requires Redis for coordination"
35
44
  echo " Start Redis: redis-server"
36
45
  echo " Or use Task mode: /cfn-loop-task"
37
46
  exit 1
38
47
  fi
39
48
 
40
- echo "✅ Redis available"
49
+ echo "✅ Redis available at $CFN_REDIS_HOST:$CFN_REDIS_PORT"
41
50
  ```
42
51
 
43
- **Step 3: Spawn Coordinator (REQUIRED - Execute this command now via Bash tool)**
52
+ **Step 5: Spawn Coordinator (REQUIRED - Execute this command now via Bash tool)**
44
53
  ```bash
45
54
  npx claude-flow-novice agent cfn-v3-coordinator \
46
55
  --task-id "$TASK_ID" \
@@ -49,10 +58,10 @@ npx claude-flow-novice agent cfn-v3-coordinator \
49
58
  --background=true
50
59
  ```
51
60
 
52
- **Step 4: Inform User**
61
+ **Step 6: Inform User**
53
62
  After spawning coordinator, tell user:
54
63
  - ✅ CFN Loop coordinator spawned with task ID: $TASK_ID
55
- - 📊 Monitor progress: `redis-cli HGETALL "cfn_loop:task:$TASK_ID:context"`
64
+ - 📊 Monitor progress: `redis-cli -h $CFN_REDIS_HOST -p $CFN_REDIS_PORT HGETALL "cfn_loop:task:$TASK_ID:context"`
56
65
  - 🌐 Web dashboard: http://localhost:3000
57
66
 
58
67
  ---
@@ -61,6 +61,21 @@ mkdir -p "$CFN_TELEMETRY_DIR"
61
61
  # shellcheck source=./security_utils.sh
62
62
  source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/security_utils.sh"
63
63
 
64
+ ##############################################################################
65
+ # Input Sanitization (Security)
66
+ ##############################################################################
67
+ sanitize_input() {
68
+ local input="$1"
69
+ local max_length="${2:-256}" # Default max length 256 chars
70
+
71
+ # Truncate to max length
72
+ input="${input:0:$max_length}"
73
+
74
+ # Remove dangerous characters (only allow alphanumeric, dash, underscore, dot, comma, colon, space, forward slash)
75
+ # This covers task IDs, agent types, file paths, and JSON-like structures
76
+ echo "$input" | sed 's/[^a-zA-Z0-9._:, /-]//g'
77
+ }
78
+
64
79
  HELPERS_DIR="$SCRIPT_DIR/helpers"
65
80
  REDIS_COORD_SKILL="$PROJECT_ROOT/.claude/skills/cfn-redis-coordination"
66
81
 
@@ -142,6 +157,10 @@ while [[ $# -gt 0 ]]; do
142
157
  echo "Error: --loop3-agents requires a value"
143
158
  exit 1
144
159
  fi
160
+ if [[ -z "$2" ]]; then
161
+ echo "Error: --loop3-agents value cannot be empty"
162
+ exit 1
163
+ fi
145
164
  validate_agent_list "$2" || { echo "Invalid Loop 3 agent list"; exit 1; }
146
165
  LOOP3_AGENTS="$2"
147
166
  shift 2
@@ -151,6 +170,10 @@ while [[ $# -gt 0 ]]; do
151
170
  echo "Error: --loop2-agents requires a value"
152
171
  exit 1
153
172
  fi
173
+ if [[ -z "$2" ]]; then
174
+ echo "Error: --loop2-agents value cannot be empty"
175
+ exit 1
176
+ fi
154
177
  validate_agent_list "$2" || { echo "Invalid Loop 2 agent list"; exit 1; }
155
178
  LOOP2_AGENTS="$2"
156
179
  shift 2
@@ -160,6 +183,10 @@ while [[ $# -gt 0 ]]; do
160
183
  echo "Error: --product-owner requires a value"
161
184
  exit 1
162
185
  fi
186
+ if [[ -z "$2" ]]; then
187
+ echo "Error: --product-owner value cannot be empty"
188
+ exit 1
189
+ fi
163
190
  PRODUCT_OWNER=$(sanitize_input "$2") || { echo "Invalid product owner"; exit 1; }
164
191
  shift 2
165
192
  ;;
@@ -553,22 +580,43 @@ function spawn_loop3_agents() {
553
580
  safe_agent_id=$(sanitize_input "$UNIQUE_AGENT_ID") || continue
554
581
 
555
582
  # Dual-mode agent spawning: Docker or CLI
556
- # Docker mode: CFN_DOCKER_MODE=true or Docker socket available
557
- # CLI mode: Default (uses npx)
558
- if [[ "${CFN_DOCKER_MODE:-false}" == "true" ]] || [[ -S /var/run/docker.sock ]]; then
583
+ # Mode Selection Priority:
584
+ # 1. Explicit CFN_DOCKER_MODE='true'/'false' (highest priority - user override)
585
+ # 2. Automatic Docker socket detection (if CFN_DOCKER_MODE unset)
586
+ # 3. Default CLI mode (fallback if no Docker socket)
587
+ #
588
+ # BUG FIX: Respect CFN_DOCKER_MODE='false' even when Docker socket exists
589
+ SPAWN_MODE="cli" # Default
590
+ SPAWN_REASON=""
591
+
592
+ if [[ "${CFN_DOCKER_MODE:-}" == "true" ]]; then
593
+ SPAWN_MODE="docker"
594
+ SPAWN_REASON="explicit CFN_DOCKER_MODE=true"
595
+ elif [[ "${CFN_DOCKER_MODE:-}" == "false" ]]; then
596
+ SPAWN_MODE="cli"
597
+ SPAWN_REASON="explicit CFN_DOCKER_MODE=false (overrides Docker socket detection)"
598
+ elif [[ -S /var/run/docker.sock ]]; then
599
+ SPAWN_MODE="docker"
600
+ SPAWN_REASON="automatic Docker socket detection"
601
+ else
602
+ SPAWN_MODE="cli"
603
+ SPAWN_REASON="default (no Docker socket)"
604
+ fi
605
+
606
+ if [[ "$SPAWN_MODE" == "docker" ]]; then
559
607
  # Docker-based spawning (prevents WebAssembly OOM)
560
- echo " → Docker mode: spawning via container" >&2
608
+ echo " → Docker mode: ${SPAWN_REASON}" >&2
561
609
 
562
610
  # SECURITY FIX: Sanitize Docker environment variables to prevent command injection
563
- CFN_DOCKER_IMAGE_SAFE=$(sanitize_docker_var "${CFN_DOCKER_IMAGE:-claude-flow-novice:agent}") || {
611
+ CFN_DOCKER_IMAGE_SAFE=$(sanitize_input "${CFN_DOCKER_IMAGE:-claude-flow-novice:agent}") || {
564
612
  echo "❌ Invalid CFN_DOCKER_IMAGE" >&2
565
613
  exit 1
566
614
  }
567
- CFN_DOCKER_NETWORK_SAFE=$(sanitize_docker_var "${CFN_DOCKER_NETWORK:-mcp-network}") || {
615
+ CFN_DOCKER_NETWORK_SAFE=$(sanitize_input "${CFN_DOCKER_NETWORK:-mcp-network}") || {
568
616
  echo "❌ Invalid CFN_DOCKER_NETWORK" >&2
569
617
  exit 1
570
618
  }
571
- CFN_MEMORY_LIMIT_SAFE=$(sanitize_docker_var "${CFN_MEMORY_LIMIT:-2g}") || {
619
+ CFN_MEMORY_LIMIT_SAFE=$(sanitize_input "${CFN_MEMORY_LIMIT:-2g}") || {
572
620
  echo "❌ Invalid CFN_MEMORY_LIMIT" >&2
573
621
  exit 1
574
622
  }
@@ -619,7 +667,7 @@ function spawn_loop3_agents() {
619
667
  AGENT_PID=$!
620
668
  else
621
669
  # CLI-based spawning (traditional approach)
622
- echo " → CLI mode: spawning via npx" >&2
670
+ echo " → CLI mode: ${SPAWN_REASON}" >&2
623
671
 
624
672
  if command -v execute_instrumented >/dev/null 2>&1; then
625
673
  execute_instrumented "npx" "$CFN_VALIDATION_TIMEOUT" "$CFN_MEMORY_LIMIT" \
@@ -20,8 +20,9 @@ AGENT_ID=${3:-""}
20
20
  TIMEOUT=${4:-120}
21
21
 
22
22
  # Redis configuration
23
- REDIS_HOST=${REDIS_HOST:-"localhost"}
24
- REDIS_PORT=${REDIS_PORT:-6379}
23
+ # Support both REDIS_HOST and CFN_REDIS_HOST (TypeScript uses CFN_REDIS_HOST)
24
+ REDIS_HOST=${CFN_REDIS_HOST:-${REDIS_HOST:-"localhost"}}
25
+ REDIS_PORT=${CFN_REDIS_PORT:-${REDIS_PORT:-6379}}
25
26
  REDIS_DB=${REDIS_DB:-0}
26
27
 
27
28
  # Debug output
@@ -21,8 +21,9 @@ redis-cli() {
21
21
  export -f redis-cli
22
22
 
23
23
  # Optional: Set Redis connection defaults
24
- export REDIS_HOST="${REDIS_HOST:-localhost}"
25
- export REDIS_PORT="${REDIS_PORT:-6379}"
24
+ # Support both REDIS_HOST and CFN_REDIS_HOST (TypeScript uses CFN_REDIS_HOST)
25
+ export REDIS_HOST="${CFN_REDIS_HOST:-${REDIS_HOST:-localhost}}"
26
+ export REDIS_PORT="${CFN_REDIS_PORT:-${REDIS_PORT:-6379}}"
26
27
 
27
28
  # Helper: Check if Redis is available (useful for conditional logic)
28
29
  is_redis_available() {