claude-flow-novice 2.14.14 → 2.14.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/cfn-loop-cli.md +21 -27
- package/claude-assets/commands/cfn-loop-cli.md +21 -27
- package/claude-assets/skills/cfn-multi-coordinator-planning/map-dependencies-conflicts.sh +375 -375
- package/claude-assets/skills/cfn-multi-coordinator-planning/plan-coordinator-resources.sh +257 -257
- package/claude-assets/skills/cfn-multi-coordinator-planning/plan-multi-coordinator-work.sh +266 -266
- package/claude-assets/skills/cfn-multi-coordinator-planning/plan-risk-rollout.sh +349 -349
- package/claude-assets/skills/cfn-multi-coordinator-planning/test-multi-coordinator-planning.sh +337 -337
- package/claude-assets/skills/cfn-multi-coordinator-planning/validate-task-planning.sh +188 -188
- package/dist/agent/skill-mcp-selector.js +459 -0
- package/dist/agent/skill-mcp-selector.js.map +1 -0
- package/dist/cli/agent-token-manager.js +382 -0
- package/dist/cli/agent-token-manager.js.map +1 -0
- package/dist/cli/config-manager.js +91 -109
- package/dist/cli/config-manager.js.map +1 -1
- package/dist/mcp/auth-middleware.js +367 -0
- package/dist/mcp/auth-middleware.js.map +1 -0
- package/dist/mcp/playwright-mcp-server-auth.js +515 -0
- package/dist/mcp/playwright-mcp-server-auth.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,350 +1,350 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
set -euo pipefail
|
|
4
|
-
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
-
|
|
7
|
-
# Configuration
|
|
8
|
-
DEFAULT_PHASE_TIMEOUT=1800 # 30 minutes per phase
|
|
9
|
-
DEFAULT_ROLLBACK_TIMEOUT=600 # 10 minutes for rollback
|
|
10
|
-
SUCCESS_THRESHOLD=0.85
|
|
11
|
-
|
|
12
|
-
# Colors
|
|
13
|
-
RED='\033[0;31m'
|
|
14
|
-
GREEN='\033[0;32m'
|
|
15
|
-
YELLOW='\033[1;33m'
|
|
16
|
-
BLUE='\033[0;34m'
|
|
17
|
-
NC='\033[0m'
|
|
18
|
-
|
|
19
|
-
log() {
|
|
20
|
-
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
warn() {
|
|
24
|
-
echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}"
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
error() {
|
|
28
|
-
echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}"
|
|
29
|
-
exit 1
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
info() {
|
|
33
|
-
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1${NC}"
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
calculate_zone_complexity() {
|
|
37
|
-
local zone_data="$1"
|
|
38
|
-
local complexity_score=0
|
|
39
|
-
|
|
40
|
-
# Base complexity from agent count
|
|
41
|
-
local agent_count
|
|
42
|
-
agent_count=$(echo "$zone_data" | jq -r '.agent_types | length // 0')
|
|
43
|
-
complexity_score=$((complexity_score + agent_count * 10))
|
|
44
|
-
|
|
45
|
-
# Complexity from deliverable count
|
|
46
|
-
local deliverable_count
|
|
47
|
-
deliverable_count=$(echo "$zone_data" | jq -r '.deliverables | length // 0')
|
|
48
|
-
complexity_score=$((complexity_score + deliverable_count * 5))
|
|
49
|
-
|
|
50
|
-
# Complexity from task description length (longer = more complex)
|
|
51
|
-
local task_description
|
|
52
|
-
task_description=$(echo "$zone_data" | jq -r '.task_description // ""')
|
|
53
|
-
local description_length=${#task_description}
|
|
54
|
-
if [[ $description_length -gt 100 ]]; then
|
|
55
|
-
complexity_score=$((complexity_score + 15))
|
|
56
|
-
elif [[ $description_length -gt 50 ]]; then
|
|
57
|
-
complexity_score=$((complexity_score + 10))
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
# Complexity from acceptance criteria
|
|
61
|
-
local acceptance_count
|
|
62
|
-
acceptance_count=$(echo "$zone_data" | jq -r '.acceptance_criteria | length // 0')
|
|
63
|
-
complexity_score=$((complexity_score + acceptance_count * 8))
|
|
64
|
-
|
|
65
|
-
# Risk factors
|
|
66
|
-
if echo "$zone_data" | jq -e '.risk_factors' >/dev/null 2>&1; then
|
|
67
|
-
local risk_factors
|
|
68
|
-
risk_factors=$(echo "$zone_data" | jq -r '.risk_factors | length // 0')
|
|
69
|
-
complexity_score=$((complexity_score + risk_factors * 20))
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
echo "$complexity_score"
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
rank_zones_by_complexity() {
|
|
76
|
-
local zone_config="$1"
|
|
77
|
-
local zones_with_complexity="[]"
|
|
78
|
-
|
|
79
|
-
local i=0
|
|
80
|
-
while IFS= read -r zone_name; do
|
|
81
|
-
local zone_data
|
|
82
|
-
zone_data=$(echo "$zone_config" | jq -r ".zones[$i]")
|
|
83
|
-
|
|
84
|
-
local complexity
|
|
85
|
-
complexity=$(calculate_zone_complexity "$zone_data")
|
|
86
|
-
|
|
87
|
-
local zone_entry="{
|
|
88
|
-
\"name\": \"$zone_name\",
|
|
89
|
-
\"complexity_score\": $complexity,
|
|
90
|
-
\"data\": $zone_data
|
|
91
|
-
}"
|
|
92
|
-
|
|
93
|
-
zones_with_complexity=$(echo "$zones_with_complexity" | jq ". + [$zone_entry]")
|
|
94
|
-
((i++))
|
|
95
|
-
done < <(echo "$zone_config" | jq -r '.zones[].name')
|
|
96
|
-
|
|
97
|
-
# Sort by complexity score (ascending)
|
|
98
|
-
echo "$zones_with_complexity" | jq 'sort_by(.complexity_score)'
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
create_rollout_phases() {
|
|
102
|
-
local ranked_zones="$1"
|
|
103
|
-
local max_zones_per_phase="${2:-2}"
|
|
104
|
-
|
|
105
|
-
local rollout_phases="[]"
|
|
106
|
-
local phase_number=1
|
|
107
|
-
local i=0
|
|
108
|
-
|
|
109
|
-
while true; do
|
|
110
|
-
local phase_zones="[]"
|
|
111
|
-
local zones_in_phase=0
|
|
112
|
-
|
|
113
|
-
while [[ $zones_in_phase -lt $max_zones_per_phase ]]; do
|
|
114
|
-
local zone_data
|
|
115
|
-
zone_data=$(echo "$ranked_zones" | jq ".[$i] // empty")
|
|
116
|
-
|
|
117
|
-
if [[ "$zone_data" == "null" || "$zone_data" == "" ]]; then
|
|
118
|
-
break 2
|
|
119
|
-
fi
|
|
120
|
-
|
|
121
|
-
phase_zones=$(echo "$phase_zones" | jq ". + [$zone_data]")
|
|
122
|
-
((i++))
|
|
123
|
-
((zones_in_phase++))
|
|
124
|
-
done
|
|
125
|
-
|
|
126
|
-
if [[ $zones_in_phase -eq 0 ]]; then
|
|
127
|
-
break
|
|
128
|
-
fi
|
|
129
|
-
|
|
130
|
-
local phase_entry="{
|
|
131
|
-
\"phase\": $phase_number,
|
|
132
|
-
\"zones\": $phase_zones,
|
|
133
|
-
\"max_execution_time\": $DEFAULT_PHASE_TIMEOUT,
|
|
134
|
-
\"success_threshold\": $SUCCESS_THRESHOLD,
|
|
135
|
-
\"rollback_timeout\": $DEFAULT_ROLLBACK_TIMEOUT
|
|
136
|
-
}"
|
|
137
|
-
|
|
138
|
-
rollout_phases=$(echo "$rollout_phases" | jq ". + [$phase_entry]")
|
|
139
|
-
((phase_number++))
|
|
140
|
-
done
|
|
141
|
-
|
|
142
|
-
echo "$rollout_phases"
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
create_success_criteria() {
|
|
146
|
-
local rollout_phases="$1"
|
|
147
|
-
|
|
148
|
-
local success_criteria="[]"
|
|
149
|
-
|
|
150
|
-
local phase_count
|
|
151
|
-
phase_count=$(echo "$rollout_phases" | jq 'length')
|
|
152
|
-
|
|
153
|
-
for ((i=0; i<phase_count; i++)); do
|
|
154
|
-
local phase_data
|
|
155
|
-
phase_data=$(echo "$rollout_phases" | jq ".[$i]")
|
|
156
|
-
|
|
157
|
-
local zone_names
|
|
158
|
-
zone_names=$(echo "$phase_data" | jq -r '.zones[].name')
|
|
159
|
-
|
|
160
|
-
local phase_criteria="{
|
|
161
|
-
\"phase\": $((i + 1)),
|
|
162
|
-
\"required_success_zones\": [],
|
|
163
|
-
\"minimum_confidence_threshold\": $SUCCESS_THRESHOLD,
|
|
164
|
-
\"all_zones_must_complete\": true,
|
|
165
|
-
\"validation_checks\": [
|
|
166
|
-
\"redis_namespace_isolation\",
|
|
167
|
-
\"agent_completion_signaling\",
|
|
168
|
-
\"coordinator_lifecycle_management\",
|
|
169
|
-
\"deliverable_verification\"
|
|
170
|
-
]
|
|
171
|
-
}"
|
|
172
|
-
|
|
173
|
-
# Add required zone names
|
|
174
|
-
local zones_array="[]"
|
|
175
|
-
while IFS= read -r zone_name; do
|
|
176
|
-
zones_array=$(echo "$zones_array" | jq ". + [\"$zone_name\"]")
|
|
177
|
-
done <<< "$zone_names"
|
|
178
|
-
|
|
179
|
-
phase_criteria=$(echo "$phase_criteria" | jq ".required_success_zones = $zones_array")
|
|
180
|
-
success_criteria=$(echo "$success_criteria" | jq ". + [$phase_criteria]")
|
|
181
|
-
done
|
|
182
|
-
|
|
183
|
-
echo "$success_criteria"
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
create_rollback_triggers() {
|
|
187
|
-
local rollout_phases="$1"
|
|
188
|
-
|
|
189
|
-
local rollback_triggers="[]"
|
|
190
|
-
|
|
191
|
-
local phase_count
|
|
192
|
-
phase_count=$(echo "$rollout_phases" | jq 'length')
|
|
193
|
-
|
|
194
|
-
# Global rollback triggers
|
|
195
|
-
local global_triggers="[
|
|
196
|
-
{
|
|
197
|
-
\"trigger\": \"any_zone_critical_failure\",
|
|
198
|
-
\"action\": \"immediate_rollback_all\",
|
|
199
|
-
\"description\": \"Critical system failure in any zone\"
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
\"trigger\": \"redis_namespace_corruption\",
|
|
203
|
-
\"action\": \"emergency_stop_and_cleanup\",
|
|
204
|
-
\"description\": \"Redis namespace isolation breach\"
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
\"trigger\": \"resource_exhaustion\",
|
|
208
|
-
\"action\": \"scale_back_and_retry\",
|
|
209
|
-
\"description\": \"System resources exhausted\"
|
|
210
|
-
}
|
|
211
|
-
]"
|
|
212
|
-
|
|
213
|
-
# Phase-specific rollback triggers
|
|
214
|
-
local i=0
|
|
215
|
-
for ((i=0; i<phase_count; i++)); do
|
|
216
|
-
local phase_zones
|
|
217
|
-
phase_zones=$(echo "$rollout_phases" | jq -r ".[$i].zones[].name")
|
|
218
|
-
|
|
219
|
-
while IFS= read -r zone_name; do
|
|
220
|
-
local trigger="{
|
|
221
|
-
\"trigger\": \"zone_${zone_name}_completion_failure\",
|
|
222
|
-
\"phase\": $((i + 1)),
|
|
223
|
-
\"action\": \"rollback_current_phase\",
|
|
224
|
-
\"description\": \"Zone $zone_name failed to complete in phase $((i + 1))\"
|
|
225
|
-
}"
|
|
226
|
-
|
|
227
|
-
rollback_triggers=$(echo "$rollback_triggers" | jq ". + [$trigger]")
|
|
228
|
-
done <<< "$phase_zones"
|
|
229
|
-
done
|
|
230
|
-
|
|
231
|
-
# Combine global and specific triggers
|
|
232
|
-
echo "$global_triggers" | jq ". + $rollback_triggers"
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
generate_rollout_plan() {
|
|
236
|
-
local zone_config="$1"
|
|
237
|
-
local max_zones_per_phase="${2:-2}"
|
|
238
|
-
|
|
239
|
-
info "Analyzing zone complexity for rollout planning"
|
|
240
|
-
|
|
241
|
-
# Rank zones by complexity
|
|
242
|
-
local ranked_zones
|
|
243
|
-
ranked_zones=$(rank_zones_by_complexity "$zone_config")
|
|
244
|
-
|
|
245
|
-
# Create rollout phases
|
|
246
|
-
local rollout_phases
|
|
247
|
-
rollout_phases=$(create_rollout_phases "$ranked_zones" "$max_zones_per_phase")
|
|
248
|
-
|
|
249
|
-
# Create success criteria
|
|
250
|
-
local success_criteria
|
|
251
|
-
success_criteria=$(create_success_criteria "$rollout_phases")
|
|
252
|
-
|
|
253
|
-
# Create rollback triggers
|
|
254
|
-
local rollback_triggers
|
|
255
|
-
rollback_triggers=$(create_rollback_triggers "$rollout_phases")
|
|
256
|
-
|
|
257
|
-
# Generate complete rollout plan
|
|
258
|
-
local rollout_plan="{
|
|
259
|
-
\"timestamp\": $(date '+%s'),
|
|
260
|
-
\"total_zones\": $(echo "$zone_config" | jq '.zones | length'),
|
|
261
|
-
\"max_zones_per_phase\": $max_zones_per_phase,
|
|
262
|
-
\"phases\": $rollout_phases,
|
|
263
|
-
\"success_criteria\": $success_criteria,
|
|
264
|
-
\"rollback_triggers\": $rollback_triggers,
|
|
265
|
-
\"execution_strategy\": {
|
|
266
|
-
\"type\": \"graduated_rollout\",
|
|
267
|
-
\"monitoring_level\": \"enhanced\",
|
|
268
|
-
\"auto_rollback_enabled\": true,
|
|
269
|
-
\"manual_approval_required\": false
|
|
270
|
-
}
|
|
271
|
-
}"
|
|
272
|
-
|
|
273
|
-
echo "$rollout_plan"
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
display_rollout_summary() {
|
|
277
|
-
local rollout_plan="$1"
|
|
278
|
-
|
|
279
|
-
echo
|
|
280
|
-
info "=== Risk-Based Rollout Plan ==="
|
|
281
|
-
echo "Total zones: $(echo "$rollout_plan" | jq -r '.total_zones')"
|
|
282
|
-
echo "Maximum zones per phase: $(echo "$rollout_plan" | jq -r '.max_zones_per_phase')"
|
|
283
|
-
echo
|
|
284
|
-
|
|
285
|
-
local phase_count
|
|
286
|
-
phase_count=$(echo "$rollout_plan" | jq '.phases | length')
|
|
287
|
-
|
|
288
|
-
echo "Rollout Phases:"
|
|
289
|
-
for ((i=0; i<phase_count; i++)); do
|
|
290
|
-
local phase_data
|
|
291
|
-
phase_data=$(echo "$rollout_plan" | jq ".phases[$i]")
|
|
292
|
-
local phase_number=$((i + 1))
|
|
293
|
-
local zone_count
|
|
294
|
-
zone_count=$(echo "$phase_data" | jq '.zones | length')
|
|
295
|
-
local zone_names
|
|
296
|
-
zone_names=$(echo "$phase_data" | jq -r '.zones[].name' | tr '\n' ', ' | sed 's/,$//')
|
|
297
|
-
|
|
298
|
-
echo " Phase $phase_number: $zone_names ($zone_count zones)"
|
|
299
|
-
done
|
|
300
|
-
echo
|
|
301
|
-
|
|
302
|
-
echo "Success Criteria:"
|
|
303
|
-
echo " - Minimum confidence threshold: $(echo "$rollout_plan" | jq -r '.success_criteria[0].minimum_confidence_threshold')"
|
|
304
|
-
echo " - All zones must complete: $(echo "$rollout_plan" | jq -r '.success_criteria[0].all_zones_must_complete')"
|
|
305
|
-
echo " - Validation checks: $(echo "$rollout_plan" | jq -r '.success_criteria[0].validation_checks | length') checks"
|
|
306
|
-
echo
|
|
307
|
-
|
|
308
|
-
echo "Rollback Triggers:"
|
|
309
|
-
echo " - Global triggers: 3"
|
|
310
|
-
echo " - Phase-specific triggers: $(echo "$rollout_plan" | jq '.rollback_triggers | length - 3')"
|
|
311
|
-
echo
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
main() {
|
|
315
|
-
local config_file="$1"
|
|
316
|
-
local max_zones_per_phase="${2:-2}"
|
|
317
|
-
|
|
318
|
-
if [[ -z "$config_file" ]]; then
|
|
319
|
-
error "Usage: $0 <zone-config-file> [max-zones-per-phase]"
|
|
320
|
-
fi
|
|
321
|
-
|
|
322
|
-
if [[ ! -f "$config_file" ]]; then
|
|
323
|
-
error "Configuration file not found: $config_file"
|
|
324
|
-
fi
|
|
325
|
-
|
|
326
|
-
log "Starting risk-based rollout planning for: $config_file"
|
|
327
|
-
|
|
328
|
-
# Read configuration
|
|
329
|
-
local zone_config
|
|
330
|
-
if ! zone_config=$(jq . "$config_file" 2>/dev/null); then
|
|
331
|
-
error "Invalid JSON in configuration file: $config_file"
|
|
332
|
-
fi
|
|
333
|
-
|
|
334
|
-
# Generate rollout plan
|
|
335
|
-
local rollout_plan
|
|
336
|
-
rollout_plan=$(generate_rollout_plan "$zone_config" "$max_zones_per_phase")
|
|
337
|
-
|
|
338
|
-
# Save rollout plan
|
|
339
|
-
local output_file="/tmp/rollout-plan-$(date '+%s').json"
|
|
340
|
-
echo "$rollout_plan" > "$output_file"
|
|
341
|
-
|
|
342
|
-
log "✅ Risk-based rollout planning completed"
|
|
343
|
-
log "Rollout plan saved to: $output_file"
|
|
344
|
-
|
|
345
|
-
# Display summary
|
|
346
|
-
display_rollout_summary "$rollout_plan"
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
# Execute main function with all arguments
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
|
|
7
|
+
# Configuration
|
|
8
|
+
DEFAULT_PHASE_TIMEOUT=1800 # 30 minutes per phase
|
|
9
|
+
DEFAULT_ROLLBACK_TIMEOUT=600 # 10 minutes for rollback
|
|
10
|
+
SUCCESS_THRESHOLD=0.85
|
|
11
|
+
|
|
12
|
+
# Colors
|
|
13
|
+
RED='\033[0;31m'
|
|
14
|
+
GREEN='\033[0;32m'
|
|
15
|
+
YELLOW='\033[1;33m'
|
|
16
|
+
BLUE='\033[0;34m'
|
|
17
|
+
NC='\033[0m'
|
|
18
|
+
|
|
19
|
+
log() {
|
|
20
|
+
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
warn() {
|
|
24
|
+
echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
error() {
|
|
28
|
+
echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}"
|
|
29
|
+
exit 1
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
info() {
|
|
33
|
+
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1${NC}"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
calculate_zone_complexity() {
|
|
37
|
+
local zone_data="$1"
|
|
38
|
+
local complexity_score=0
|
|
39
|
+
|
|
40
|
+
# Base complexity from agent count
|
|
41
|
+
local agent_count
|
|
42
|
+
agent_count=$(echo "$zone_data" | jq -r '.agent_types | length // 0')
|
|
43
|
+
complexity_score=$((complexity_score + agent_count * 10))
|
|
44
|
+
|
|
45
|
+
# Complexity from deliverable count
|
|
46
|
+
local deliverable_count
|
|
47
|
+
deliverable_count=$(echo "$zone_data" | jq -r '.deliverables | length // 0')
|
|
48
|
+
complexity_score=$((complexity_score + deliverable_count * 5))
|
|
49
|
+
|
|
50
|
+
# Complexity from task description length (longer = more complex)
|
|
51
|
+
local task_description
|
|
52
|
+
task_description=$(echo "$zone_data" | jq -r '.task_description // ""')
|
|
53
|
+
local description_length=${#task_description}
|
|
54
|
+
if [[ $description_length -gt 100 ]]; then
|
|
55
|
+
complexity_score=$((complexity_score + 15))
|
|
56
|
+
elif [[ $description_length -gt 50 ]]; then
|
|
57
|
+
complexity_score=$((complexity_score + 10))
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Complexity from acceptance criteria
|
|
61
|
+
local acceptance_count
|
|
62
|
+
acceptance_count=$(echo "$zone_data" | jq -r '.acceptance_criteria | length // 0')
|
|
63
|
+
complexity_score=$((complexity_score + acceptance_count * 8))
|
|
64
|
+
|
|
65
|
+
# Risk factors
|
|
66
|
+
if echo "$zone_data" | jq -e '.risk_factors' >/dev/null 2>&1; then
|
|
67
|
+
local risk_factors
|
|
68
|
+
risk_factors=$(echo "$zone_data" | jq -r '.risk_factors | length // 0')
|
|
69
|
+
complexity_score=$((complexity_score + risk_factors * 20))
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
echo "$complexity_score"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
rank_zones_by_complexity() {
|
|
76
|
+
local zone_config="$1"
|
|
77
|
+
local zones_with_complexity="[]"
|
|
78
|
+
|
|
79
|
+
local i=0
|
|
80
|
+
while IFS= read -r zone_name; do
|
|
81
|
+
local zone_data
|
|
82
|
+
zone_data=$(echo "$zone_config" | jq -r ".zones[$i]")
|
|
83
|
+
|
|
84
|
+
local complexity
|
|
85
|
+
complexity=$(calculate_zone_complexity "$zone_data")
|
|
86
|
+
|
|
87
|
+
local zone_entry="{
|
|
88
|
+
\"name\": \"$zone_name\",
|
|
89
|
+
\"complexity_score\": $complexity,
|
|
90
|
+
\"data\": $zone_data
|
|
91
|
+
}"
|
|
92
|
+
|
|
93
|
+
zones_with_complexity=$(echo "$zones_with_complexity" | jq ". + [$zone_entry]")
|
|
94
|
+
((i++))
|
|
95
|
+
done < <(echo "$zone_config" | jq -r '.zones[].name')
|
|
96
|
+
|
|
97
|
+
# Sort by complexity score (ascending)
|
|
98
|
+
echo "$zones_with_complexity" | jq 'sort_by(.complexity_score)'
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
create_rollout_phases() {
|
|
102
|
+
local ranked_zones="$1"
|
|
103
|
+
local max_zones_per_phase="${2:-2}"
|
|
104
|
+
|
|
105
|
+
local rollout_phases="[]"
|
|
106
|
+
local phase_number=1
|
|
107
|
+
local i=0
|
|
108
|
+
|
|
109
|
+
while true; do
|
|
110
|
+
local phase_zones="[]"
|
|
111
|
+
local zones_in_phase=0
|
|
112
|
+
|
|
113
|
+
while [[ $zones_in_phase -lt $max_zones_per_phase ]]; do
|
|
114
|
+
local zone_data
|
|
115
|
+
zone_data=$(echo "$ranked_zones" | jq ".[$i] // empty")
|
|
116
|
+
|
|
117
|
+
if [[ "$zone_data" == "null" || "$zone_data" == "" ]]; then
|
|
118
|
+
break 2
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
phase_zones=$(echo "$phase_zones" | jq ". + [$zone_data]")
|
|
122
|
+
((i++))
|
|
123
|
+
((zones_in_phase++))
|
|
124
|
+
done
|
|
125
|
+
|
|
126
|
+
if [[ $zones_in_phase -eq 0 ]]; then
|
|
127
|
+
break
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
local phase_entry="{
|
|
131
|
+
\"phase\": $phase_number,
|
|
132
|
+
\"zones\": $phase_zones,
|
|
133
|
+
\"max_execution_time\": $DEFAULT_PHASE_TIMEOUT,
|
|
134
|
+
\"success_threshold\": $SUCCESS_THRESHOLD,
|
|
135
|
+
\"rollback_timeout\": $DEFAULT_ROLLBACK_TIMEOUT
|
|
136
|
+
}"
|
|
137
|
+
|
|
138
|
+
rollout_phases=$(echo "$rollout_phases" | jq ". + [$phase_entry]")
|
|
139
|
+
((phase_number++))
|
|
140
|
+
done
|
|
141
|
+
|
|
142
|
+
echo "$rollout_phases"
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
create_success_criteria() {
|
|
146
|
+
local rollout_phases="$1"
|
|
147
|
+
|
|
148
|
+
local success_criteria="[]"
|
|
149
|
+
|
|
150
|
+
local phase_count
|
|
151
|
+
phase_count=$(echo "$rollout_phases" | jq 'length')
|
|
152
|
+
|
|
153
|
+
for ((i=0; i<phase_count; i++)); do
|
|
154
|
+
local phase_data
|
|
155
|
+
phase_data=$(echo "$rollout_phases" | jq ".[$i]")
|
|
156
|
+
|
|
157
|
+
local zone_names
|
|
158
|
+
zone_names=$(echo "$phase_data" | jq -r '.zones[].name')
|
|
159
|
+
|
|
160
|
+
local phase_criteria="{
|
|
161
|
+
\"phase\": $((i + 1)),
|
|
162
|
+
\"required_success_zones\": [],
|
|
163
|
+
\"minimum_confidence_threshold\": $SUCCESS_THRESHOLD,
|
|
164
|
+
\"all_zones_must_complete\": true,
|
|
165
|
+
\"validation_checks\": [
|
|
166
|
+
\"redis_namespace_isolation\",
|
|
167
|
+
\"agent_completion_signaling\",
|
|
168
|
+
\"coordinator_lifecycle_management\",
|
|
169
|
+
\"deliverable_verification\"
|
|
170
|
+
]
|
|
171
|
+
}"
|
|
172
|
+
|
|
173
|
+
# Add required zone names
|
|
174
|
+
local zones_array="[]"
|
|
175
|
+
while IFS= read -r zone_name; do
|
|
176
|
+
zones_array=$(echo "$zones_array" | jq ". + [\"$zone_name\"]")
|
|
177
|
+
done <<< "$zone_names"
|
|
178
|
+
|
|
179
|
+
phase_criteria=$(echo "$phase_criteria" | jq ".required_success_zones = $zones_array")
|
|
180
|
+
success_criteria=$(echo "$success_criteria" | jq ". + [$phase_criteria]")
|
|
181
|
+
done
|
|
182
|
+
|
|
183
|
+
echo "$success_criteria"
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
create_rollback_triggers() {
|
|
187
|
+
local rollout_phases="$1"
|
|
188
|
+
|
|
189
|
+
local rollback_triggers="[]"
|
|
190
|
+
|
|
191
|
+
local phase_count
|
|
192
|
+
phase_count=$(echo "$rollout_phases" | jq 'length')
|
|
193
|
+
|
|
194
|
+
# Global rollback triggers
|
|
195
|
+
local global_triggers="[
|
|
196
|
+
{
|
|
197
|
+
\"trigger\": \"any_zone_critical_failure\",
|
|
198
|
+
\"action\": \"immediate_rollback_all\",
|
|
199
|
+
\"description\": \"Critical system failure in any zone\"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
\"trigger\": \"redis_namespace_corruption\",
|
|
203
|
+
\"action\": \"emergency_stop_and_cleanup\",
|
|
204
|
+
\"description\": \"Redis namespace isolation breach\"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
\"trigger\": \"resource_exhaustion\",
|
|
208
|
+
\"action\": \"scale_back_and_retry\",
|
|
209
|
+
\"description\": \"System resources exhausted\"
|
|
210
|
+
}
|
|
211
|
+
]"
|
|
212
|
+
|
|
213
|
+
# Phase-specific rollback triggers
|
|
214
|
+
local i=0
|
|
215
|
+
for ((i=0; i<phase_count; i++)); do
|
|
216
|
+
local phase_zones
|
|
217
|
+
phase_zones=$(echo "$rollout_phases" | jq -r ".[$i].zones[].name")
|
|
218
|
+
|
|
219
|
+
while IFS= read -r zone_name; do
|
|
220
|
+
local trigger="{
|
|
221
|
+
\"trigger\": \"zone_${zone_name}_completion_failure\",
|
|
222
|
+
\"phase\": $((i + 1)),
|
|
223
|
+
\"action\": \"rollback_current_phase\",
|
|
224
|
+
\"description\": \"Zone $zone_name failed to complete in phase $((i + 1))\"
|
|
225
|
+
}"
|
|
226
|
+
|
|
227
|
+
rollback_triggers=$(echo "$rollback_triggers" | jq ". + [$trigger]")
|
|
228
|
+
done <<< "$phase_zones"
|
|
229
|
+
done
|
|
230
|
+
|
|
231
|
+
# Combine global and specific triggers
|
|
232
|
+
echo "$global_triggers" | jq ". + $rollback_triggers"
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
generate_rollout_plan() {
|
|
236
|
+
local zone_config="$1"
|
|
237
|
+
local max_zones_per_phase="${2:-2}"
|
|
238
|
+
|
|
239
|
+
info "Analyzing zone complexity for rollout planning"
|
|
240
|
+
|
|
241
|
+
# Rank zones by complexity
|
|
242
|
+
local ranked_zones
|
|
243
|
+
ranked_zones=$(rank_zones_by_complexity "$zone_config")
|
|
244
|
+
|
|
245
|
+
# Create rollout phases
|
|
246
|
+
local rollout_phases
|
|
247
|
+
rollout_phases=$(create_rollout_phases "$ranked_zones" "$max_zones_per_phase")
|
|
248
|
+
|
|
249
|
+
# Create success criteria
|
|
250
|
+
local success_criteria
|
|
251
|
+
success_criteria=$(create_success_criteria "$rollout_phases")
|
|
252
|
+
|
|
253
|
+
# Create rollback triggers
|
|
254
|
+
local rollback_triggers
|
|
255
|
+
rollback_triggers=$(create_rollback_triggers "$rollout_phases")
|
|
256
|
+
|
|
257
|
+
# Generate complete rollout plan
|
|
258
|
+
local rollout_plan="{
|
|
259
|
+
\"timestamp\": $(date '+%s'),
|
|
260
|
+
\"total_zones\": $(echo "$zone_config" | jq '.zones | length'),
|
|
261
|
+
\"max_zones_per_phase\": $max_zones_per_phase,
|
|
262
|
+
\"phases\": $rollout_phases,
|
|
263
|
+
\"success_criteria\": $success_criteria,
|
|
264
|
+
\"rollback_triggers\": $rollback_triggers,
|
|
265
|
+
\"execution_strategy\": {
|
|
266
|
+
\"type\": \"graduated_rollout\",
|
|
267
|
+
\"monitoring_level\": \"enhanced\",
|
|
268
|
+
\"auto_rollback_enabled\": true,
|
|
269
|
+
\"manual_approval_required\": false
|
|
270
|
+
}
|
|
271
|
+
}"
|
|
272
|
+
|
|
273
|
+
echo "$rollout_plan"
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
display_rollout_summary() {
|
|
277
|
+
local rollout_plan="$1"
|
|
278
|
+
|
|
279
|
+
echo
|
|
280
|
+
info "=== Risk-Based Rollout Plan ==="
|
|
281
|
+
echo "Total zones: $(echo "$rollout_plan" | jq -r '.total_zones')"
|
|
282
|
+
echo "Maximum zones per phase: $(echo "$rollout_plan" | jq -r '.max_zones_per_phase')"
|
|
283
|
+
echo
|
|
284
|
+
|
|
285
|
+
local phase_count
|
|
286
|
+
phase_count=$(echo "$rollout_plan" | jq '.phases | length')
|
|
287
|
+
|
|
288
|
+
echo "Rollout Phases:"
|
|
289
|
+
for ((i=0; i<phase_count; i++)); do
|
|
290
|
+
local phase_data
|
|
291
|
+
phase_data=$(echo "$rollout_plan" | jq ".phases[$i]")
|
|
292
|
+
local phase_number=$((i + 1))
|
|
293
|
+
local zone_count
|
|
294
|
+
zone_count=$(echo "$phase_data" | jq '.zones | length')
|
|
295
|
+
local zone_names
|
|
296
|
+
zone_names=$(echo "$phase_data" | jq -r '.zones[].name' | tr '\n' ', ' | sed 's/,$//')
|
|
297
|
+
|
|
298
|
+
echo " Phase $phase_number: $zone_names ($zone_count zones)"
|
|
299
|
+
done
|
|
300
|
+
echo
|
|
301
|
+
|
|
302
|
+
echo "Success Criteria:"
|
|
303
|
+
echo " - Minimum confidence threshold: $(echo "$rollout_plan" | jq -r '.success_criteria[0].minimum_confidence_threshold')"
|
|
304
|
+
echo " - All zones must complete: $(echo "$rollout_plan" | jq -r '.success_criteria[0].all_zones_must_complete')"
|
|
305
|
+
echo " - Validation checks: $(echo "$rollout_plan" | jq -r '.success_criteria[0].validation_checks | length') checks"
|
|
306
|
+
echo
|
|
307
|
+
|
|
308
|
+
echo "Rollback Triggers:"
|
|
309
|
+
echo " - Global triggers: 3"
|
|
310
|
+
echo " - Phase-specific triggers: $(echo "$rollout_plan" | jq '.rollback_triggers | length - 3')"
|
|
311
|
+
echo
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
main() {
|
|
315
|
+
local config_file="$1"
|
|
316
|
+
local max_zones_per_phase="${2:-2}"
|
|
317
|
+
|
|
318
|
+
if [[ -z "$config_file" ]]; then
|
|
319
|
+
error "Usage: $0 <zone-config-file> [max-zones-per-phase]"
|
|
320
|
+
fi
|
|
321
|
+
|
|
322
|
+
if [[ ! -f "$config_file" ]]; then
|
|
323
|
+
error "Configuration file not found: $config_file"
|
|
324
|
+
fi
|
|
325
|
+
|
|
326
|
+
log "Starting risk-based rollout planning for: $config_file"
|
|
327
|
+
|
|
328
|
+
# Read configuration
|
|
329
|
+
local zone_config
|
|
330
|
+
if ! zone_config=$(jq . "$config_file" 2>/dev/null); then
|
|
331
|
+
error "Invalid JSON in configuration file: $config_file"
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
# Generate rollout plan
|
|
335
|
+
local rollout_plan
|
|
336
|
+
rollout_plan=$(generate_rollout_plan "$zone_config" "$max_zones_per_phase")
|
|
337
|
+
|
|
338
|
+
# Save rollout plan
|
|
339
|
+
local output_file="/tmp/rollout-plan-$(date '+%s').json"
|
|
340
|
+
echo "$rollout_plan" > "$output_file"
|
|
341
|
+
|
|
342
|
+
log "✅ Risk-based rollout planning completed"
|
|
343
|
+
log "Rollout plan saved to: $output_file"
|
|
344
|
+
|
|
345
|
+
# Display summary
|
|
346
|
+
display_rollout_summary "$rollout_plan"
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
# Execute main function with all arguments
|
|
350
350
|
main "$@"
|