@paulduvall/claude-dev-toolkit 0.0.1-alpha.2 → 0.0.1-alpha.21
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/LICENSE +21 -0
- package/README.md +88 -37
- package/bin/claude-commands +307 -65
- package/commands/active/xarchitecture.md +393 -0
- package/commands/active/xconfig.md +127 -0
- package/commands/active/xcontinue.md +92 -0
- package/commands/active/xdebug.md +130 -0
- package/commands/active/xdocs.md +178 -0
- package/commands/active/xexplore.md +94 -0
- package/commands/active/xgit.md +149 -0
- package/commands/active/xpipeline.md +152 -0
- package/commands/active/xquality.md +96 -0
- package/commands/active/xrefactor.md +198 -0
- package/commands/active/xrelease.md +142 -0
- package/commands/active/xsecurity.md +92 -0
- package/commands/active/xspec.md +174 -0
- package/commands/active/xtdd.md +151 -0
- package/commands/active/xtest.md +89 -0
- package/commands/active/xverify.md +80 -0
- package/commands/experiments/xact.md +742 -0
- package/commands/experiments/xanalytics.md +113 -0
- package/commands/experiments/xanalyze.md +70 -0
- package/commands/experiments/xapi.md +161 -0
- package/commands/experiments/xatomic.md +112 -0
- package/commands/experiments/xaws.md +85 -0
- package/commands/experiments/xcicd.md +337 -0
- package/commands/experiments/xcommit.md +122 -0
- package/commands/experiments/xcompliance.md +182 -0
- package/commands/experiments/xconstraints.md +89 -0
- package/commands/experiments/xcoverage.md +90 -0
- package/commands/experiments/xdb.md +102 -0
- package/commands/experiments/xdesign.md +121 -0
- package/commands/experiments/xdevcontainer.md +238 -0
- package/commands/experiments/xevaluate.md +111 -0
- package/commands/experiments/xfootnote.md +12 -0
- package/commands/experiments/xgenerate.md +117 -0
- package/commands/experiments/xgovernance.md +149 -0
- package/commands/experiments/xgreen.md +66 -0
- package/commands/experiments/xiac.md +118 -0
- package/commands/experiments/xincident.md +137 -0
- package/commands/experiments/xinfra.md +115 -0
- package/commands/experiments/xknowledge.md +115 -0
- package/commands/experiments/xmaturity.md +120 -0
- package/commands/experiments/xmetrics.md +118 -0
- package/commands/experiments/xmonitoring.md +128 -0
- package/commands/experiments/xnew.md +903 -0
- package/commands/experiments/xobservable.md +114 -0
- package/commands/experiments/xoidc.md +165 -0
- package/commands/experiments/xoptimize.md +115 -0
- package/commands/experiments/xperformance.md +112 -0
- package/commands/experiments/xplanning.md +131 -0
- package/commands/experiments/xpolicy.md +115 -0
- package/commands/experiments/xproduct.md +98 -0
- package/commands/experiments/xreadiness.md +75 -0
- package/commands/experiments/xred.md +55 -0
- package/commands/experiments/xrisk.md +128 -0
- package/commands/experiments/xrules.md +124 -0
- package/commands/experiments/xsandbox.md +120 -0
- package/commands/experiments/xscan.md +102 -0
- package/commands/experiments/xsetup.md +123 -0
- package/commands/experiments/xtemplate.md +116 -0
- package/commands/experiments/xtrace.md +212 -0
- package/commands/experiments/xux.md +171 -0
- package/commands/experiments/xvalidate.md +104 -0
- package/commands/experiments/xworkflow.md +113 -0
- package/hooks/.smellrc.example.json +19 -0
- package/hooks/README.md +263 -0
- package/hooks/check-commit-signing.py +127 -0
- package/hooks/check-complexity.py +38 -0
- package/hooks/check-security.py +37 -0
- package/hooks/claude-wrapper.sh +29 -0
- package/hooks/config.py +110 -0
- package/hooks/file-logger.sh +100 -0
- package/hooks/lib/argument-parser.sh +427 -0
- package/hooks/lib/config-constants.sh +230 -0
- package/hooks/lib/context-manager.sh +560 -0
- package/hooks/lib/error-handler.sh +423 -0
- package/hooks/lib/execution-engine.sh +444 -0
- package/hooks/lib/execution-results.sh +113 -0
- package/hooks/lib/execution-simulation.sh +114 -0
- package/hooks/lib/field-validators.sh +104 -0
- package/hooks/lib/file-utils.sh +398 -0
- package/hooks/lib/subagent-discovery.sh +468 -0
- package/hooks/lib/subagent-validator.sh +407 -0
- package/hooks/lib/validation-reporter.sh +134 -0
- package/hooks/on-error-debug.sh +226 -0
- package/hooks/pre-commit-quality.sh +204 -0
- package/hooks/pre-commit-test-runner.sh +132 -0
- package/hooks/pre-write-security.sh +115 -0
- package/hooks/prevent-credential-exposure.sh +279 -0
- package/hooks/security_bandit.py +177 -0
- package/hooks/security_checks.py +97 -0
- package/hooks/security_secrets.py +81 -0
- package/hooks/security_trojan.py +61 -0
- package/hooks/settings.example.json +52 -0
- package/hooks/smell_checks.py +238 -0
- package/hooks/smell_javascript.py +231 -0
- package/hooks/smell_python.py +110 -0
- package/hooks/smell_ruff.py +70 -0
- package/hooks/smell_types.py +72 -0
- package/hooks/subagent-trigger-simple.sh +202 -0
- package/hooks/subagent-trigger.sh +253 -0
- package/hooks/suppression.py +82 -0
- package/hooks/tab-color.sh +70 -0
- package/hooks/verify-before-edit.sh +135 -0
- package/lib/backup-restore-command.js +140 -0
- package/lib/base/base-command.js +252 -0
- package/lib/base/command-result.js +184 -0
- package/lib/config/constants.js +255 -0
- package/lib/config.js +48 -6
- package/lib/configure-command.js +428 -0
- package/lib/dependency-validator.js +64 -5
- package/lib/hook-installer-core.js +2 -2
- package/lib/installation-instruction-generator.js +213 -495
- package/lib/installer.js +134 -56
- package/lib/oidc-command.js +740 -0
- package/lib/services/backup-list-service.js +226 -0
- package/lib/services/backup-service.js +230 -0
- package/lib/services/command-installer-service.js +217 -0
- package/lib/services/logger-service.js +201 -0
- package/lib/services/package-manager-service.js +319 -0
- package/lib/services/platform-instruction-service.js +294 -0
- package/lib/services/recovery-instruction-service.js +348 -0
- package/lib/services/restore-service.js +221 -0
- package/lib/setup-command.js +359 -0
- package/lib/setup-wizard.js +155 -262
- package/lib/uninstall-command.js +100 -0
- package/lib/utils/claude-path-config.js +184 -0
- package/lib/utils/file-system-utils.js +152 -0
- package/lib/utils.js +8 -4
- package/lib/verify-command.js +430 -0
- package/package.json +7 -3
- package/scripts/postinstall.js +172 -157
- package/subagents/debug-specialist.md +7 -0
- package/templates/README.md +115 -0
- package/templates/basic-settings.json +30 -0
- package/templates/comprehensive-settings.json +57 -0
- package/templates/global-claude.md +344 -0
- package/templates/hybrid-hook-config.yaml +132 -0
- package/templates/security-focused-settings.json +62 -0
- package/templates/subagent-hooks.yaml +188 -0
- package/lib/package-manager-service.js +0 -270
- package/subagents/debug-context.md +0 -197
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
|
|
4
|
+
# Execution Engine Module for Subagent-Hook Integration
|
|
5
|
+
#
|
|
6
|
+
# This module provides functionality to execute subagents with proper
|
|
7
|
+
# timeout handling, blocking/non-blocking modes, and result processing.
|
|
8
|
+
|
|
9
|
+
# Include guard
|
|
10
|
+
[[ -n "${_EXECUTION_ENGINE_LOADED:-}" ]] && return 0
|
|
11
|
+
_EXECUTION_ENGINE_LOADED=1
|
|
12
|
+
|
|
13
|
+
# Source required modules
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
source "$SCRIPT_DIR/config-constants.sh"
|
|
16
|
+
source "$SCRIPT_DIR/file-utils.sh"
|
|
17
|
+
source "$SCRIPT_DIR/error-handler.sh"
|
|
18
|
+
source "$SCRIPT_DIR/execution-simulation.sh"
|
|
19
|
+
source "$SCRIPT_DIR/execution-results.sh"
|
|
20
|
+
|
|
21
|
+
##################################
|
|
22
|
+
# Execution State Management
|
|
23
|
+
##################################
|
|
24
|
+
|
|
25
|
+
# Global variables for execution state (compatible with older bash versions)
|
|
26
|
+
EXECUTION_PID=""
|
|
27
|
+
EXECUTION_START_TIME=""
|
|
28
|
+
EXECUTION_OUTPUT_FILE=""
|
|
29
|
+
EXECUTION_ERROR_FILE=""
|
|
30
|
+
EXECUTION_RESULT=""
|
|
31
|
+
|
|
32
|
+
##################################
|
|
33
|
+
# Execution Mode Functions
|
|
34
|
+
##################################
|
|
35
|
+
|
|
36
|
+
determine_execution_mode() {
|
|
37
|
+
local event_type="$1"
|
|
38
|
+
local forced_mode="${2:-auto}"
|
|
39
|
+
|
|
40
|
+
log_debug "Determining execution mode for event: $event_type (forced: $forced_mode)"
|
|
41
|
+
|
|
42
|
+
# Check for forced mode from arguments
|
|
43
|
+
if [[ "$forced_mode" != "auto" ]]; then
|
|
44
|
+
echo "$forced_mode"
|
|
45
|
+
log_debug "Using forced execution mode: $forced_mode"
|
|
46
|
+
return $EXIT_SUCCESS
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Determine based on event type
|
|
50
|
+
local blocking_events=("pre_write" "pre_commit" "security_check")
|
|
51
|
+
local event
|
|
52
|
+
|
|
53
|
+
for event in "${blocking_events[@]}"; do
|
|
54
|
+
if [[ "$event_type" == "$event" ]]; then
|
|
55
|
+
echo "blocking"
|
|
56
|
+
log_debug "Using blocking mode for event: $event_type"
|
|
57
|
+
return $EXIT_SUCCESS
|
|
58
|
+
fi
|
|
59
|
+
done
|
|
60
|
+
|
|
61
|
+
# Default to non-blocking
|
|
62
|
+
echo "non-blocking"
|
|
63
|
+
log_debug "Using non-blocking mode for event: $event_type"
|
|
64
|
+
return $EXIT_SUCCESS
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get_timeout_for_execution() {
|
|
68
|
+
local event_type="$1"
|
|
69
|
+
local subagent_name="$2"
|
|
70
|
+
local custom_timeout="${SUBAGENT_TIMEOUT:-}"
|
|
71
|
+
|
|
72
|
+
# Use custom timeout if provided
|
|
73
|
+
if [[ -n "$custom_timeout" ]]; then
|
|
74
|
+
echo "$custom_timeout"
|
|
75
|
+
log_debug "Using custom timeout: ${custom_timeout}ms"
|
|
76
|
+
return $EXIT_SUCCESS
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Use event-specific timeout
|
|
80
|
+
local timeout
|
|
81
|
+
timeout=$(get_timeout_for_event "$event_type")
|
|
82
|
+
echo "$timeout"
|
|
83
|
+
log_debug "Using event-specific timeout: ${timeout}ms for $event_type"
|
|
84
|
+
return $EXIT_SUCCESS
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
##################################
|
|
88
|
+
# Subagent Execution Functions
|
|
89
|
+
##################################
|
|
90
|
+
|
|
91
|
+
execute_subagent() {
|
|
92
|
+
local subagent_file="$1"
|
|
93
|
+
local context_file="$2"
|
|
94
|
+
local execution_mode="${3:-non-blocking}"
|
|
95
|
+
local timeout="${4:-$DEFAULT_TIMEOUT}"
|
|
96
|
+
|
|
97
|
+
if [[ -z "$subagent_file" ]] || [[ -z "$context_file" ]]; then
|
|
98
|
+
log_error "Subagent file and context file are required"
|
|
99
|
+
return $EXIT_VALIDATION_FAILED
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
local subagent_name
|
|
103
|
+
subagent_name=$(basename "$subagent_file" "$SUBAGENT_FILE_EXTENSION")
|
|
104
|
+
|
|
105
|
+
log_info "Executing subagent: $subagent_name (mode: $execution_mode, timeout: ${timeout}ms)"
|
|
106
|
+
|
|
107
|
+
# Prepare execution environment
|
|
108
|
+
if ! prepare_execution_environment "$subagent_name"; then
|
|
109
|
+
log_error "Failed to prepare execution environment"
|
|
110
|
+
return $EXIT_EXECUTION_FAILED
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Execute based on mode
|
|
114
|
+
case "$execution_mode" in
|
|
115
|
+
"blocking")
|
|
116
|
+
execute_subagent_blocking "$subagent_file" "$context_file" "$timeout"
|
|
117
|
+
;;
|
|
118
|
+
"non-blocking")
|
|
119
|
+
execute_subagent_non_blocking "$subagent_file" "$context_file" "$timeout"
|
|
120
|
+
;;
|
|
121
|
+
"dry-run")
|
|
122
|
+
execute_subagent_dry_run "$subagent_file" "$context_file"
|
|
123
|
+
;;
|
|
124
|
+
*)
|
|
125
|
+
log_error "Unknown execution mode: $execution_mode"
|
|
126
|
+
return $EXIT_VALIDATION_FAILED
|
|
127
|
+
;;
|
|
128
|
+
esac
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
execute_subagent_blocking() {
|
|
132
|
+
local subagent_file="$1"
|
|
133
|
+
local context_file="$2"
|
|
134
|
+
local timeout="$3"
|
|
135
|
+
|
|
136
|
+
local subagent_name
|
|
137
|
+
subagent_name=$(basename "$subagent_file" "$SUBAGENT_FILE_EXTENSION")
|
|
138
|
+
|
|
139
|
+
log_debug "Starting blocking execution of: $subagent_name"
|
|
140
|
+
EXECUTION_START_TIME=$(date +%s)
|
|
141
|
+
|
|
142
|
+
# In a real implementation, this would invoke Claude with the subagent
|
|
143
|
+
# For now, we simulate the execution with a mock implementation
|
|
144
|
+
if ! execute_subagent_simulation "$subagent_file" "$context_file" "$timeout"; then
|
|
145
|
+
log_error "Subagent execution failed: $subagent_name"
|
|
146
|
+
return $EXIT_EXECUTION_FAILED
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Process execution results
|
|
150
|
+
if ! process_execution_results "$subagent_name" "blocking"; then
|
|
151
|
+
log_error "Failed to process execution results: $subagent_name"
|
|
152
|
+
return $EXIT_EXECUTION_FAILED
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
log_info "Blocking execution completed: $subagent_name"
|
|
156
|
+
return $EXIT_SUCCESS
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
execute_subagent_non_blocking() {
|
|
160
|
+
local subagent_file="$1"
|
|
161
|
+
local context_file="$2"
|
|
162
|
+
local timeout="$3"
|
|
163
|
+
|
|
164
|
+
local subagent_name
|
|
165
|
+
subagent_name=$(basename "$subagent_file" "$SUBAGENT_FILE_EXTENSION")
|
|
166
|
+
|
|
167
|
+
log_debug "Starting non-blocking execution of: $subagent_name"
|
|
168
|
+
EXECUTION_START_TIME=$(date +%s)
|
|
169
|
+
|
|
170
|
+
# Execute in background
|
|
171
|
+
(
|
|
172
|
+
if ! execute_subagent_simulation "$subagent_file" "$context_file" "$timeout"; then
|
|
173
|
+
log_error "Background subagent execution failed: $subagent_name"
|
|
174
|
+
exit $EXIT_EXECUTION_FAILED
|
|
175
|
+
fi
|
|
176
|
+
exit $EXIT_SUCCESS
|
|
177
|
+
) &
|
|
178
|
+
|
|
179
|
+
EXECUTION_PID=$!
|
|
180
|
+
log_debug "Non-blocking execution started with PID: $EXECUTION_PID"
|
|
181
|
+
|
|
182
|
+
# For non-blocking, we don't wait for completion
|
|
183
|
+
log_info "Non-blocking execution initiated: $subagent_name (PID: $EXECUTION_PID)"
|
|
184
|
+
return $EXIT_SUCCESS
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
execute_subagent_dry_run() {
|
|
188
|
+
local subagent_file="$1"
|
|
189
|
+
local context_file="$2"
|
|
190
|
+
|
|
191
|
+
local subagent_name
|
|
192
|
+
subagent_name=$(basename "$subagent_file" "$SUBAGENT_FILE_EXTENSION")
|
|
193
|
+
|
|
194
|
+
log_info "DRY RUN: Would execute subagent: $subagent_name"
|
|
195
|
+
|
|
196
|
+
# Show what would be executed
|
|
197
|
+
cat <<EOF
|
|
198
|
+
Dry Run Execution Plan:
|
|
199
|
+
======================
|
|
200
|
+
Subagent: $subagent_name
|
|
201
|
+
File: $subagent_file
|
|
202
|
+
Context: $context_file
|
|
203
|
+
Output: $EXECUTION_OUTPUT_FILE
|
|
204
|
+
Error Log: $EXECUTION_ERROR_FILE
|
|
205
|
+
|
|
206
|
+
Context Summary:
|
|
207
|
+
$(head -10 "$context_file" 2>/dev/null || echo "Context file not readable")
|
|
208
|
+
|
|
209
|
+
Subagent Metadata:
|
|
210
|
+
$(extract_subagent_metadata "$subagent_file")
|
|
211
|
+
|
|
212
|
+
Execution would proceed with simulated Claude invocation.
|
|
213
|
+
EOF
|
|
214
|
+
|
|
215
|
+
log_info "Dry run completed: $subagent_name"
|
|
216
|
+
return $EXIT_SUCCESS
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
##################################
|
|
220
|
+
# Simulation and Results
|
|
221
|
+
##################################
|
|
222
|
+
# See: execution-simulation.sh, execution-results.sh
|
|
223
|
+
|
|
224
|
+
##################################
|
|
225
|
+
# Multiple Subagent Execution
|
|
226
|
+
##################################
|
|
227
|
+
|
|
228
|
+
execute_multiple_subagents() {
|
|
229
|
+
local event_type="$1"
|
|
230
|
+
local context_file="$2"
|
|
231
|
+
local execution_mode="${3:-auto}"
|
|
232
|
+
|
|
233
|
+
log_info "Executing multiple subagents for event: $event_type"
|
|
234
|
+
|
|
235
|
+
# Get subagents for the event
|
|
236
|
+
local subagents
|
|
237
|
+
if ! subagents=$(get_subagents_for_event "$event_type"); then
|
|
238
|
+
log_error "Failed to get subagents for event: $event_type"
|
|
239
|
+
return $EXIT_GENERAL_ERROR
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
if [[ -z "$subagents" ]]; then
|
|
243
|
+
log_info "No subagents configured for event: $event_type"
|
|
244
|
+
return $EXIT_SUCCESS
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
local any_failures=false
|
|
248
|
+
local executed_count=0
|
|
249
|
+
|
|
250
|
+
# Execute each subagent
|
|
251
|
+
while IFS= read -r subagent_name; do
|
|
252
|
+
[[ -z "$subagent_name" ]] && continue
|
|
253
|
+
|
|
254
|
+
((executed_count++))
|
|
255
|
+
log_info "Executing subagent $executed_count: $subagent_name"
|
|
256
|
+
|
|
257
|
+
# Find subagent file
|
|
258
|
+
local subagent_file
|
|
259
|
+
if ! subagent_file=$(find_subagent "$subagent_name"); then
|
|
260
|
+
log_error "Subagent not found: $subagent_name"
|
|
261
|
+
any_failures=true
|
|
262
|
+
continue
|
|
263
|
+
fi
|
|
264
|
+
|
|
265
|
+
# Determine execution mode for this subagent
|
|
266
|
+
local subagent_mode
|
|
267
|
+
subagent_mode=$(determine_execution_mode "$event_type" "$execution_mode")
|
|
268
|
+
|
|
269
|
+
# Get timeout for this execution
|
|
270
|
+
local timeout
|
|
271
|
+
timeout=$(get_timeout_for_execution "$event_type" "$subagent_name")
|
|
272
|
+
|
|
273
|
+
# Execute the subagent
|
|
274
|
+
if ! execute_subagent "$subagent_file" "$context_file" "$subagent_mode" "$timeout"; then
|
|
275
|
+
log_error "Failed to execute subagent: $subagent_name"
|
|
276
|
+
any_failures=true
|
|
277
|
+
|
|
278
|
+
# In blocking mode, stop on first failure
|
|
279
|
+
if [[ "$subagent_mode" == "blocking" ]]; then
|
|
280
|
+
log_error "Blocking execution failed, stopping remaining subagents"
|
|
281
|
+
break
|
|
282
|
+
fi
|
|
283
|
+
else
|
|
284
|
+
log_info "Successfully executed subagent: $subagent_name"
|
|
285
|
+
fi
|
|
286
|
+
done <<< "$subagents"
|
|
287
|
+
|
|
288
|
+
log_info "Multiple subagent execution completed (executed: $executed_count)"
|
|
289
|
+
|
|
290
|
+
if [[ "$any_failures" == true ]]; then
|
|
291
|
+
log_error "Some subagent executions failed"
|
|
292
|
+
return $EXIT_EXECUTION_FAILED
|
|
293
|
+
fi
|
|
294
|
+
|
|
295
|
+
return $EXIT_SUCCESS
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
##################################
|
|
299
|
+
# Execution Environment Functions
|
|
300
|
+
##################################
|
|
301
|
+
|
|
302
|
+
prepare_execution_environment() {
|
|
303
|
+
local subagent_name="$1"
|
|
304
|
+
|
|
305
|
+
log_debug "Preparing execution environment for: $subagent_name"
|
|
306
|
+
|
|
307
|
+
# Create output files
|
|
308
|
+
EXECUTION_OUTPUT_FILE=$(create_temp_file "$OUTPUT_FILE_PREFIX" "$subagent_name-$$")
|
|
309
|
+
if [[ $? -ne $EXIT_SUCCESS ]]; then
|
|
310
|
+
log_error "Failed to create output file"
|
|
311
|
+
return $EXIT_GENERAL_ERROR
|
|
312
|
+
fi
|
|
313
|
+
|
|
314
|
+
EXECUTION_ERROR_FILE="${EXECUTION_OUTPUT_FILE}.err"
|
|
315
|
+
if ! touch "$EXECUTION_ERROR_FILE"; then
|
|
316
|
+
log_error "Failed to create error file"
|
|
317
|
+
return $EXIT_GENERAL_ERROR
|
|
318
|
+
fi
|
|
319
|
+
|
|
320
|
+
# Set secure permissions
|
|
321
|
+
chmod "$SECURE_FILE_PERMISSIONS" "$EXECUTION_OUTPUT_FILE" "$EXECUTION_ERROR_FILE"
|
|
322
|
+
|
|
323
|
+
log_debug "Execution environment prepared:"
|
|
324
|
+
log_debug " Output: $EXECUTION_OUTPUT_FILE"
|
|
325
|
+
log_debug " Error: $EXECUTION_ERROR_FILE"
|
|
326
|
+
|
|
327
|
+
return $EXIT_SUCCESS
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
cleanup_execution_environment() {
|
|
331
|
+
local keep_logs="${1:-false}"
|
|
332
|
+
|
|
333
|
+
log_debug "Cleaning up execution environment"
|
|
334
|
+
|
|
335
|
+
# Clean up output files unless keeping logs
|
|
336
|
+
if [[ "$keep_logs" != true ]]; then
|
|
337
|
+
[[ -n "$EXECUTION_OUTPUT_FILE" ]] && rm -f "$EXECUTION_OUTPUT_FILE"
|
|
338
|
+
[[ -n "$EXECUTION_ERROR_FILE" ]] && rm -f "$EXECUTION_ERROR_FILE"
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
# Kill background processes if any
|
|
342
|
+
if [[ -n "$EXECUTION_PID" ]]; then
|
|
343
|
+
if kill -0 "$EXECUTION_PID" 2>/dev/null; then
|
|
344
|
+
log_debug "Terminating background execution: $EXECUTION_PID"
|
|
345
|
+
kill "$EXECUTION_PID" 2>/dev/null || true
|
|
346
|
+
fi
|
|
347
|
+
fi
|
|
348
|
+
|
|
349
|
+
# Reset global variables
|
|
350
|
+
EXECUTION_PID=""
|
|
351
|
+
EXECUTION_START_TIME=""
|
|
352
|
+
EXECUTION_OUTPUT_FILE=""
|
|
353
|
+
EXECUTION_ERROR_FILE=""
|
|
354
|
+
EXECUTION_RESULT=""
|
|
355
|
+
|
|
356
|
+
log_debug "Execution environment cleanup completed"
|
|
357
|
+
return $EXIT_SUCCESS
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
##################################
|
|
361
|
+
# Execution Status Functions
|
|
362
|
+
##################################
|
|
363
|
+
|
|
364
|
+
get_execution_status() {
|
|
365
|
+
if [[ -n "$EXECUTION_PID" ]]; then
|
|
366
|
+
if kill -0 "$EXECUTION_PID" 2>/dev/null; then
|
|
367
|
+
echo "running"
|
|
368
|
+
else
|
|
369
|
+
echo "completed"
|
|
370
|
+
fi
|
|
371
|
+
else
|
|
372
|
+
echo "not_started"
|
|
373
|
+
fi
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
wait_for_execution() {
|
|
377
|
+
local timeout_seconds="${1:-30}"
|
|
378
|
+
|
|
379
|
+
if [[ -z "$EXECUTION_PID" ]]; then
|
|
380
|
+
log_debug "No execution to wait for"
|
|
381
|
+
return $EXIT_SUCCESS
|
|
382
|
+
fi
|
|
383
|
+
|
|
384
|
+
log_debug "Waiting for execution to complete (timeout: ${timeout_seconds}s)"
|
|
385
|
+
|
|
386
|
+
local waited=0
|
|
387
|
+
while kill -0 "$EXECUTION_PID" 2>/dev/null; do
|
|
388
|
+
sleep 1
|
|
389
|
+
((waited++))
|
|
390
|
+
|
|
391
|
+
if [[ $waited -ge $timeout_seconds ]]; then
|
|
392
|
+
log_warning "Execution timeout reached, terminating process"
|
|
393
|
+
kill "$EXECUTION_PID" 2>/dev/null || true
|
|
394
|
+
return $EXIT_TIMEOUT
|
|
395
|
+
fi
|
|
396
|
+
done
|
|
397
|
+
|
|
398
|
+
# Get exit status
|
|
399
|
+
wait "$EXECUTION_PID" 2>/dev/null
|
|
400
|
+
local exit_status=$?
|
|
401
|
+
|
|
402
|
+
log_debug "Execution completed with status: $exit_status"
|
|
403
|
+
return $exit_status
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
##################################
|
|
407
|
+
# Utility Functions
|
|
408
|
+
##################################
|
|
409
|
+
|
|
410
|
+
extract_subagent_metadata() {
|
|
411
|
+
local subagent_file="$1"
|
|
412
|
+
|
|
413
|
+
if [[ ! -f "$subagent_file" ]]; then
|
|
414
|
+
echo "File not found"
|
|
415
|
+
return
|
|
416
|
+
fi
|
|
417
|
+
|
|
418
|
+
local name description version tools
|
|
419
|
+
name=$(extract_frontmatter_field "$subagent_file" "name" false 2>/dev/null || echo "Unknown")
|
|
420
|
+
description=$(extract_frontmatter_field "$subagent_file" "description" false 2>/dev/null || echo "No description")
|
|
421
|
+
version=$(extract_frontmatter_field "$subagent_file" "version" false 2>/dev/null || echo "Unknown")
|
|
422
|
+
tools=$(extract_frontmatter_field "$subagent_file" "tools" false 2>/dev/null || echo "All")
|
|
423
|
+
|
|
424
|
+
cat <<EOF
|
|
425
|
+
Name: $name
|
|
426
|
+
Description: $description
|
|
427
|
+
Version: $version
|
|
428
|
+
Tools: $tools
|
|
429
|
+
EOF
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
##################################
|
|
433
|
+
# Initialization
|
|
434
|
+
##################################
|
|
435
|
+
|
|
436
|
+
initialize_execution_engine() {
|
|
437
|
+
log_debug "Execution engine module initialized"
|
|
438
|
+
|
|
439
|
+
# Set up signal handlers for cleanup
|
|
440
|
+
trap 'cleanup_execution_environment' EXIT
|
|
441
|
+
trap 'cleanup_execution_environment; exit 130' INT TERM
|
|
442
|
+
|
|
443
|
+
return $EXIT_SUCCESS
|
|
444
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
|
|
4
|
+
# Execution Results Module
|
|
5
|
+
#
|
|
6
|
+
# Provides result processing, blocking condition detection,
|
|
7
|
+
# and output handling for subagent executions.
|
|
8
|
+
# Extracted from execution-engine.sh.
|
|
9
|
+
|
|
10
|
+
# Include guard
|
|
11
|
+
[[ -n "${_EXECUTION_RESULTS_LOADED:-}" ]] && return 0
|
|
12
|
+
_EXECUTION_RESULTS_LOADED=1
|
|
13
|
+
|
|
14
|
+
# Source required modules
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
source "$SCRIPT_DIR/config-constants.sh"
|
|
17
|
+
source "$SCRIPT_DIR/file-utils.sh"
|
|
18
|
+
source "$SCRIPT_DIR/error-handler.sh"
|
|
19
|
+
|
|
20
|
+
##################################
|
|
21
|
+
# Result Processing Functions
|
|
22
|
+
##################################
|
|
23
|
+
|
|
24
|
+
process_execution_results() {
|
|
25
|
+
local subagent_name="$1"
|
|
26
|
+
local execution_mode="$2"
|
|
27
|
+
|
|
28
|
+
log_debug "Processing execution results for: $subagent_name"
|
|
29
|
+
|
|
30
|
+
if [[ ! -f "$EXECUTION_OUTPUT_FILE" ]]; then
|
|
31
|
+
log_error "Execution output file not found: $EXECUTION_OUTPUT_FILE"
|
|
32
|
+
return $EXIT_EXECUTION_FAILED
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Read execution output
|
|
36
|
+
local output_content
|
|
37
|
+
if ! output_content=$(read_file_safely "$EXECUTION_OUTPUT_FILE"); then
|
|
38
|
+
log_error "Failed to read execution output"
|
|
39
|
+
return $EXIT_EXECUTION_FAILED
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
EXECUTION_RESULT="$output_content"
|
|
43
|
+
|
|
44
|
+
# Check for blocking conditions in output
|
|
45
|
+
if check_for_blocking_conditions "$output_content"; then
|
|
46
|
+
log_warning "Subagent $subagent_name recommends BLOCKING the operation"
|
|
47
|
+
|
|
48
|
+
if [[ "$execution_mode" == "blocking" ]]; then
|
|
49
|
+
display_blocking_message "$subagent_name" "$output_content"
|
|
50
|
+
return $EXIT_EXECUTION_FAILED
|
|
51
|
+
else
|
|
52
|
+
log_warning "Non-blocking mode: continuing despite blocking recommendation"
|
|
53
|
+
fi
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
log_info "Execution results processed successfully: $subagent_name"
|
|
57
|
+
return $EXIT_SUCCESS
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
check_for_blocking_conditions() {
|
|
61
|
+
local output_content="$1"
|
|
62
|
+
|
|
63
|
+
# First check for positive/safe patterns - these override blocking
|
|
64
|
+
local safe_patterns=(
|
|
65
|
+
"Operation appears safe to proceed"
|
|
66
|
+
"Continue with planned action"
|
|
67
|
+
"No security violations detected"
|
|
68
|
+
"Status: Executed successfully"
|
|
69
|
+
"safe to proceed"
|
|
70
|
+
"continue with"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
local pattern
|
|
74
|
+
for pattern in "${safe_patterns[@]}"; do
|
|
75
|
+
if echo "$output_content" | grep -qi "$pattern"; then
|
|
76
|
+
log_debug "Safe operation pattern found: $pattern"
|
|
77
|
+
return $EXIT_GENERAL_ERROR # No blocking condition
|
|
78
|
+
fi
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
# Look for explicit blocking directives only
|
|
82
|
+
local blocking_patterns=(
|
|
83
|
+
"OPERATION MUST BE BLOCKED"
|
|
84
|
+
"SECURITY VIOLATION DETECTED"
|
|
85
|
+
"CRITICAL ERROR - STOP"
|
|
86
|
+
"STOP EXECUTION IMMEDIATELY"
|
|
87
|
+
"ABORT OPERATION"
|
|
88
|
+
"BLOCK THIS OPERATION"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
for pattern in "${blocking_patterns[@]}"; do
|
|
92
|
+
if echo "$output_content" | grep -qi "$pattern"; then
|
|
93
|
+
log_debug "Blocking pattern found: $pattern"
|
|
94
|
+
return $EXIT_SUCCESS # Found blocking condition
|
|
95
|
+
fi
|
|
96
|
+
done
|
|
97
|
+
|
|
98
|
+
# Default: allow operation
|
|
99
|
+
log_debug "No explicit blocking conditions found, allowing operation"
|
|
100
|
+
return $EXIT_GENERAL_ERROR
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
display_blocking_message() {
|
|
104
|
+
local subagent_name="$1"
|
|
105
|
+
local output_content="$2"
|
|
106
|
+
|
|
107
|
+
echo "OPERATION BLOCKED by subagent: $subagent_name" >&2
|
|
108
|
+
echo "" >&2
|
|
109
|
+
echo "Reason:" >&2
|
|
110
|
+
echo "$output_content" | head -20 >&2
|
|
111
|
+
echo "" >&2
|
|
112
|
+
echo "The operation has been blocked for safety. Please review the subagent's feedback above." >&2
|
|
113
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
|
|
4
|
+
# Execution Simulation Module
|
|
5
|
+
#
|
|
6
|
+
# Provides mock/simulation execution of subagents for testing
|
|
7
|
+
# and development. Extracted from execution-engine.sh.
|
|
8
|
+
|
|
9
|
+
# Include guard
|
|
10
|
+
[[ -n "${_EXECUTION_SIMULATION_LOADED:-}" ]] && return 0
|
|
11
|
+
_EXECUTION_SIMULATION_LOADED=1
|
|
12
|
+
|
|
13
|
+
# Source required modules
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
source "$SCRIPT_DIR/config-constants.sh"
|
|
16
|
+
source "$SCRIPT_DIR/file-utils.sh"
|
|
17
|
+
source "$SCRIPT_DIR/error-handler.sh"
|
|
18
|
+
|
|
19
|
+
##################################
|
|
20
|
+
# Subagent Simulation Functions
|
|
21
|
+
##################################
|
|
22
|
+
|
|
23
|
+
execute_subagent_simulation() {
|
|
24
|
+
local subagent_file="$1"
|
|
25
|
+
local context_file="$2"
|
|
26
|
+
local timeout="$3"
|
|
27
|
+
|
|
28
|
+
local subagent_name
|
|
29
|
+
subagent_name=$(basename "$subagent_file" "$SUBAGENT_FILE_EXTENSION")
|
|
30
|
+
|
|
31
|
+
log_debug "Simulating subagent execution: $subagent_name"
|
|
32
|
+
|
|
33
|
+
# Extract subagent configuration
|
|
34
|
+
local tools description
|
|
35
|
+
tools=$(extract_frontmatter_field "$subagent_file" "tools" false 2>/dev/null || echo "all")
|
|
36
|
+
description=$(extract_frontmatter_field "$subagent_file" "description" false 2>/dev/null || echo "No description")
|
|
37
|
+
|
|
38
|
+
# Create simulated output
|
|
39
|
+
local simulation_output
|
|
40
|
+
simulation_output=$(cat <<EOF
|
|
41
|
+
Subagent Execution Report
|
|
42
|
+
========================
|
|
43
|
+
Name: $subagent_name
|
|
44
|
+
Description: $description
|
|
45
|
+
Tools: ${tools:-all}
|
|
46
|
+
Execution Time: $(date)
|
|
47
|
+
Status: Executed successfully
|
|
48
|
+
|
|
49
|
+
Context Analysis:
|
|
50
|
+
$(analyze_context_for_simulation "$context_file")
|
|
51
|
+
|
|
52
|
+
Recommendations:
|
|
53
|
+
- Operation appears safe to proceed
|
|
54
|
+
- No security violations detected
|
|
55
|
+
- Code style conforms to standards
|
|
56
|
+
- Continue with planned action
|
|
57
|
+
|
|
58
|
+
Execution Summary:
|
|
59
|
+
- Analysis completed successfully
|
|
60
|
+
- No blocking issues found
|
|
61
|
+
- Ready for next step in workflow
|
|
62
|
+
EOF
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Write to output file
|
|
66
|
+
if ! echo "$simulation_output" > "$EXECUTION_OUTPUT_FILE"; then
|
|
67
|
+
log_error "Failed to write simulation output"
|
|
68
|
+
return $EXIT_EXECUTION_FAILED
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Simulate processing time (shorter for testing)
|
|
72
|
+
sleep 1
|
|
73
|
+
|
|
74
|
+
# Check for timeout simulation
|
|
75
|
+
local execution_time=$(($(date +%s) - EXECUTION_START_TIME))
|
|
76
|
+
local timeout_seconds=$((timeout / 1000))
|
|
77
|
+
|
|
78
|
+
if [[ $execution_time -gt $timeout_seconds ]]; then
|
|
79
|
+
log_error "Simulated timeout exceeded: ${execution_time}s > ${timeout_seconds}s"
|
|
80
|
+
return $EXIT_TIMEOUT
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
log_debug "Subagent simulation completed successfully: $subagent_name"
|
|
84
|
+
return $EXIT_SUCCESS
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
analyze_context_for_simulation() {
|
|
88
|
+
local context_file="$1"
|
|
89
|
+
|
|
90
|
+
if [[ ! -f "$context_file" ]]; then
|
|
91
|
+
echo "Context file not available"
|
|
92
|
+
return
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Extract key information from context
|
|
96
|
+
local event_type file_path git_branch
|
|
97
|
+
|
|
98
|
+
if command -v jq >/dev/null 2>&1; then
|
|
99
|
+
event_type=$(jq -r '.event.type // "unknown"' "$context_file" 2>/dev/null)
|
|
100
|
+
file_path=$(jq -r '.file.path // "none"' "$context_file" 2>/dev/null)
|
|
101
|
+
git_branch=$(jq -r '.git.branch // "unknown"' "$context_file" 2>/dev/null)
|
|
102
|
+
else
|
|
103
|
+
event_type="unknown"
|
|
104
|
+
file_path="none"
|
|
105
|
+
git_branch="unknown"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
cat <<EOF
|
|
109
|
+
- Event Type: $event_type
|
|
110
|
+
- Target File: $file_path
|
|
111
|
+
- Git Branch: $git_branch
|
|
112
|
+
- Analysis: Standard workflow operation detected
|
|
113
|
+
EOF
|
|
114
|
+
}
|