claude-flow-novice 2.14.36 → 2.15.0

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.
Files changed (34) hide show
  1. package/.claude/commands/cfn-loop-cli.md +491 -456
  2. package/.claude/commands/switch-api.md +33 -12
  3. package/.claude/skills/cfn-agent-spawning/get-agent-provider-env.sh +107 -0
  4. package/.claude/skills/cfn-agent-spawning/parse-agent-provider.sh +59 -0
  5. package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +24 -6
  6. package/.claude/skills/cfn-loop-orchestration/helpers/spawn-agents.sh +18 -9
  7. package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +220 -220
  8. package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +5 -0
  9. package/claude-assets/agents/custom/claude-code-expert.md +151 -2
  10. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +43 -3
  11. package/claude-assets/commands/cfn-loop-cli.md +491 -456
  12. package/claude-assets/commands/switch-api.md +33 -12
  13. package/claude-assets/skills/cfn-agent-spawning/get-agent-provider-env.sh +107 -0
  14. package/claude-assets/skills/cfn-agent-spawning/parse-agent-provider.sh +59 -0
  15. package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +24 -6
  16. package/claude-assets/skills/cfn-error-logging/SKILL.md +339 -0
  17. package/claude-assets/skills/cfn-error-logging/cleanup-error-logs.sh +334 -0
  18. package/claude-assets/skills/cfn-error-logging/integrate-cli.sh +232 -0
  19. package/claude-assets/skills/cfn-error-logging/integrate-docker.sh +294 -0
  20. package/claude-assets/skills/cfn-error-logging/invoke-error-logging.sh +839 -0
  21. package/claude-assets/skills/cfn-error-logging/test-error-logging.sh +475 -0
  22. package/claude-assets/skills/cfn-loop-orchestration/helpers/spawn-agents.sh +18 -9
  23. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +5 -3
  24. package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +220 -220
  25. package/claude-assets/skills/cfn-task-mode-sanitize/task-mode-env-sanitizer.sh +21 -9
  26. package/claude-assets/skills/cfn-validation-runner-instrumentation/wrapped-executor.sh +3 -1
  27. package/dist/hello.js +27 -3
  28. package/dist/hello.js.map +1 -1
  29. package/dist/server.js +194 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/server.test.js +207 -0
  32. package/dist/server.test.js.map +1 -0
  33. package/package.json +2 -1
  34. package/scripts/switch-api.sh +140 -12
@@ -0,0 +1,839 @@
1
+ #!/bin/bash
2
+
3
+ ##############################################################################
4
+ # CFN Error Logging Skill - Main Invocation Script
5
+ # Version: 1.0.0
6
+ #
7
+ # Comprehensive error logging and diagnostic capture for CFN Loop failures
8
+ # Creates detailed error reports that users can send for debugging
9
+ #
10
+ # Usage:
11
+ # invoke-error-logging.sh --action <capture|report|cleanup|list> \
12
+ # --task-id <unique-id> \
13
+ # [--error-type <type>] \
14
+ # [--error-message <message>] \
15
+ # [--exit-code <number>] \
16
+ # [--context <json>]
17
+ ##############################################################################
18
+
19
+ set -euo pipefail
20
+
21
+ # Determine script directory
22
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
24
+
25
+ # Configuration
26
+ LOG_BASE_DIR="/tmp/cfn_error_logs"
27
+ RETENTION_DAYS="${CFN_ERROR_LOG_RETENTION:-7}"
28
+ MAX_LOG_SIZE_MB="${CFN_ERROR_LOG_MAX_SIZE_MB:-100}"
29
+
30
+ # Initialize variables
31
+ ACTION=""
32
+ TASK_ID=""
33
+ ERROR_TYPE=""
34
+ ERROR_MESSAGE=""
35
+ EXIT_CODE=""
36
+ CONTEXT_JSON=""
37
+ FORMAT="markdown"
38
+ SINCE_TIME=""
39
+
40
+ # Helper functions
41
+ log() {
42
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
43
+ }
44
+
45
+ show_usage() {
46
+ cat << EOF
47
+ CFN Error Logging Skill v1.0.0
48
+
49
+ Usage: $0 --action <action> --task-id <id> [options]
50
+
51
+ ACTIONS:
52
+ capture Capture error data and diagnostics
53
+ report Generate user-friendly error report
54
+ cleanup Clean up old error logs
55
+ list List error logs
56
+ diagnostics Run system diagnostics
57
+ validate Validate dependencies
58
+
59
+ REQUIRED:
60
+ --action <action> Action to perform
61
+
62
+ OPTIONAL:
63
+ --task-id <id> CFN Loop task identifier (required for capture, report, list)
64
+
65
+ OPTIONS:
66
+ --error-type <type> Type of error (orchestrator, agent-spawn, timeout, etc.)
67
+ --error-message <msg> Human-readable error description
68
+ --exit-code <code> Process exit code
69
+ --context <json> Additional context data
70
+ --format <format> Report format (markdown|json)
71
+ --since <time> List errors since time (e.g., "24h", "7d")
72
+ --retention-days <n> Cleanup retention period (default: 7)
73
+
74
+ EXAMPLES:
75
+ # Capture error on CFN Loop failure
76
+ $0 --action capture --task-id "cfn-cli-1731234567" --error-type "orchestrator" --error-message "Agent spawning failed" --exit-code 1
77
+
78
+ # Generate user report
79
+ $0 --action report --task-id "cfn-cli-1731234567" --format markdown
80
+
81
+ # List recent errors
82
+ $0 --action list --since "24h" --format table
83
+
84
+ # Clean old logs
85
+ $0 --action cleanup --retention-days 7
86
+ EOF
87
+ }
88
+
89
+ validate_parameters() {
90
+ if [ -z "$ACTION" ]; then
91
+ echo "❌ Error: Missing required action parameter"
92
+ echo "Use --help for usage information"
93
+ exit 1
94
+ fi
95
+
96
+ # Task ID is required for most actions but optional for diagnostics, validate, cleanup, and list
97
+ case "$ACTION" in
98
+ diagnostics|validate|cleanup|list)
99
+ # Task ID optional for these actions
100
+ ;;
101
+ *)
102
+ if [ -z "$TASK_ID" ]; then
103
+ echo "❌ Error: Missing required task-id parameter for action '$ACTION'"
104
+ echo "Use --help for usage information"
105
+ exit 1
106
+ fi
107
+ ;;
108
+ esac
109
+
110
+ # Validate action
111
+ case "$ACTION" in
112
+ capture|report|cleanup|list|diagnostics|validate)
113
+ ;;
114
+ *)
115
+ echo "❌ Error: Invalid action '$ACTION'"
116
+ echo "Valid actions: capture, report, cleanup, list, diagnostics, validate"
117
+ exit 1
118
+ ;;
119
+ esac
120
+
121
+ # Validate task ID format (only if task ID is provided)
122
+ if [ -n "$TASK_ID" ] && [[ ! "$TASK_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
123
+ echo "❌ Error: Invalid task ID format"
124
+ echo "Task ID should contain only letters, numbers, hyphens, and underscores"
125
+ exit 1
126
+ fi
127
+ }
128
+
129
+ setup_directories() {
130
+ # Create log directory structure
131
+ mkdir -p "$LOG_BASE_DIR"
132
+ mkdir -p "$LOG_BASE_DIR/reports"
133
+ mkdir -p "$LOG_BASE_DIR/compressed"
134
+
135
+ # Set permissions
136
+ chmod 755 "$LOG_BASE_DIR"
137
+ chmod 755 "$LOG_BASE_DIR/reports"
138
+ chmod 755 "$LOG_BASE_DIR/compressed"
139
+ }
140
+
141
+ collect_system_diagnostics() {
142
+ local diagnostics_file="$1"
143
+
144
+ log "Collecting system diagnostics..."
145
+
146
+ # System information
147
+ {
148
+ echo "{"
149
+ echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
150
+ echo " \"hostname\": \"$(hostname 2>/dev/null || echo 'unknown')\","
151
+ echo " \"user\": \"$(whoami 2>/dev/null || echo 'unknown')\","
152
+ echo " \"working_directory\": \"$(pwd)\","
153
+ echo " \"os\": \"$(uname -s 2>/dev/null || echo 'unknown')\","
154
+ echo " \"os_version\": \"$(uname -r 2>/dev/null || echo 'unknown')\","
155
+ echo " \"architecture\": \"$(uname -m 2>/dev/null || echo 'unknown')\","
156
+
157
+ # Hardware information
158
+ echo " \"hardware\": {"
159
+ echo " \"cpu_cores\": $(nproc 2>/dev/null || echo 'unknown'),"
160
+
161
+ if command -v free >/dev/null 2>&1; then
162
+ local mem_info=$(free -h 2>/dev/null || echo "Memory: Unknown")
163
+ echo " \"memory\": \"$mem_info\""
164
+ else
165
+ echo " \"memory\": \"Memory information unavailable\""
166
+ fi
167
+
168
+ if command -v df >/dev/null 2>&1; then
169
+ local disk_info=$(df -h / 2>/dev/null | tail -1 || echo "Disk: Unknown")
170
+ echo " \"disk\": \"$disk_info\""
171
+ else
172
+ echo " \"disk\": \"Disk information unavailable\""
173
+ fi
174
+
175
+ echo " },"
176
+
177
+ # Software information
178
+ echo " \"software\": {"
179
+
180
+ if command -v node >/dev/null 2>&1; then
181
+ echo " \"node_version\": \"$(node --version 2>/dev/null || echo 'unknown')\","
182
+ else
183
+ echo " \"node_version\": \"not found\""
184
+ fi
185
+
186
+ if command -v npx >/dev/null 2>&1; then
187
+ echo " \"npx_version\": \"$(npx --version 2>/dev/null || echo 'unknown')\","
188
+ else
189
+ echo " \"npx_version\": \"not found\""
190
+ fi
191
+
192
+ if command -v docker >/dev/null 2>&1; then
193
+ echo " \"docker_version\": \"$(docker --version 2>/dev/null || echo 'unknown')\","
194
+ else
195
+ echo " \"docker_version\": \"not found\""
196
+ fi
197
+
198
+ if command -v redis-cli >/dev/null 2>&1; then
199
+ echo " \"redis_available\": true"
200
+ if redis-cli ping >/dev/null 2>&1; then
201
+ echo " \"redis_connected\": true"
202
+ echo " \"redis_info\": \"$(redis-cli info server 2>/dev/null | head -5 | tr '\n' ' ' || echo '')\""
203
+ else
204
+ echo " \"redis_connected\": false"
205
+ fi
206
+ else
207
+ echo " \"redis_available\": false"
208
+ echo " "redis_connected": false"
209
+ fi
210
+
211
+ echo " },"
212
+
213
+ # Environment
214
+ echo " \"environment\": {"
215
+ echo " \"path\": \"${PATH:-not set}\","
216
+ echo " \"home\": \"${HOME:-not set}\","
217
+ echo " \"shell\": \"${SHELL:-not set}\","
218
+ echo " \"lang\": \"${LANG:-not set}\""
219
+ echo " },"
220
+
221
+ # Processes
222
+ if command -v pgrep >/dev/null 2>&1; then
223
+ local cfn_processes=$(pgrep -f "claude-flow-novice\|cfn-" 2>/dev/null | wc -l || echo "0")
224
+ echo " \"processes\": {"
225
+ echo " \"cfn_running\": $cfn_processes,"
226
+ echo " \"total_processes\": $(ps aux 2>/dev/null | wc -l || echo 'unknown')"
227
+ echo " }"
228
+ else
229
+ echo " \"processes\": {"
230
+ echo " \"cfn_running\": \"unknown\","
231
+ echo " \"total_processes\": \"unknown\""
232
+ echo " }"
233
+ fi
234
+
235
+ echo "}"
236
+ } > "$diagnostics_file"
237
+ }
238
+
239
+ collect_cfn_state() {
240
+ local state_file="$1"
241
+
242
+ log "Collecting CFN Loop state..."
243
+
244
+ {
245
+ echo "{"
246
+ echo " \"task_id\": \"$TASK_ID\","
247
+ echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
248
+ echo " \"error_type\": \"$ERROR_TYPE\","
249
+ echo " \"error_message\": \"$ERROR_MESSAGE\","
250
+ echo " \"exit_code\": ${EXIT_CODE:-null},"
251
+
252
+ # Redis state
253
+ if command -v redis-cli >/dev/null 2>&1 && redis-cli ping >/dev/null 2>&1; then
254
+ echo " \"redis_state\": {"
255
+ echo " \"connected\": true,"
256
+
257
+ # Task context
258
+ local task_context=$(redis-cli HGETALL "cfn_loop:task:$TASK_ID:context" 2>/dev/null || echo "")
259
+ if [ -n "$task_context" ]; then
260
+ echo " \"task_context\": {"
261
+ echo "$task_context" | sed 's/^/ "/' | sed 's/" "/", "/g' | sed 's/$/"/'
262
+ echo " },"
263
+ else
264
+ echo " \"task_context\": null,"
265
+ fi
266
+
267
+ # Agent PIDs
268
+ local agent_pids=$(redis-cli KEYS "cfn_loop:task:$TASK_ID:agent:*:pid" 2>/dev/null | wc -l || echo "0")
269
+ echo " \"tracked_agents\": $agent_pids,"
270
+
271
+ # Recent signals
272
+ local recent_signals=$(redis-cli LRANGE "swarm:$TASK_ID:*:done" 0 9 2>/dev/null | wc -l || echo "0")
273
+ echo " \"recent_signals\": $recent_signals"
274
+ echo " },"
275
+ else
276
+ echo " \"redis_state\": {"
277
+ echo " \"connected\": false,"
278
+ echo " \"reason\": \"Redis not available or not connected\""
279
+ echo " },"
280
+ fi
281
+
282
+ # Checkpoint state
283
+ local checkpoint_file="/tmp/cfn_loop_${TASK_ID}_checkpoint.json"
284
+ if [ -f "$checkpoint_file" ]; then
285
+ echo " \"checkpoint\": {"
286
+ echo " \"available\": true,"
287
+ echo " \"last_iteration\": $(jq -r '.iteration' "$checkpoint_file" 2>/dev/null || echo 'unknown'),"
288
+ echo " \"mode\": \"$(jq -r '.mode' "$checkpoint_file" 2>/dev/null || echo 'unknown')\","
289
+ echo " \"timestamp\": $(jq -r '.timestamp' "$checkpoint_file" 2>/dev/null || echo 'unknown')"
290
+ echo " },"
291
+ else
292
+ echo " \"checkpoint\": {"
293
+ echo " \"available\": false"
294
+ echo " },"
295
+ fi
296
+
297
+ # Temporary files
298
+ local temp_dir="/tmp/cfn_loop_${TASK_ID}"
299
+ if [ -d "$temp_dir" ]; then
300
+ local temp_files=$(find "$temp_dir" -type f 2>/dev/null | wc -l || echo "0")
301
+ echo " \"temp_files\": {"
302
+ echo " \"directory\": \"$temp_dir\","
303
+ echo " \"file_count\": $temp_files"
304
+ echo " },"
305
+ else
306
+ echo " \"temp_files\": null,"
307
+ fi
308
+
309
+ # Context JSON
310
+ if [ -n "$CONTEXT_JSON" ]; then
311
+ echo " \"context\": $CONTEXT_JSON"
312
+ fi
313
+
314
+ echo "}"
315
+ } > "$state_file"
316
+ }
317
+
318
+ capture_error() {
319
+ local timestamp=$(date +%s)
320
+ local error_log_file="$LOG_BASE_DIR/cfn-error-${TASK_ID}-${timestamp}.json"
321
+
322
+ log "Capturing error data for task: $TASK_ID"
323
+
324
+ setup_directories
325
+
326
+ # Create comprehensive error log
327
+ {
328
+ echo "{"
329
+ echo " \"capture_id\": \"error-${TASK_ID}-${timestamp}\","
330
+ echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
331
+ echo " \"unix_timestamp\": $timestamp,"
332
+
333
+ # Error details
334
+ echo " \"error\": {"
335
+ echo " \"type\": \"$ERROR_TYPE\","
336
+ echo " \"message\": \"$ERROR_MESSAGE\","
337
+ echo " \"exit_code\": ${EXIT_CODE:-null},"
338
+ echo " \"task_id\": \"$TASK_ID\""
339
+ echo " },"
340
+
341
+ # Include system diagnostics and CFN state
342
+ echo " \"system_diagnostics\": $(cat "${LOG_BASE_DIR}/sys-diagnostics-${timestamp}.json"),"
343
+ echo " \"cfn_state\": $(cat "${LOG_BASE_DIR}/cfn-state-${TASK_ID}-${timestamp}.json")"
344
+
345
+ echo "}"
346
+ } > "$error_log_file"
347
+
348
+ # Clean up temporary diagnostic files
349
+ rm -f "${LOG_BASE_DIR}/sys-diagnostics-${timestamp}.json" 2>/dev/null || true
350
+ rm -f "${LOG_BASE_DIR}/cfn-state-${TASK_ID}-${timestamp}.json" 2>/dev/null || true
351
+
352
+ log "Error data captured: $error_log_file"
353
+ log "Generate report with: $0 --action report --task-id $TASK_ID"
354
+ }
355
+
356
+ generate_report() {
357
+ local timestamp=$(date +%s)
358
+ local file_ext="md"
359
+
360
+ if [ "$FORMAT" = "json" ]; then
361
+ file_ext="json"
362
+ fi
363
+
364
+ local report_file="$LOG_BASE_DIR/reports/cfn-report-${TASK_ID}-${timestamp}.${file_ext}"
365
+
366
+ # Find the most recent error log for this task
367
+ local error_log=$(find "$LOG_BASE_DIR" -name "cfn-error-${TASK_ID}-*.json" -type f -printf '%T@ %p\n' 2>/dev/null | sort -n | tail -1 | cut -d' ' -f2- || echo "")
368
+
369
+ if [ -z "$error_log" ] || [ ! -f "$error_log" ]; then
370
+ echo "❌ No error log found for task: $TASK_ID"
371
+ echo "Available tasks:"
372
+ find "$LOG_BASE_DIR" -name "cfn-error-*.json" -type f -exec basename {} \; 2>/dev/null | sort -u | sed 's/cfn-error-//g' | sed 's/-[0-9]*\.json$//' | head -10
373
+ return 1
374
+ fi
375
+
376
+ log "Generating error report for task: $TASK_ID"
377
+
378
+ # Parse error log data
379
+ local error_type=$(jq -r '.error.type' "$error_log" 2>/dev/null || echo "unknown")
380
+ local error_message=$(jq -r '.error.message' "$error_log" 2>/dev/null || echo "No message")
381
+ local exit_code=$(jq -r '.error.exit_code' "$error_log" 2>/dev/null || echo "unknown")
382
+ local error_timestamp=$(jq -r '.timestamp' "$error_log" 2>/dev/null || echo "unknown")
383
+
384
+ # System diagnostics
385
+ local redis_available=$(jq -r '.system_diagnostics.software.redis_connected' "$error_log" 2>/dev/null || echo "false")
386
+ local node_version=$(jq -r '.system_diagnostics.software.node_version' "$error_log" 2>/dev/null || echo "not found")
387
+ local npx_version=$(jq -r '.system_diagnostics.software.npx_version' "$error_log" 2>/dev/null || echo "not found")
388
+
389
+ # Generate troubleshooting steps
390
+ local troubleshooting_steps=""
391
+ case "$error_type" in
392
+ "orchestrator")
393
+ troubleshooting_steps="1. ✅ Check task configuration parameters\n2. ✅ Verify orchestrator script permissions\n3. ❌ Check system resources (memory/disk)\n4. ✅ Validate agent availability"
394
+ ;;
395
+ "agent-spawn")
396
+ troubleshooting_steps="1. ✅ Check Node.js installation: node --version\n2. ✅ Check npx availability: npx --version\n3. ❌ Check Redis connection: redis-cli ping\n4. ✅ Check available memory: free -h"
397
+ ;;
398
+ "timeout")
399
+ troubleshooting_steps="1. ✅ Check system load: top\n2. ✅ Verify network connectivity\n3. ❌ Increase timeout values if needed\n4. ✅ Check for stuck processes"
400
+ ;;
401
+ "resource")
402
+ troubleshooting_steps="1. ✅ Check available memory: free -h\n2. ✅ Check disk space: df -h\n3. ❌ Close unnecessary applications\n4. ✅ Check process limits: ulimit -a"
403
+ ;;
404
+ *)
405
+ troubleshooting_steps="1. ✅ Check system diagnostics below\n2. ✅ Review error message context\n3. ❌ Check CFN Loop configuration\n4. ✅ Verify all dependencies"
406
+ ;;
407
+ esac
408
+
409
+ # Generate report
410
+ cat > "$report_file" << EOF
411
+ # CFN Loop Error Report
412
+
413
+ ## 🚨 Error Summary
414
+ - **Task ID**: $TASK_ID
415
+ - **Error Type**: $error_type
416
+ - **Message**: $error_message
417
+ - **Timestamp**: $error_timestamp
418
+ - **Exit Code**: $exit_code
419
+
420
+ ## 📋 Quick Diagnosis
421
+ **Most Likely Cause**: Based on error type $error_type
422
+ **Recommended Action**: Follow troubleshooting steps below
423
+
424
+ ## 🔧 Troubleshooting Steps
425
+ $troubleshooting_steps
426
+
427
+ ## 📊 System State
428
+
429
+ ### Software Dependencies
430
+ - **Node.js**: $node_version
431
+ - **npx**: $npx_version
432
+ - **Redis**: $(if [ "$redis_available" = "true" ]; then echo "✅ Connected"; else echo "❌ Not Connected"; fi)
433
+ - **Docker**: $(if command -v docker >/dev/null 2>&1; then docker --version | head -1; else echo "Not installed"; fi)
434
+
435
+ ### System Resources
436
+ $(jq -r '.system_diagnostics.hardware.memory' "$error_log" 2>/dev/null || echo "Memory information unavailable")
437
+ $(jq -r '.system_diagnostics.hardware.disk' "$error_log" 2>/dev/null || echo "Disk information unavailable")
438
+
439
+ ### Process Status
440
+ - **CFN Processes Running**: $(jq -r '.system_diagnostics.processes.cfn_running' "$error_log" 2>/dev/null || echo "Unknown")
441
+ - **Total Processes**: $(jq -r '.system_diagnostics.processes.total_processes' "$error_log" 2>/dev/null || echo "Unknown")
442
+
443
+ ## 📝 Send This Report
444
+ **To**: Your Claude assistant
445
+ **Include**:
446
+ - Complete error details above
447
+ - Any recent changes to your setup
448
+ - Steps you were trying to perform
449
+ - Command you executed
450
+
451
+ ## 📁 Log Files
452
+ - **Error Log**: $(basename "$error_log")
453
+ - **Log Location**: $LOG_BASE_DIR
454
+ - **Generated**: $(date)
455
+
456
+ ## 🔍 Additional Information
457
+
458
+ ### CFN Loop State
459
+ $(if [ -f "/tmp/cfn_loop_${TASK_ID}_checkpoint.json" ]; then
460
+ echo "- **Last Checkpoint**: $(jq -r '.iteration' "/tmp/cfn_loop_${TASK_ID}_checkpoint.json" 2>/dev/null || echo "Unknown")"
461
+ echo "- **Mode**: $(jq -r '.mode' "/tmp/cfn_loop_${TASK_ID}_checkpoint.json" 2>/dev/null || echo "Unknown")"
462
+ else
463
+ echo "- **No checkpoint available**"
464
+ fi)
465
+
466
+ ### Temporary Files
467
+ $(if [ -d "/tmp/cfn_loop_${TASK_ID}" ]; then
468
+ local temp_count=$(find "/tmp/cfn_loop_${TASK_ID}" -type f 2>/dev/null | wc -l || echo "0")
469
+ echo "- **Temp Files**: $temp_count files"
470
+ else
471
+ echo "- **No temporary files**"
472
+ fi)
473
+ EOF
474
+
475
+ log "Error report generated: $report_file"
476
+ echo ""
477
+ echo "📋 Error report saved to: $report_file"
478
+ echo "📤 Send this file to your Claude assistant for debugging help"
479
+ echo ""
480
+ echo "💡 Quick copy command:"
481
+ echo " cat $report_file | pbcopy # macOS"
482
+ echo " cat $report_file | xclip -selection clipboard # Linux"
483
+ }
484
+
485
+ list_error_logs() {
486
+ local query="$1"
487
+
488
+ log "Listing error logs..."
489
+
490
+ case "$FORMAT" in
491
+ "table")
492
+ echo "Available Error Logs:"
493
+ printf "%-20s %-12s %-20s %-30s\n" "Task ID" "Type" "Timestamp" "Error Message"
494
+ printf "%-20s %-12s %-20s %-30s\n" "--------------------" "------------" "--------------------" "------------------------------"
495
+
496
+ find "$LOG_BASE_DIR" -name "cfn-error-*.json" -type f -printf '%T@ %p\n' 2>/dev/null | sort -n | while read -r timestamp file; do
497
+ local task_id=$(basename "$file" | sed 's/cfn-error-//' | sed 's/-[0-9]*\.json$//')
498
+ local error_type=$(jq -r '.error.type' "$file" 2>/dev/null || echo "unknown")
499
+ local error_message=$(jq -r '.error.message' "$file" 2>/dev/null | head -c 30)
500
+ local file_timestamp=$(date -d "@$timestamp" "+%Y-%m-%d %H:%M" 2>/dev/null || echo "unknown")
501
+
502
+ printf "%-20s %-12s %-20s %-30s\n" "$task_id" "$error_type" "$file_timestamp" "$error_message"
503
+ done
504
+ ;;
505
+ "json")
506
+ find "$LOG_BASE_DIR" -name "cfn-error-*.json" -type f -exec basename {} \; 2>/dev/null | sort -u | sed 's/cfn-error-//g' | sed 's/-[0-9]*\.json$//' | jq -R '{
507
+ "task_id": .,
508
+ "logs": [
509
+ (input | split("\n")[] | select(length > 0) | . as $task_id |
510
+ "cfn-error-\($task_id)-*.json" |
511
+ [
512
+ inputs | select(test("cfn-error-\($task_id)-"; .)) |
513
+ {
514
+ "file": .,
515
+ "timestamp": (inputs | test(.; test("cfn-error-\($task_id)-"; .)) | input_filename | split("-") | .[2] | split("\\.") | .[0] | tonumber) | strftime("%Y-%m-%d %H:%M:%S")
516
+ }
517
+ ]
518
+ )
519
+ ]
520
+ }' | while read -r line; do
521
+ if [ -n "$query" ] && [[ "$line" =~ "$query" ]]; then
522
+ echo "$line"
523
+ elif [ -z "$query" ]; then
524
+ echo "$line"
525
+ fi
526
+ done
527
+ ;;
528
+ *)
529
+ echo "Available error logs:"
530
+ find "$LOG_BASE_DIR" -name "cfn-error-*.json" -type f -exec basename {} \; 2>/dev/null | sort -u | sed 's/cfn-error-//g' | sed 's/-[0-9]*\.json$//'
531
+ ;;
532
+ esac
533
+ }
534
+
535
+ cleanup_logs() {
536
+ local retention_secs=$((RETENTION_DAYS * 24 * 3600))
537
+ local current_time=$(date +%s)
538
+ local cutoff_time=$((current_time - retention_secs))
539
+
540
+ log "Cleaning up error logs older than $RETENTION_DAYS days..."
541
+
542
+ local cleaned_count=0
543
+ local compressed_count=0
544
+
545
+ # Compress old logs
546
+ while IFS= read -r -d '' file; do
547
+ local file_time=$(date -r "$file" +%s 2>/dev/null || echo "0")
548
+ if [ "$file_time" -lt "$cutoff_time" ]; then
549
+ if gzip "$file" 2>/dev/null; then
550
+ mv "$file.gz" "$LOG_BASE_DIR/compressed/"
551
+ ((compressed_count++))
552
+ fi
553
+ fi
554
+ done < <(find "$LOG_BASE_DIR" -name "cfn-error-*.json" -type f -print0 2>/dev/null)
555
+
556
+ # Remove very old compressed logs (30 days)
557
+ local old_cutoff=$((current_time - (30 * 24 * 3600)))
558
+ while IFS= read -r -d '' file; do
559
+ local file_time=$(date -r "$file" +%s 2>/dev/null || echo "0")
560
+ if [ "$file_time" -lt "$old_cutoff" ]; then
561
+ rm -f "$file"
562
+ ((cleaned_count++))
563
+ fi
564
+ done < <(find "$LOG_BASE_DIR/compressed" -name "*.json.gz" -type f -print0 2>/dev/null)
565
+
566
+ # Check total size and enforce limit
567
+ local total_size=$(du -sm "$LOG_BASE_DIR" 2>/dev/null | cut -f1 || echo "0")
568
+ if [ "$total_size" -gt "$MAX_LOG_SIZE_MB" ]; then
569
+ log "Log directory size (${total_size}MB) exceeds limit (${MAX_LOG_SIZE_MB}MB)"
570
+ # Remove oldest files until under limit
571
+ while [ "$total_size" -gt "$MAX_LOG_SIZE_MB" ]; do
572
+ local oldest_file=$(find "$LOG_BASE_DIR" -name "*.json*" -type f -printf '%T@ %p\n' 2>/dev/null | sort -n | head -1 | cut -d' ' -f2-)
573
+ if [ -n "$oldest_file" ] && [ -f "$oldest_file" ]; then
574
+ rm -f "$oldest_file"
575
+ total_size=$(du -sm "$LOG_BASE_DIR" 2>/dev/null | cut -f1 || echo "0")
576
+ fi
577
+ done
578
+ fi
579
+
580
+ log "Cleanup completed: $compressed_count files compressed, $cleaned_count files removed"
581
+ }
582
+
583
+ run_diagnostics() {
584
+ log "Running system diagnostics..."
585
+
586
+ echo "=== CFN Loop System Diagnostics ==="
587
+ echo ""
588
+
589
+ # Basic system info
590
+ echo "🖥️ System Information:"
591
+ echo " Hostname: $(hostname 2>/dev/null || echo 'unknown')"
592
+ echo " User: $(whoami 2>/dev/null || echo 'unknown')"
593
+ echo " Shell: $SHELL"
594
+ echo " Working Directory: $(pwd)"
595
+ echo ""
596
+
597
+ # Dependency checks
598
+ echo "📦 Dependency Status:"
599
+
600
+ local deps_status=0
601
+
602
+ if command -v node >/dev/null 2>&1; then
603
+ echo " ✅ Node.js: $(node --version)"
604
+ else
605
+ echo " ❌ Node.js: NOT FOUND"
606
+ ((deps_status++))
607
+ fi
608
+
609
+ if command -v npx >/dev/null 2>&1; then
610
+ echo " ✅ npx: $(npx --version)"
611
+ else
612
+ echo " ❌ npx: NOT FOUND"
613
+ ((deps_status++))
614
+ fi
615
+
616
+ if command -v docker >/dev/null 2>&1; then
617
+ echo " ✅ Docker: $(docker --version | head -1)"
618
+ else
619
+ echo " ⚠️ Docker: NOT FOUND (optional)"
620
+ fi
621
+
622
+ if command -v redis-cli >/dev/null 2>&1; then
623
+ echo " ✅ Redis CLI: Available"
624
+ if redis-cli ping >/dev/null 2>&1; then
625
+ echo " ✅ Redis Server: CONNECTED"
626
+ else
627
+ echo " ❌ Redis Server: NOT CONNECTED"
628
+ ((deps_status++))
629
+ fi
630
+ else
631
+ echo " ❌ Redis CLI: NOT FOUND"
632
+ ((deps_status++))
633
+ fi
634
+
635
+ echo ""
636
+
637
+ # Resource status
638
+ echo "💻 Resource Status:"
639
+
640
+ if command -v free >/dev/null 2>&1; then
641
+ echo " Memory: $(free -h | grep '^Mem:' | awk '{print $3 "/" $2 " (" $4 ")"}')"
642
+ echo " Swap: $(free -h | grep '^Swap:' | awk '{print $3 "/" $2 " (" $4 ")"}' || echo 'Swap not available')"
643
+ else
644
+ echo " Memory: Information unavailable"
645
+ fi
646
+
647
+ if command -v df >/dev/null 2>&1; then
648
+ echo " Disk: $(df -h / | tail -1 | awk '{print $3 "/" $2 " (" $4 ")"}')"
649
+ else
650
+ echo " Disk: Information unavailable"
651
+ fi
652
+
653
+ echo ""
654
+
655
+ # CFN Loop specific
656
+ echo "🔄 CFN Loop Status:"
657
+
658
+ local cfn_processes=$(pgrep -f "claude-flow-novice\|cfn-" 2>/dev/null | wc -l || echo "0")
659
+ echo " CFN Processes Running: $cfn_processes"
660
+
661
+ if [ -d "/tmp" ]; then
662
+ local cfn_temp_dirs=$(find /tmp -name "cfn_loop_*" -type d 2>/dev/null | wc -l || echo "0")
663
+ echo " Temporary Directories: $cfn_temp_dirs"
664
+ fi
665
+
666
+ echo ""
667
+
668
+ # Error log status
669
+ if [ -d "$LOG_BASE_DIR" ]; then
670
+ local error_count=$(find "$LOG_BASE_DIR" -name "cfn-error-*.json" -type f 2>/dev/null | wc -l || echo "0")
671
+ local report_count=$(find "$LOG_BASE_DIR/reports" -name "*.md" -type f 2>/dev/null | wc -l || echo "0")
672
+ echo "📊 Error Log Status:"
673
+ echo " Error Logs: $error_count"
674
+ echo " Reports Generated: $report_count"
675
+ echo " Log Directory: $LOG_BASE_DIR"
676
+ echo " Total Size: $(du -sh "$LOG_BASE_DIR" 2>/dev/null | cut -f1 || echo 'unknown')"
677
+ else
678
+ echo "📊 Error Log Status: Directory not found"
679
+ fi
680
+
681
+ echo ""
682
+
683
+ # Overall status
684
+ if [ "$deps_status" -eq 0 ]; then
685
+ echo "✅ Overall Status: HEALTHY"
686
+ else
687
+ echo "⚠️ Overall Status: ISSUES DETECTED ($deps_status problems)"
688
+ fi
689
+
690
+ echo ""
691
+ }
692
+
693
+ validate_dependencies() {
694
+ log "Validating CFN Loop dependencies..."
695
+
696
+ local validation_status=0
697
+ local missing_deps=()
698
+
699
+ # Check required dependencies
700
+ local required_deps=("node" "npx" "jq" "bc")
701
+ for dep in "${required_deps[@]}"; do
702
+ if ! command -v "$dep" >/dev/null 2>&1; then
703
+ missing_deps+=("$dep")
704
+ ((validation_status++))
705
+ fi
706
+ done
707
+
708
+ if [ ${#missing_deps[@]} -gt 0 ]; then
709
+ echo "❌ Missing Dependencies:"
710
+ for dep in "${missing_deps[@]}"; do
711
+ echo " - $dep"
712
+ done
713
+ echo ""
714
+ echo "💡 Installation Commands:"
715
+ if [[ " ${missing_deps[*]}" =~ "node" ]] || [[ " ${missing_deps[*]}" =~ "npx" ]]; then
716
+ echo " # Install Node.js and npx:"
717
+ echo " curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -"
718
+ echo " sudo apt-get install -y nodejs npm"
719
+ echo " sudo npm install -g npx"
720
+ fi
721
+ if [[ " ${missing_deps[*]}" =~ "jq" ]]; then
722
+ echo " # Install jq:"
723
+ echo " sudo apt-get install -y jq"
724
+ fi
725
+ if [[ " ${missing_deps[*]}" =~ "bc" ]]; then
726
+ echo " # Install bc:"
727
+ echo " sudo apt-get install -y bc"
728
+ fi
729
+ else
730
+ echo "✅ All required dependencies are available"
731
+ fi
732
+
733
+ echo ""
734
+
735
+ # Check optional dependencies
736
+ echo "🔍 Optional Dependencies:"
737
+
738
+ local optional_deps=("redis-cli" "docker")
739
+ for dep in "${optional_deps[@]}"; do
740
+ if command -v "$dep" >/dev/null 2>&1; then
741
+ case "$dep" in
742
+ "redis-cli")
743
+ if redis-cli ping >/dev/null 2>&1; then
744
+ echo " ✅ Redis Server: Running"
745
+ else
746
+ echo " ⚠️ Redis CLI: Available, Server Not Connected"
747
+ fi
748
+ ;;
749
+ "docker")
750
+ echo " ✅ Docker: $(docker --version | head -1)"
751
+ ;;
752
+ esac
753
+ else
754
+ echo " ⚪ $dep: Not Available (optional)"
755
+ fi
756
+ done
757
+
758
+ return $validation_status
759
+ }
760
+
761
+ # Parse arguments
762
+ while [[ $# -gt 0 ]]; do
763
+ case $1 in
764
+ --action)
765
+ ACTION="$2"
766
+ shift 2
767
+ ;;
768
+ --task-id)
769
+ TASK_ID="$2"
770
+ shift 2
771
+ ;;
772
+ --error-type)
773
+ ERROR_TYPE="$2"
774
+ shift 2
775
+ ;;
776
+ --error-message)
777
+ ERROR_MESSAGE="$2"
778
+ shift 2
779
+ ;;
780
+ --exit-code)
781
+ EXIT_CODE="$2"
782
+ shift 2
783
+ ;;
784
+ --context)
785
+ CONTEXT_JSON="$2"
786
+ shift 2
787
+ ;;
788
+ --format)
789
+ FORMAT="$2"
790
+ shift 2
791
+ ;;
792
+ --since)
793
+ SINCE_TIME="$2"
794
+ shift 2
795
+ ;;
796
+ --retention-days)
797
+ RETENTION_DAYS="$2"
798
+ shift 2
799
+ ;;
800
+ --help|-h)
801
+ show_usage
802
+ exit 0
803
+ ;;
804
+ *)
805
+ echo "Unknown option: $1"
806
+ show_usage
807
+ exit 1
808
+ ;;
809
+ esac
810
+ done
811
+
812
+ # Validate parameters
813
+ validate_parameters
814
+
815
+ # Execute action
816
+ case "$ACTION" in
817
+ capture)
818
+ collect_system_diagnostics "${LOG_BASE_DIR}/sys-diagnostics-$(date +%s).json"
819
+ collect_cfn_state "${LOG_BASE_DIR}/cfn-state-${TASK_ID}-$(date +%s).json"
820
+ capture_error
821
+ ;;
822
+ report)
823
+ generate_report
824
+ ;;
825
+ cleanup)
826
+ cleanup_logs
827
+ ;;
828
+ list)
829
+ list_error_logs "$SINCE_TIME"
830
+ ;;
831
+ diagnostics)
832
+ run_diagnostics
833
+ ;;
834
+ validate)
835
+ validate_dependencies
836
+ ;;
837
+ esac
838
+
839
+ log "Error logging action '$ACTION' completed"