claude-flow-novice 2.14.34 → 2.14.36

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 (42) hide show
  1. package/.claude/commands/CFN_LOOP_TASK_MODE.md +1 -1
  2. package/.claude/commands/switch-api.md +1 -1
  3. package/.claude/skills/cfn-agent-discovery/agents-registry.json +1 -1
  4. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +2 -1
  5. package/.claude/skills/cfn-loop-validation/config.json +2 -2
  6. package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +221 -0
  7. package/claude-assets/agents/README-AGENT_LIFECYCLE.md +37 -10
  8. package/claude-assets/agents/README-VALIDATION.md +0 -8
  9. package/claude-assets/agents/cfn-dev-team/README.md +0 -8
  10. package/claude-assets/agents/cfn-dev-team/coordinators/README.md +1 -9
  11. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +565 -565
  12. package/claude-assets/agents/cfn-dev-team/developers/README.md +1 -9
  13. package/claude-assets/agents/cfn-dev-team/documentation/README-VALIDATION.md +0 -8
  14. package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md +0 -10
  15. package/claude-assets/agents/cfn-dev-team/reviewers/README.md +1 -9
  16. package/claude-assets/agents/cfn-dev-team/reviewers/quality/quality-metrics.md +0 -10
  17. package/claude-assets/agents/cfn-dev-team/test-agent.md +0 -10
  18. package/claude-assets/agents/cfn-dev-team/testers/README.md +1 -9
  19. package/claude-assets/agents/csuite/cto-agent.md +0 -10
  20. package/claude-assets/agents/custom/cfn-system-expert.md +1 -128
  21. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +1 -5
  22. package/claude-assets/agents/docker-team/csuite/c-suite-template.md +1 -5
  23. package/claude-assets/agents/docker-team/infrastructure/team-coordinator-template.md +1 -5
  24. package/claude-assets/agents/marketing_hybrid/cost_tracker.md +0 -10
  25. package/claude-assets/agents/marketing_hybrid/docker_deployer.md +0 -10
  26. package/claude-assets/agents/marketing_hybrid/zai_worker_spawner.md +0 -10
  27. package/claude-assets/commands/CFN_LOOP_TASK_MODE.md +1 -1
  28. package/claude-assets/commands/switch-api.md +1 -1
  29. package/claude-assets/skills/cfn-agent-discovery/agents-registry.json +1 -1
  30. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +2 -1
  31. package/claude-assets/skills/cfn-loop-validation/config.json +2 -2
  32. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +324 -322
  33. package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +221 -0
  34. package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +2 -2
  35. package/claude-assets/skills/cfn-task-mode-sanitize/task-mode-env-sanitizer.sh +213 -182
  36. package/claude-assets/skills/cfn-validation-runner-instrumentation/wrapped-executor.sh +233 -271
  37. package/dist/cli/agent-definition-parser.js.map +1 -1
  38. package/dist/cli/config-manager.js +109 -91
  39. package/package.json +1 -1
  40. package/scripts/docker-build-mcp.sh +155 -0
  41. package/scripts/docker-test-mcp.sh +260 -0
  42. package/scripts/mcp-health-check.sh +123 -0
@@ -1,327 +1,289 @@
1
- #!/bin/bash
2
- # CFN Validation Runner Instrumentation
3
- # Wraps Bun/Node/Playwright invocations with logging, timeouts, and cleanup
1
+ #!/usr/bin/env bash
2
+
3
+ ##############################################################################
4
+ # CFN Validation Runner Process Instrumentation
5
+ # Provides process wrapping, monitoring, and instrumentation for CFN agents
6
+ #
7
+ # Usage:
8
+ # source wrapped-executor.sh
9
+ # wrap_execution <command> <timeout> <log_prefix>
10
+ #
11
+ # Example:
12
+ # wrap_execution "npx claude-flow-novice agent coder" 300 "agent-execution"
13
+ ##############################################################################
4
14
 
5
15
  set -euo pipefail
6
16
 
7
- # Script configuration
8
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
10
-
11
- # Configuration defaults
12
- DEFAULT_TIMEOUT="${CFN_VALIDATION_TIMEOUT:-300}" # 5 minutes
13
- DEFAULT_MEMORY="${CFN_VALIDATION_MEMORY:-2048}" # 2GB
14
- LOG_DIR="${CFN_VALIDATION_LOG_DIR:-$PROJECT_ROOT/.claude/logs/validation}"
15
- MONITOR_INTERVAL="${CFN_MONITOR_INTERVAL:-30}" # 30 seconds
16
-
17
- # Colors for output
18
- RED='\033[0;31m'
19
- GREEN='\033[0;32m'
20
- YELLOW='\033[1;33m'
21
- BLUE='\033[0;34m'
22
- NC='\033[0m' # No Color
23
-
24
- # Logging functions
25
- log_info() {
26
- echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
27
- }
17
+ # Instrumentation state
18
+ declare -A CFN_INSTRUMENT_STATE
19
+ CFN_INSTRUMENT_STATE["active"]=false
20
+ CFN_INSTRUMENT_STATE["start_time"]=0
21
+ CFN_INSTRUMENT_STATE["pid"]=0
22
+ CFN_INSTRUMENT_STATE["timeout"]=0
23
+ CFN_INSTRUMENT_STATE["log_prefix"]=""
28
24
 
29
- log_success() {
30
- echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
31
- }
25
+ # Default timeouts (seconds)
26
+ readonly DEFAULT_TIMEOUT=300 # 5 minutes
27
+ readonly MAX_TIMEOUT=3600 # 1 hour
28
+ readonly WARNING_TIMEOUT=240 # 4 minutes
32
29
 
33
- log_error() {
34
- echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
35
- }
30
+ # Resource limits
31
+ readonly MAX_MEMORY_MB=2048
32
+ readonly MAX_CPU_PERCENT=80
36
33
 
37
- log_warning() {
38
- echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
39
- }
34
+ ##############################################################################
35
+ # Core Instrumentation Functions
36
+ ##############################################################################
40
37
 
41
- # Process monitoring
42
- monitor_process() {
43
- local pid="$1"
44
- local timeout="$2"
45
- local command_name="$3"
46
- local log_file="$4"
38
+ wrap_execution() {
39
+ local command="$1"
40
+ local timeout="${2:-$DEFAULT_TIMEOUT}"
41
+ local log_prefix="${3:-cfn-execution}"
47
42
 
48
- local elapsed=0
49
- while kill -0 "$pid" 2>/dev/null; do
50
- if [[ $elapsed -ge $timeout ]]; then
51
- log_warning "Process $pid ($command_name) exceeded timeout ${timeout}s, terminating..."
43
+ # Validate timeout
44
+ if (( timeout > MAX_TIMEOUT )); then
45
+ timeout=$MAX_TIMEOUT
46
+ echo "⚠️ Timeout capped at ${MAX_TIMEOUT}s" >&2
47
+ fi
52
48
 
53
- # Get memory usage before termination
54
- local memory_usage=$(ps -o rss= -p "$pid" 2>/dev/null | tr -d ' ' || echo "unknown")
55
- log_error "Memory usage at termination: ${memory_usage}KB"
49
+ # Initialize instrumentation state
50
+ CFN_INSTRUMENT_STATE["active"]=true
51
+ CFN_INSTRUMENT_STATE["start_time"]=$(date +%s)
52
+ CFN_INSTRUMENT_STATE["timeout"]=$timeout
53
+ CFN_INSTRUMENT_STATE["log_prefix"]="$log_prefix"
56
54
 
57
- # Terminate the process gracefully
58
- kill -TERM "$pid" 2>/dev/null || true
59
- sleep 5
55
+ echo "🔧 CFN Process Instrumentation v1.0.0" >&2
56
+ echo " Command: $command" >&2
57
+ echo " Timeout: ${timeout}s" >&2
58
+ echo " PID: $$" >&2
59
+ echo " Start: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >&2
60
60
 
61
- # Force kill if still running
62
- if kill -0 "$pid" 2>/dev/null; then
63
- log_error "Force killing process $pid ($command_name)"
64
- kill -KILL "$pid" 2>/dev/null || true
65
- fi
66
-
67
- return 124 # Timeout exit code
68
- fi
61
+ # Setup monitoring
62
+ setup_process_monitoring "$timeout" "$log_prefix"
69
63
 
70
- # Log periodic status
71
- if [[ $((elapsed % MONITOR_INTERVAL)) -eq 0 && $elapsed -gt 0 ]]; then
72
- local memory_usage=$(ps -o rss= -p "$pid" 2>/dev/null | tr -d ' ' || echo "unknown")
73
- log_info "Process $pid ($command_name) running: ${elapsed}s elapsed, ${memory_usage}KB memory"
74
- fi
64
+ # Execute with instrumentation
65
+ local result
66
+ result=$(execute_with_monitoring "$command" "$timeout" "$log_prefix")
67
+ local exit_code=$?
75
68
 
76
- sleep 1
77
- ((elapsed++))
78
- done
69
+ # Cleanup and report
70
+ cleanup_instrumentation "$exit_code"
79
71
 
80
- return 0
72
+ return $exit_code
81
73
  }
82
74
 
83
- # Instrumented execution wrapper
84
- execute_instrumented() {
85
- local command="$1"
86
- local timeout="${2:-$DEFAULT_TIMEOUT}"
87
- local memory_limit="${3:-$DEFAULT_MEMORY}"
88
- shift 3
89
- local args=("$@")
90
-
91
- # Create log directory
92
- mkdir -p "$LOG_DIR"
93
-
94
- # Generate unique execution ID
95
- local execution_id="exec_$(date +%Y%m%d_%H%M%S)_$$"
96
- local log_file="$LOG_DIR/${execution_id}.log"
97
- export LOG_FILE="$log_file"
98
-
99
- # Extract command name for logging
100
- local command_name=$(basename "$command")
101
- local full_command="$command ${args[*]}"
102
-
103
- # Start execution logging
104
- log_info "=== Starting Instrumented Execution ==="
105
- log_info "Execution ID: $execution_id"
106
- log_info "Command: $full_command"
107
- log_info "Timeout: ${timeout}s"
108
- log_info "Memory Limit: ${memory_limit}MB"
109
- log_info "Working Directory: $(pwd)"
110
- log_info "Environment: CFN_MODE=${CFN_MODE:-unset}, NODE_OPTIONS=${NODE_OPTIONS:-unset}"
111
-
112
- # Set up resource limits
113
- local memory_limit_kb=$((memory_limit * 1024))
114
-
115
- # Start the command with resource limits
116
- local start_time=$(date +%s)
117
- log_info "Starting process at $(date)"
118
-
119
- # Launch command in background with resource limits
120
- (
121
- # Apply memory limit
122
- ulimit -v "$memory_limit_kb" 2>/dev/null || {
123
- log_warning "Could not set memory limit via ulimit"
124
- }
125
-
126
- # Apply Node.js specific memory limit
127
- if [[ "$command_name" == "node" || "$command_name" == "bun" ]]; then
128
- export NODE_OPTIONS="${NODE_OPTIONS:-} --max-old-space-size=$memory_limit"
129
- log_info "Set NODE_OPTIONS: $NODE_OPTIONS"
130
- fi
75
+ setup_process_monitoring() {
76
+ local timeout="$1"
77
+ local log_prefix="$2"
131
78
 
132
- # Execute the command
133
- exec "$command" "${args[@]}" 2>&1
134
- ) &
79
+ echo " Setting up process monitoring..." >&2
135
80
 
136
- local pid=$!
137
- log_info "Process started with PID: $pid"
81
+ # Start resource monitoring in background
82
+ (
83
+ local monitor_interval=30 # Check every 30 seconds
84
+ local elapsed=0
138
85
 
139
- # Start monitoring in background
140
- monitor_process "$pid" "$timeout" "$command_name" "$log_file" &
141
- local monitor_pid=$!
86
+ while (( elapsed < timeout )); do
87
+ sleep $monitor_interval
88
+ elapsed=$((elapsed + monitor_interval))
142
89
 
143
- # Wait for command completion
144
- local exit_code=0
145
- if wait "$pid" 2>/dev/null; then
146
- exit_code=$?
147
- log_success "Process $pid ($command_name) completed successfully"
148
- else
149
- exit_code=$?
150
- if [[ $exit_code -eq 124 ]]; then
151
- log_error "Process $pid ($command_name) timed out after ${timeout}s"
152
- else
153
- log_error "Process $pid ($command_name) failed with exit code: $exit_code"
154
- fi
155
- fi
90
+ if [[ "${CFN_INSTRUMENT_STATE[active]}" == "true" ]]; then
91
+ check_resource_usage "$log_prefix" "$elapsed"
92
+ else
93
+ break
94
+ fi
95
+ done
156
96
 
157
- # Stop monitoring
158
- kill "$monitor_pid" 2>/dev/null || true
159
- wait "$monitor_pid" 2>/dev/null || true
97
+ # Timeout warning
98
+ if [[ "${CFN_INSTRUMENT_STATE[active]}" == "true" ]]; then
99
+ echo "⚠️ [$log_prefix] Approaching timeout: ${elapsed}s" >&2
100
+ fi
101
+ ) &
160
102
 
161
- # Calculate execution time
162
- local end_time=$(date +%s)
163
- local duration=$((end_time - start_time))
103
+ echo " Resource monitoring started (interval: 30s)" >&2
104
+ }
164
105
 
165
- # Final status logging
166
- log_info "=== Execution Summary ==="
167
- log_info "Command: $full_command"
168
- log_info "Exit Code: $exit_code"
169
- log_info "Duration: ${duration}s"
170
- log_info "Memory Limit: ${memory_limit}MB"
106
+ check_resource_usage() {
107
+ local log_prefix="$1"
108
+ local elapsed="$2"
171
109
 
172
- # Log resource usage summary if available
110
+ # Check memory usage
173
111
  if command -v ps >/dev/null 2>&1; then
174
- local final_memory=$(ps -o rss= -p "$pid" 2>/dev/null | tr -d ' ' || echo "unknown")
175
- log_info "Final Memory: ${final_memory}KB"
176
- fi
112
+ local memory_mb=$(ps -o rss= -p $$ 2>/dev/null | awk '{print int($1/1024)}' || echo "0")
177
113
 
178
- # Cleanup if process is still running
179
- if kill -0 "$pid" 2>/dev/null; then
180
- log_warning "Cleaning up still-running process $pid"
181
- kill -TERM "$pid" 2>/dev/null || true
182
- sleep 2
183
- kill -KILL "$pid" 2>/dev/null || true
114
+ if (( memory_mb > MAX_MEMORY_MB )); then
115
+ echo "⚠️ [$log_prefix] High memory: ${memory_mb}MB (limit: ${MAX_MEMORY_MB}MB)" >&2
116
+ fi
184
117
  fi
185
118
 
186
- # Archive log if successful
187
- if [[ $exit_code -eq 0 ]]; then
188
- local archive_log="$LOG_DIR/${execution_id}_success.log"
189
- mv "$log_file" "$archive_log" 2>/dev/null || true
190
- log_success "Log archived: $archive_log"
191
- else
192
- local archive_log="$LOG_DIR/${execution_id}_failed.log"
193
- mv "$log_file" "$archive_log" 2>/dev/null || true
194
- log_error "Failed log archived: $archive_log"
119
+ # Check CPU usage (basic check)
120
+ if command -v top >/dev/null 2>&1; then
121
+ local cpu_percent=$(top -b -n 1 -p $$ 2>/dev/null | awk 'NR>7 {print $9}' | head -1 || echo "0")
122
+
123
+ if (( $(echo "$cpu_percent > $MAX_CPU_PERCENT" | bc -l 2>/dev/null || echo "0") )); then
124
+ echo "⚠️ [$log_prefix] High CPU: ${cpu_percent}%" >&2
125
+ fi
195
126
  fi
196
127
 
197
- return $exit_code
128
+ # Warning timeout check
129
+ if (( elapsed > WARNING_TIMEOUT )); then
130
+ echo "⏰ [$log_prefix] Long running: ${elapsed}s" >&2
131
+ fi
198
132
  }
199
133
 
200
- # Specific wrappers for common tools
201
- execute_node() {
202
- local timeout="${1:-$DEFAULT_TIMEOUT}"
203
- shift
204
- log_info "Executing Node.js with instrumentation"
205
- execute_instrumented "node" "$timeout" "$DEFAULT_MEMORY" "$@"
206
- }
134
+ execute_with_monitoring() {
135
+ local command="$1"
136
+ local timeout="$2"
137
+ local log_prefix="$3"
207
138
 
208
- execute_bun() {
209
- local timeout="${1:-$DEFAULT_TIMEOUT}"
210
- shift
211
- log_info "Executing Bun with instrumentation"
212
- execute_instrumented "bun" "$timeout" "$DEFAULT_MEMORY" "$@"
213
- }
139
+ echo " Executing: $command" >&2
214
140
 
215
- execute_playwright() {
216
- local timeout="${1:-$DEFAULT_TIMEOUT}"
217
- shift
218
- # Playwright may need more memory
219
- local playwright_memory="${CFN_PLAYWRIGHT_MEMORY:-4096}"
220
- log_info "Executing Playwright with instrumentation"
221
- execute_instrumented "npx" "$timeout" "$playwright_memory" "playwright" "$@"
222
- }
141
+ # Store command PID for monitoring
142
+ local child_pid
223
143
 
224
- execute_npx() {
225
- local timeout="${1:-$DEFAULT_TIMEOUT}"
226
- shift
227
- log_info "Executing NPX with instrumentation"
228
- execute_instrumented "npx" "$timeout" "$DEFAULT_MEMORY" "$@"
229
- }
144
+ # Execute command with timeout
145
+ if command -v timeout >/dev/null 2>&1; then
146
+ # Use system timeout if available
147
+ timeout "$timeout" bash -c "$command" &
148
+ child_pid=$!
149
+ CFN_INSTRUMENT_STATE["pid"]=$child_pid
230
150
 
231
- # Cleanup old logs
232
- cleanup_logs() {
233
- local max_days="${CFN_LOG_RETENTION_DAYS:-7}"
234
- log_info "Cleaning up logs older than $max_days days"
151
+ echo " Process PID: $child_pid" >&2
235
152
 
236
- find "$LOG_DIR" -name "*.log" -type f -mtime "+$max_days" -delete 2>/dev/null || true
237
- log_info "Log cleanup completed"
238
- }
153
+ # Wait for completion with monitoring
154
+ local wait_result=0
155
+ while kill -0 $child_pid 2>/dev/null; do
156
+ sleep 5
239
157
 
240
- # Show usage
241
- show_usage() {
242
- cat <<'EOF'
243
- CFN Validation Runner Instrumentation
158
+ # Check if we're approaching timeout
159
+ local elapsed=$(($(date +%s) - CFN_INSTRUMENT_STATE[start_time]))
160
+ if (( elapsed > timeout - 10 )); then
161
+ echo "⚠️ [$log_prefix] Approaching hard timeout, preparing graceful shutdown" >&2
162
+ fi
163
+ done
164
+
165
+ wait $child_pid
166
+ wait_result=$?
167
+
168
+ else
169
+ # Fallback without system timeout
170
+ echo " Running without system timeout (not available)" >&2
171
+ bash -c "$command" &
172
+ child_pid=$!
173
+ CFN_INSTRUMENT_STATE["pid"]=$child_pid
174
+
175
+ # Basic wait (less safe)
176
+ wait $child_pid
177
+ wait_result=$?
178
+ fi
179
+
180
+ return $wait_result
181
+ }
244
182
 
245
- USAGE:
246
- source "$(dirname "${BASH_SOURCE[0]}")/wrapped-executor.sh"
183
+ cleanup_instrumentation() {
184
+ local exit_code="$1"
185
+ local elapsed=$(($(date +%s) - CFN_INSTRUMENT_STATE[start_time]))
247
186
 
248
- # Generic Execution
249
- execute_instrumented <command> [timeout] [memory_limit] [args...]
187
+ echo "🧹 Process instrumentation cleanup" >&2
188
+ echo " Exit code: $exit_code" >&2
189
+ echo " Duration: ${elapsed}s" >&2
250
190
 
251
- # Tool-Specific Wrappers
252
- execute_node [timeout] [args...] # Execute Node.js
253
- execute_bun [timeout] [args...] # Execute Bun
254
- execute_playwright [timeout] [args...] # Execute Playwright
255
- execute_npx [timeout] [args...] # Execute NPX
191
+ # Kill any remaining background processes
192
+ if [[ -n "${CFN_INSTRUMENT_STATE[pid]:-}" ]] && kill -0 "${CFN_INSTRUMENT_STATE[pid]}" 2>/dev/null; then
193
+ echo " Terminating child process: ${CFN_INSTRUMENT_STATE[pid]}" >&2
194
+ kill -TERM "${CFN_INSTRUMENT_STATE[pid]}" 2>/dev/null || true
195
+ sleep 2
196
+ kill -KILL "${CFN_INSTRUMENT_STATE[pid]}" 2>/dev/null || true
197
+ fi
256
198
 
257
- # Maintenance
258
- cleanup_logs # Clean up old logs
199
+ # Clear state
200
+ CFN_INSTRUMENT_STATE["active"]=false
201
+ CFN_INSTRUMENT_STATE["pid"]=0
259
202
 
260
- ENVIRONMENT VARIABLES:
261
- CFN_VALIDATION_TIMEOUT # Default timeout in seconds (default: 300)
262
- CFN_VALIDATION_MEMORY # Default memory limit in MB (default: 2048)
263
- CFN_VALIDATION_LOG_DIR # Log directory (default: ./.claude/logs/validation)
264
- CFN_MONITOR_INTERVAL # Monitoring interval in seconds (default: 30)
265
- CFN_PLAYWRIGHT_MEMORY # Playwright memory limit in MB (default: 4096)
266
- CFN_LOG_RETENTION_DAYS # Log retention in days (default: 7)
203
+ echo "✅ Instrumentation cleanup complete" >&2
204
+ }
267
205
 
268
- EXAMPLES:
269
- # Execute Node.js script with default settings
270
- execute_node validate.js
206
+ ##############################################################################
207
+ # Utility Functions
208
+ ##############################################################################
209
+
210
+ get_instrumentation_status() {
211
+ if [[ "${CFN_INSTRUMENT_STATE[active]}" == "true" ]]; then
212
+ local elapsed=$(($(date +%s) - CFN_INSTRUMENT_STATE[start_time]))
213
+ echo "CFN Instrumentation Status: ACTIVE"
214
+ echo " PID: $$"
215
+ echo " Child PID: ${CFN_INSTRUMENT_STATE[pid]}"
216
+ echo " Elapsed: ${elapsed}s"
217
+ echo " Timeout: ${CFN_INSTRUMENT_STATE[timeout]}s"
218
+ echo " Log Prefix: ${CFN_INSTRUMENT_STATE[log_prefix]}"
219
+ else
220
+ echo "CFN Instrumentation Status: INACTIVE"
221
+ fi
222
+ }
271
223
 
272
- # Execute Bun with custom timeout
273
- execute_bun 600 build.ts
224
+ force_kill_execution() {
225
+ local signal="${1:-TERM}"
274
226
 
275
- # Execute Playwright with longer timeout
276
- execute_playwright 900 test.spec.js
227
+ if [[ "${CFN_INSTRUMENT_STATE[active]}" == "true" ]] && [[ -n "${CFN_INSTRUMENT_STATE[pid]:-}" ]]; then
228
+ echo "🚨 Force killing execution: ${CFN_INSTRUMENT_STATE[pid]} (signal: $signal)" >&2
229
+ kill -"$signal" "${CFN_INSTRUMENT_STATE[pid]}" 2>/dev/null || true
277
230
 
278
- # Generic execution with custom memory limit
279
- execute_instrumented custom-tool 300 4096 --arg1 --arg2
231
+ if [[ "$signal" == "TERM" ]]; then
232
+ sleep 2
233
+ if kill -0 "${CFN_INSTRUMENT_STATE[pid]}" 2>/dev/null; then
234
+ kill -KILL "${CFN_INSTRUMENT_STATE[pid]}" 2>/dev/null || true
235
+ fi
236
+ fi
237
+ fi
238
+ }
280
239
 
281
- OUTPUT:
282
- All executions generate detailed logs in ./.claude/logs/validation/
283
- Logs include: start time, end time, memory usage, exit codes, timeouts
240
+ ##############################################################################
241
+ # Signal Handlers
242
+ ##############################################################################
284
243
 
285
- EOF
244
+ setup_signal_handlers() {
245
+ trap 'handle_instrumentation_signal INT' INT
246
+ trap 'handle_instrumentation_signal TERM' TERM
247
+ trap 'handle_instrumentation_signal HUP' HUP
286
248
  }
287
249
 
288
- # Main execution block
289
- if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
290
- if [[ "$1" == "--help" || "$1" == "-h" ]]; then
291
- show_usage
292
- exit 0
250
+ handle_instrumentation_signal() {
251
+ local signal="$1"
252
+ echo "🛑 Instrumentation received signal: $signal" >&2
253
+
254
+ if [[ "${CFN_INSTRUMENT_STATE[active]}" == "true" ]]; then
255
+ force_kill_execution TERM
256
+ cleanup_instrumentation 130
293
257
  fi
294
258
 
295
- # Execute operation if provided
259
+ exit 130
260
+ }
261
+
262
+ ##############################################################################
263
+ # Auto-initialization
264
+ ##############################################################################
265
+
266
+ # If script is sourced, make instrumentation available
267
+ if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
268
+ echo "🔧 CFN Process Instrumentation loaded" >&2
269
+ echo " Use: wrap_execution <command> <timeout> <log_prefix>" >&2
270
+ setup_signal_handlers
271
+ fi
272
+
273
+ # If script is executed directly, show usage
274
+ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
275
+ echo "CFN Process Instrumentation v1.0.0"
276
+ echo ""
277
+ echo "Usage:"
278
+ echo " source wrapped-executor.sh"
279
+ echo " wrap_execution \"command\" timeout log_prefix"
280
+ echo ""
281
+ echo "Example:"
282
+ echo " wrap_execution \"npx claude-flow-novice agent coder\" 300 \"agent-execution\""
283
+ echo ""
284
+
285
+ # Test run if arguments provided
296
286
  if [[ $# -gt 0 ]]; then
297
- case "$1" in
298
- "node")
299
- shift
300
- execute_node "$@"
301
- ;;
302
- "bun")
303
- shift
304
- execute_bun "$@"
305
- ;;
306
- "playwright")
307
- shift
308
- execute_playwright "$@"
309
- ;;
310
- "npx")
311
- shift
312
- execute_npx "$@"
313
- ;;
314
- "cleanup")
315
- cleanup_logs
316
- ;;
317
- *)
318
- echo "Unknown command: $1" >&2
319
- echo "Use --help for usage information" >&2
320
- exit 1
321
- ;;
322
- esac
323
- else
324
- echo "CFN Validation Runner Instrumentation" >&2
325
- echo "Use --help for usage information" >&2
287
+ wrap_execution "$@"
326
288
  fi
327
289
  fi
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/agent-definition-parser.ts"],"sourcesContent":["/**\r\n * Agent Definition Parser\r\n *\r\n * Parses agent definition files (.md) with YAML frontmatter and markdown content.\r\n * Supports agent definitions in .claude/agents/ directory structure.\r\n */\r\n\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { glob } from 'glob';\r\n\r\nexport interface AgentDefinition {\r\n // YAML frontmatter fields\r\n name: string;\r\n description: string;\r\n tools: string[];\r\n model: 'haiku' | 'sonnet' | 'opus';\r\n type?: string;\r\n color?: string;\r\n acl_level?: number;\r\n capabilities?: string[];\r\n validation_hooks?: string[];\r\n lifecycle?: {\r\n pre_task?: string;\r\n post_task?: string;\r\n };\r\n\r\n // Parsed markdown content\r\n content: string;\r\n\r\n // File metadata\r\n filePath: string;\r\n category?: string; // e.g., 'core-agents', 'specialized', 'custom'\r\n}\r\n\r\n/**\r\n * Parse YAML frontmatter from markdown content\r\n */\r\nfunction parseFrontmatter(content: string): { frontmatter: Record<string, any>; body: string } {\r\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/;\r\n const match = content.match(frontmatterRegex);\r\n\r\n if (!match) {\r\n return { frontmatter: {}, body: content };\r\n }\r\n\r\n const [, yamlContent, body] = match;\r\n\r\n // Simple YAML parser (handles basic key-value pairs, arrays, and objects)\r\n const frontmatter: Record<string, any> = {};\r\n const lines = yamlContent.split('\\n');\r\n let currentKey = '';\r\n let currentArray: string[] = [];\r\n let isInArray = false;\r\n let isInObject = false;\r\n let currentObject: Record<string, string> = {};\r\n let objectKey = '';\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#')) continue;\r\n\r\n // Array item\r\n if (trimmed.startsWith('- ')) {\r\n if (!isInArray) {\r\n isInArray = true;\r\n currentArray = [];\r\n }\r\n currentArray.push(trimmed.substring(2).trim());\r\n continue;\r\n }\r\n\r\n // End of array\r\n if (isInArray && !trimmed.startsWith('- ')) {\r\n frontmatter[currentKey] = currentArray;\r\n isInArray = false;\r\n currentArray = [];\r\n }\r\n\r\n // Object field (indented key-value)\r\n if (trimmed.match(/^\\s+\\w+:/) && isInObject) {\r\n const [objKey, ...objValueParts] = trimmed.split(':');\r\n const objValue = objValueParts.join(':').trim().replace(/^[\"']|[\"']$/g, '');\r\n currentObject[objKey.trim()] = objValue;\r\n continue;\r\n }\r\n\r\n // Key-value pair\r\n const colonIndex = trimmed.indexOf(':');\r\n if (colonIndex !== -1) {\r\n const key = trimmed.substring(0, colonIndex).trim();\r\n const value = trimmed.substring(colonIndex + 1).trim();\r\n\r\n // Check if this starts an object\r\n if (value === '') {\r\n isInObject = true;\r\n currentObject = {};\r\n objectKey = key;\r\n continue;\r\n }\r\n\r\n // End previous object if any\r\n if (isInObject && !trimmed.match(/^\\s+/)) {\r\n frontmatter[objectKey] = currentObject;\r\n isInObject = false;\r\n currentObject = {};\r\n }\r\n\r\n currentKey = key;\r\n\r\n // Multi-line string (starts with |)\r\n if (value === '|') {\r\n continue; // Will be handled by next lines\r\n }\r\n\r\n // Inline array (e.g., [item1, item2, item3])\r\n if (value.startsWith('[') && value.endsWith(']')) {\r\n const arrayContent = value.substring(1, value.length - 1);\r\n const items = arrayContent.split(',').map(item => item.trim());\r\n frontmatter[key] = items;\r\n continue;\r\n }\r\n\r\n // Remove quotes\r\n const cleanValue = value.replace(/^[\"']|[\"']$/g, '');\r\n frontmatter[key] = cleanValue;\r\n } else if (currentKey && trimmed && !isInArray && !isInObject) {\r\n // Continuation of multi-line string\r\n const existingValue = frontmatter[currentKey];\r\n frontmatter[currentKey] = existingValue\r\n ? `${existingValue}\\n${trimmed}`\r\n : trimmed;\r\n }\r\n }\r\n\r\n // Handle trailing array or object\r\n if (isInArray) {\r\n frontmatter[currentKey] = currentArray;\r\n }\r\n if (isInObject) {\r\n frontmatter[objectKey] = currentObject;\r\n }\r\n\r\n return { frontmatter, body: body.trim() };\r\n}\r\n\r\n/**\r\n * Find agent definition file by agent type/name\r\n */\r\nasync function findAgentFile(agentType: string, baseDir: string = '.claude/agents'): Promise<string | null> {\r\n // Normalize agent type (handle both kebab-case and underscores)\r\n const normalizedType = agentType.toLowerCase().replace(/_/g, '-');\r\n\r\n // Search patterns (in order of priority)\r\n const patterns = [\r\n // Exact match in any subdirectory\r\n `${baseDir}/**/${normalizedType}.md`,\r\n // Match with different casing\r\n `${baseDir}/**/*${normalizedType}*.md`,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const files = await glob(pattern, { nodir: true, absolute: true });\r\n if (files.length > 0) {\r\n // Prefer exact match over partial match\r\n const exactMatch = files.find(f => {\r\n const basename = path.basename(f, '.md').toLowerCase();\r\n return basename === normalizedType;\r\n });\r\n return exactMatch || files[0];\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Parse agent definition from file\r\n */\r\nexport async function parseAgentDefinition(agentType: string): Promise<AgentDefinition> {\r\n // Find agent file\r\n const filePath = await findAgentFile(agentType);\r\n\r\n if (!filePath) {\r\n throw new Error(`Agent definition not found: ${agentType}`);\r\n }\r\n\r\n // Read file content\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n\r\n // Parse frontmatter and body\r\n const { frontmatter, body } = parseFrontmatter(content);\r\n\r\n // Extract category from path\r\n const relativePath = path.relative('.claude/agents', filePath);\r\n const category = relativePath.includes('/')\r\n ? relativePath.split('/')[0]\r\n : undefined;\r\n\r\n // Build agent definition\r\n const definition: AgentDefinition = {\r\n name: frontmatter.name || agentType,\r\n description: frontmatter.description || '',\r\n tools: Array.isArray(frontmatter.tools) ? frontmatter.tools : [],\r\n model: frontmatter.model || 'haiku',\r\n type: frontmatter.type,\r\n color: frontmatter.color,\r\n acl_level: frontmatter.acl_level ? parseInt(String(frontmatter.acl_level), 10) : undefined,\r\n capabilities: frontmatter.capabilities,\r\n validation_hooks: frontmatter.validation_hooks,\r\n lifecycle: frontmatter.lifecycle,\r\n content: body,\r\n filePath,\r\n category,\r\n };\r\n\r\n return definition;\r\n}\r\n\r\n/**\r\n * List all available agent definitions\r\n */\r\nexport async function listAgentDefinitions(baseDir: string = '.claude/agents'): Promise<string[]> {\r\n const pattern = `${baseDir}/**/*.md`;\r\n const files = await glob(pattern, { nodir: true });\r\n\r\n return files.map(f => path.basename(f, '.md'));\r\n}\r\n\r\n/**\r\n * Check if agent definition includes CFN Loop protocol\r\n */\r\nexport function hasCFNLoopProtocol(definition: AgentDefinition): boolean {\r\n const content = definition.content.toLowerCase();\r\n return (\r\n content.includes('cfn loop') &&\r\n content.includes('redis completion protocol') ||\r\n content.includes('invoke-waiting-mode.sh')\r\n );\r\n}\r\n"],"names":["fs","path","glob","parseFrontmatter","content","frontmatterRegex","match","frontmatter","body","yamlContent","lines","split","currentKey","currentArray","isInArray","isInObject","currentObject","objectKey","line","trimmed","trim","startsWith","push","substring","objKey","objValueParts","objValue","join","replace","colonIndex","indexOf","key","value","endsWith","arrayContent","length","items","map","item","cleanValue","existingValue","findAgentFile","agentType","baseDir","normalizedType","toLowerCase","patterns","pattern","files","nodir","absolute","exactMatch","find","f","basename","parseAgentDefinition","filePath","Error","readFile","relativePath","relative","category","includes","undefined","definition","name","description","tools","Array","isArray","model","type","color","acl_level","parseInt","String","capabilities","validation_hooks","lifecycle","listAgentDefinitions","hasCFNLoopProtocol"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/cli/agent-definition-parser.ts"],"sourcesContent":["/**\r\n * Agent Definition Parser\r\n *\r\n * Parses agent definition files (.md) with YAML frontmatter and markdown content.\r\n * Supports agent definitions in .claude/agents/ directory structure.\r\n */\r\n\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { glob } from 'glob';\r\n\r\nexport interface AgentDefinition {\r\n // YAML frontmatter fields\r\n name: string;\r\n description: string;\r\n tools: string[];\r\n model: 'haiku' | 'sonnet' | 'opus';\r\n type?: string;\r\n color?: string;\r\n acl_level?: number;\r\n capabilities?: string[];\r\n validation_hooks?: string[];\r\n lifecycle?: {\r\n pre_task?: string;\r\n post_task?: string;\r\n };\r\n\r\n // Parsed markdown content\r\n content: string;\r\n\r\n // File metadata\r\n filePath: string;\r\n category?: string; // e.g., 'core-agents', 'specialized', 'custom'\r\n}\r\n\r\n/**\r\n * Parse YAML frontmatter from markdown content\r\n */\r\nfunction parseFrontmatter(content: string): { frontmatter: Record<string, any>; body: string } {\r\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/;\r\n const match = content.match(frontmatterRegex);\r\n\r\n if (!match) {\r\n return { frontmatter: {}, body: content };\r\n }\r\n\r\n const [, yamlContent, body] = match;\r\n\r\n \r\n // Simple YAML parser (handles basic key-value pairs, arrays, and objects)\r\n const frontmatter: Record<string, any> = {};\r\n const lines = yamlContent.split('\\n');\r\n let currentKey = '';\r\n let currentArray: string[] = [];\r\n let isInArray = false;\r\n let isInObject = false;\r\n let currentObject: Record<string, string> = {};\r\n let objectKey = '';\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#')) continue;\r\n\r\n // Array item\r\n if (trimmed.startsWith('- ')) {\r\n if (!isInArray) {\r\n isInArray = true;\r\n currentArray = [];\r\n }\r\n currentArray.push(trimmed.substring(2).trim());\r\n continue;\r\n }\r\n\r\n // End of array\r\n if (isInArray && !trimmed.startsWith('- ')) {\r\n frontmatter[currentKey] = currentArray;\r\n isInArray = false;\r\n currentArray = [];\r\n }\r\n\r\n // Object field (indented key-value)\r\n if (trimmed.match(/^\\s+\\w+:/) && isInObject) {\r\n const [objKey, ...objValueParts] = trimmed.split(':');\r\n const objValue = objValueParts.join(':').trim().replace(/^[\"']|[\"']$/g, '');\r\n currentObject[objKey.trim()] = objValue;\r\n continue;\r\n }\r\n\r\n // Key-value pair\r\n const colonIndex = trimmed.indexOf(':');\r\n if (colonIndex !== -1) {\r\n const key = trimmed.substring(0, colonIndex).trim();\r\n const value = trimmed.substring(colonIndex + 1).trim();\r\n\r\n // Check if this starts an object\r\n if (value === '') {\r\n isInObject = true;\r\n currentObject = {};\r\n objectKey = key;\r\n continue;\r\n }\r\n\r\n // End previous object if any\r\n if (isInObject && !trimmed.match(/^\\s+/)) {\r\n frontmatter[objectKey] = currentObject;\r\n isInObject = false;\r\n currentObject = {};\r\n }\r\n\r\n currentKey = key;\r\n\r\n // Multi-line string (starts with |)\r\n if (value === '|') {\r\n continue; // Will be handled by next lines\r\n }\r\n\r\n // Inline array (e.g., [item1, item2, item3])\r\n if (value.startsWith('[') && value.endsWith(']')) {\r\n const arrayContent = value.substring(1, value.length - 1);\r\n const items = arrayContent.split(',').map(item => item.trim());\r\n frontmatter[key] = items;\r\n continue;\r\n }\r\n\r\n // Remove quotes\r\n const cleanValue = value.replace(/^[\"']|[\"']$/g, '');\r\n frontmatter[key] = cleanValue;\r\n } else if (currentKey && trimmed && !isInArray && !isInObject) {\r\n // Continuation of multi-line string\r\n const existingValue = frontmatter[currentKey];\r\n frontmatter[currentKey] = existingValue\r\n ? `${existingValue}\\n${trimmed}`\r\n : trimmed;\r\n }\r\n }\r\n\r\n // Handle trailing array or object\r\n if (isInArray) {\r\n frontmatter[currentKey] = currentArray;\r\n }\r\n if (isInObject) {\r\n frontmatter[objectKey] = currentObject;\r\n }\r\n\r\n return { frontmatter, body: body.trim() };\r\n}\r\n\r\n/**\r\n * Find agent definition file by agent type/name\r\n */\r\nasync function findAgentFile(agentType: string, baseDir: string = '.claude/agents'): Promise<string | null> {\r\n // Normalize agent type (handle both kebab-case and underscores)\r\n const normalizedType = agentType.toLowerCase().replace(/_/g, '-');\r\n\r\n // Search patterns (in order of priority)\r\n const patterns = [\r\n // Exact match in any subdirectory\r\n `${baseDir}/**/${normalizedType}.md`,\r\n // Match with different casing\r\n `${baseDir}/**/*${normalizedType}*.md`,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const files = await glob(pattern, { nodir: true, absolute: true });\r\n if (files.length > 0) {\r\n // Prefer exact match over partial match\r\n const exactMatch = files.find(f => {\r\n const basename = path.basename(f, '.md').toLowerCase();\r\n return basename === normalizedType;\r\n });\r\n return exactMatch || files[0];\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Parse agent definition from file\r\n */\r\nexport async function parseAgentDefinition(agentType: string): Promise<AgentDefinition> {\r\n // Find agent file\r\n const filePath = await findAgentFile(agentType);\r\n\r\n if (!filePath) {\r\n throw new Error(`Agent definition not found: ${agentType}`);\r\n }\r\n\r\n // Read file content\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n\r\n \r\n // Parse frontmatter and body\r\n const { frontmatter, body } = parseFrontmatter(content);\r\n\r\n // Extract category from path\r\n const relativePath = path.relative('.claude/agents', filePath);\r\n const category = relativePath.includes('/')\r\n ? relativePath.split('/')[0]\r\n : undefined;\r\n\r\n \r\n // Build agent definition\r\n const definition: AgentDefinition = {\r\n name: frontmatter.name || agentType,\r\n description: frontmatter.description || '',\r\n tools: Array.isArray(frontmatter.tools) ? frontmatter.tools : [],\r\n model: frontmatter.model || 'haiku',\r\n type: frontmatter.type,\r\n color: frontmatter.color,\r\n acl_level: frontmatter.acl_level ? parseInt(String(frontmatter.acl_level), 10) : undefined,\r\n capabilities: frontmatter.capabilities,\r\n validation_hooks: frontmatter.validation_hooks,\r\n lifecycle: frontmatter.lifecycle,\r\n content: body,\r\n filePath,\r\n category,\r\n };\r\n\r\n return definition;\r\n}\r\n\r\n/**\r\n * List all available agent definitions\r\n */\r\nexport async function listAgentDefinitions(baseDir: string = '.claude/agents'): Promise<string[]> {\r\n const pattern = `${baseDir}/**/*.md`;\r\n const files = await glob(pattern, { nodir: true });\r\n\r\n return files.map(f => path.basename(f, '.md'));\r\n}\r\n\r\n/**\r\n * Check if agent definition includes CFN Loop protocol\r\n */\r\nexport function hasCFNLoopProtocol(definition: AgentDefinition): boolean {\r\n const content = definition.content.toLowerCase();\r\n return (\r\n content.includes('cfn loop') &&\r\n content.includes('redis completion protocol') ||\r\n content.includes('invoke-waiting-mode.sh')\r\n );\r\n}\r\n"],"names":["fs","path","glob","parseFrontmatter","content","frontmatterRegex","match","frontmatter","body","yamlContent","lines","split","currentKey","currentArray","isInArray","isInObject","currentObject","objectKey","line","trimmed","trim","startsWith","push","substring","objKey","objValueParts","objValue","join","replace","colonIndex","indexOf","key","value","endsWith","arrayContent","length","items","map","item","cleanValue","existingValue","findAgentFile","agentType","baseDir","normalizedType","toLowerCase","patterns","pattern","files","nodir","absolute","exactMatch","find","f","basename","parseAgentDefinition","filePath","Error","readFile","relativePath","relative","category","includes","undefined","definition","name","description","tools","Array","isArray","model","type","color","acl_level","parseInt","String","capabilities","validation_hooks","lifecycle","listAgentDefinitions","hasCFNLoopProtocol"],"mappings":"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"}