claude-flow-novice 2.14.27 → 2.14.29

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 (73) hide show
  1. package/.claude/commands/CFN_LOOP_TASK_MODE.md +119 -0
  2. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +22 -0
  3. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh.backup +273 -0
  4. package/.claude/skills/cfn-hybrid-routing/README.md +1 -1
  5. package/.claude/skills/cfn-loop-orchestration/helpers/consensus.sh +10 -0
  6. package/.claude/skills/cfn-loop-orchestration/helpers/spawn-agents.sh +10 -0
  7. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +105 -15
  8. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup +76 -11
  9. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup2 +959 -0
  10. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.clean +949 -0
  11. package/.claude/skills/cfn-product-owner-decision/execute-decision.sh +82 -10
  12. package/.claude/skills/cfn-redis-coordination/report-completion.sh +10 -0
  13. package/claude-assets/agents/cfn-dev-team/architecture/base-template-generator.md +7 -33
  14. package/claude-assets/agents/cfn-dev-team/architecture/planner.md +7 -47
  15. package/claude-assets/agents/cfn-dev-team/architecture/system-architect.md +7 -33
  16. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +88 -23
  17. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +59 -23
  18. package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +43 -39
  19. package/claude-assets/agents/cfn-dev-team/coordinators/epic-creator.md +69 -0
  20. package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +65 -1
  21. package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +7 -47
  22. package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +7 -26
  23. package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +7 -47
  24. package/claude-assets/agents/cfn-dev-team/product-owners/cto-agent.md +7 -19
  25. package/claude-assets/agents/cfn-dev-team/product-owners/power-user-persona.md +9 -49
  26. package/claude-assets/agents/cfn-dev-team/product-owners/product-owner.md +407 -22
  27. package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +7 -66
  28. package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +7 -76
  29. package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +8 -2
  30. package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +7 -66
  31. package/claude-assets/agents/cfn-dev-team/reviewers/reviewer.md +7 -78
  32. package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +7 -18
  33. package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +7 -18
  34. package/claude-assets/agents/cfn-dev-team/testers/tester.md +7 -77
  35. package/claude-assets/agents/cfn-dev-team/testers/unit/tdd-london-unit-swarm.md +7 -18
  36. package/claude-assets/agents/cfn-dev-team/testers/validation/validation-production-validator.md +7 -19
  37. package/claude-assets/agents/cfn-dev-team/testing/test-validation-agent.md +7 -44
  38. package/claude-assets/agents/cfn-dev-team/utility/agent-builder.md +35 -111
  39. package/claude-assets/agents/cfn-dev-team/utility/analyst.md +7 -47
  40. package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +7 -40
  41. package/claude-assets/agents/cfn-dev-team/utility/context-curator.md +7 -47
  42. package/claude-assets/commands/CFN_LOOP_TASK_MODE.md +119 -0
  43. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +22 -0
  44. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh.backup +273 -0
  45. package/claude-assets/skills/cfn-environment-sanitization/SKILL.md +200 -0
  46. package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +244 -0
  47. package/claude-assets/skills/cfn-hybrid-routing/README.md +1 -1
  48. package/claude-assets/skills/cfn-loop-orchestration/helpers/consensus.sh +10 -0
  49. package/claude-assets/skills/cfn-loop-orchestration/helpers/spawn-agents.sh +10 -0
  50. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +105 -15
  51. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.backup +76 -11
  52. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.backup2 +959 -0
  53. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.clean +949 -0
  54. package/claude-assets/skills/cfn-node-heap-sizer/task-mode-heap-limiter.sh +326 -0
  55. package/claude-assets/skills/cfn-process-instrumentation/SKILL.md +279 -0
  56. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +323 -0
  57. package/claude-assets/skills/cfn-product-owner-decision/execute-decision.sh +82 -10
  58. package/claude-assets/skills/cfn-redis-coordination/report-completion.sh +10 -0
  59. package/claude-assets/skills/cfn-task-audit/get-audit-data.sh +376 -0
  60. package/claude-assets/skills/cfn-task-audit/store-task-audit.sh +184 -0
  61. package/claude-assets/skills/cfn-task-mode-safety/cli-coordination.sh +519 -0
  62. package/claude-assets/skills/cfn-task-mode-safety/mode-detection.sh +326 -0
  63. package/claude-assets/skills/cfn-task-mode-sanitize/task-mode-env-sanitizer.sh +224 -0
  64. package/claude-assets/skills/cfn-telemetry/collect-metrics.sh +249 -0
  65. package/claude-assets/skills/cfn-telemetry/start-telemetry.sh +111 -0
  66. package/claude-assets/skills/cfn-validation-runner-instrumentation/wrapped-executor.sh +327 -0
  67. package/dist/agents/agent-loader.js +467 -133
  68. package/dist/agents/agent-loader.js.map +1 -1
  69. package/dist/cli/config-manager.js.map +1 -1
  70. package/package.json +1 -1
  71. package/scripts/mode-detection.sh +321 -0
  72. package/scripts/spawn-worker.sh +8 -0
  73. package/scripts/track-zai-costs-simple.sh +8 -0
@@ -0,0 +1,959 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ##############################################################################
4
+ # CFN Loop Orchestration - Main Coordinator
5
+ # Version: 1.1.0 (Security Enhanced)
6
+ #
7
+ # Orchestrates the Complete Fail Never (CFN) Loop workflow using modular
8
+ # helper scripts, Redis Coordination primitives, and enhanced security.
9
+ #
10
+ # Usage:
11
+ # ./orchestrate.sh --task-id <id> \
12
+ # --mode <mvp|standard|enterprise> \
13
+ # --loop3-agents <agent1,agent2,...> \
14
+ # --loop2-agents <agent1,agent2,...> \
15
+ # --product-owner <agent-id> \
16
+ # [--max-iterations <n>] \
17
+ # [--epic-context <json>] \
18
+ # [--phase-context <json>] \
19
+ # [--success-criteria <json>]
20
+ ##############################################################################
21
+
22
+ set -euo pipefail
23
+
24
+ # ⚠️ ANTI-023 MEMORY LEAK PROTECTION: Block Task Mode agents
25
+ # Task Mode agents spawn via Task() tool and should NOT use orchestration scripts
26
+ if [[ -z "${TASK_ID:-}" || -z "${LOOP3_AGENTS:-}" ]]; then
27
+ echo "❌ TASK MODE DETECTED - Orchestration forbidden" >&2
28
+ echo "🚨 ANTI-023: This script is for CLI-spawned coordinators only" >&2
29
+ echo "💡 Task Mode coordination should be handled directly by Main Chat" >&2
30
+ echo "🔧 Coordinator spawned via Task() tool - Main Chat should coordinate directly" >&2
31
+ exit 1
32
+ fi
33
+
34
+ # Load security utilities
35
+
36
+ # ⚠️ ANTI-023 MEMORY LEAK PROTECTION: Environment Sanitization
37
+ # Load and apply environment sanitization to prevent memory leaks
38
+ # shellcheck source=../cfn-environment-sanitization/sanitize-environment.sh
39
+ if [[ -f "$PROJECT_ROOT/.claude/skills/cfn-environment-sanitization/sanitize-environment.sh" ]]; then
40
+ source "$PROJECT_ROOT/.claude/skills/cfn-environment-sanitization/sanitize-environment.sh" --strict
41
+ echo "✅ Environment sanitization applied" >&2
42
+ else
43
+ echo "⚠️ Environment sanitization not available - proceeding without protection" >&2
44
+ fi
45
+ # shellcheck source=./security_utils.sh
46
+ source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/security_utils.sh"
47
+
48
+ # Determine script directory
49
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
50
+ HELPERS_DIR="$SCRIPT_DIR/helpers"
51
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" && REDIS_COORD_SKILL="$PROJECT_ROOT/.claude/skills/cfn-redis-coordination"
52
+
53
+ # Configuration
54
+ TASK_ID=""
55
+ MODE="standard"
56
+ LOOP3_AGENTS=""
57
+ LOOP2_AGENTS=""
58
+ PRODUCT_OWNER=""
59
+ MAX_ITERATIONS=10
60
+ MIN_QUORUM_LOOP3="0.66"
61
+ MIN_QUORUM_LOOP2="0.66"
62
+ EPIC_CONTEXT=""
63
+ PHASE_CONTEXT=""
64
+ SUCCESS_CRITERIA=""
65
+ EXPECTED_FILES=""
66
+ PHASE_ID=""
67
+
68
+ # Mode-specific thresholds
69
+ declare -A GATE_THRESHOLD=(
70
+ [mvp]=0.70
71
+ [standard]=0.75
72
+ [enterprise]=0.75
73
+ )
74
+
75
+ declare -A CONSENSUS_THRESHOLD=(
76
+ [mvp]=0.80
77
+ [standard]=0.90
78
+ [enterprise]=0.95
79
+ )
80
+
81
+ # Execution tracking
82
+ START_TIME=$(date +%s)
83
+ ITERATIONS_COMPLETED=0
84
+ FINAL_DECISION=""
85
+ LOOP3_FINAL_CONFIDENCE=0.0
86
+ LOOP2_FINAL_CONSENSUS=0.0
87
+ DELIVERABLES_VERIFIED=false
88
+
89
+ ##############################################################################
90
+ # Argument Parsing
91
+ ##############################################################################
92
+ while [[ $# -gt 0 ]]; do
93
+ case $1 in
94
+ --task-id)
95
+ if [[ $# -lt 2 ]]; then
96
+ echo "Error: --task-id requires a value"
97
+ exit 1
98
+ fi
99
+ TASK_ID=$(sanitize_input "$2") || { echo "Invalid task ID"; exit 1; }
100
+ shift 2
101
+ ;;
102
+ --mode)
103
+ if [[ $# -lt 2 ]]; then
104
+ echo "Error: --mode requires a value"
105
+ exit 1
106
+ fi
107
+ MODE="$2"
108
+ # Whitelist allowed modes
109
+ if [[ ! "$MODE" =~ ^(mvp|standard|enterprise)$ ]]; then
110
+ echo "Invalid mode. Must be mvp, standard, or enterprise."
111
+ exit 1
112
+ fi
113
+ shift 2
114
+ ;;
115
+ --loop3-agents)
116
+ if [[ $# -lt 2 ]]; then
117
+ echo "Error: --loop3-agents requires a value"
118
+ exit 1
119
+ fi
120
+ validate_agent_list "$2" || { echo "Invalid Loop 3 agent list"; exit 1; }
121
+ LOOP3_AGENTS="$2"
122
+ shift 2
123
+ ;;
124
+ --loop2-agents)
125
+ if [[ $# -lt 2 ]]; then
126
+ echo "Error: --loop2-agents requires a value"
127
+ exit 1
128
+ fi
129
+ validate_agent_list "$2" || { echo "Invalid Loop 2 agent list"; exit 1; }
130
+ LOOP2_AGENTS="$2"
131
+ shift 2
132
+ ;;
133
+ --product-owner)
134
+ if [[ $# -lt 2 ]]; then
135
+ echo "Error: --product-owner requires a value"
136
+ exit 1
137
+ fi
138
+ PRODUCT_OWNER=$(sanitize_input "$2") || { echo "Invalid product owner"; exit 1; }
139
+ shift 2
140
+ ;;
141
+ --max-iterations)
142
+ if [[ $# -lt 2 ]]; then
143
+ echo "Error: --max-iterations requires a value"
144
+ exit 1
145
+ fi
146
+ # Validate max iterations is a positive integer
147
+ if [[ ! "$2" =~ ^[1-9][0-9]*$ ]]; then
148
+ echo "Max iterations must be a positive integer"
149
+ exit 1
150
+ fi
151
+ MAX_ITERATIONS="$2"
152
+ shift 2
153
+ ;;
154
+ --min-quorum-loop3)
155
+ if [[ $# -lt 2 ]]; then
156
+ echo "Error: --min-quorum-loop3 requires a value"
157
+ exit 1
158
+ fi
159
+ # Validate quorum is a valid decimal between 0 and 1
160
+ if [[ ! "$2" =~ ^0\.[0-9]+$ ]] || (( $(echo "$2 > 1" | bc -l) )); then
161
+ echo "Invalid Loop 3 quorum. Must be between 0 and 1."
162
+ exit 1
163
+ fi
164
+ MIN_QUORUM_LOOP3="$2"
165
+ shift 2
166
+ ;;
167
+ --min-quorum-loop2)
168
+ if [[ $# -lt 2 ]]; then
169
+ echo "Error: --min-quorum-loop2 requires a value"
170
+ exit 1
171
+ fi
172
+ # Validate quorum is a valid decimal between 0 and 1
173
+ if [[ ! "$2" =~ ^0\.[0-9]+$ ]] || (( $(echo "$2 > 1" | bc -l) )); then
174
+ echo "Invalid Loop 2 quorum. Must be between 0 and 1."
175
+ exit 1
176
+ fi
177
+ MIN_QUORUM_LOOP2="$2"
178
+ shift 2
179
+ ;;
180
+ --epic-context)
181
+ if [[ $# -lt 2 ]]; then
182
+ echo "Error: --epic-context requires a value"
183
+ exit 1
184
+ fi
185
+ validate_json_context "$2" || { echo "Invalid epic context JSON"; exit 1; }
186
+ EPIC_CONTEXT="$2"
187
+ shift 2
188
+ ;;
189
+ --phase-context)
190
+ if [[ $# -lt 2 ]]; then
191
+ echo "Error: --phase-context requires a value"
192
+ exit 1
193
+ fi
194
+ validate_json_context "$2" || { echo "Invalid phase context JSON"; exit 1; }
195
+ PHASE_CONTEXT="$2"
196
+ shift 2
197
+ ;;
198
+ --success-criteria)
199
+ if [[ $# -lt 2 ]]; then
200
+ echo "Error: --success-criteria requires a value"
201
+ exit 1
202
+ fi
203
+ validate_json_context "$2" || { echo "Invalid success criteria JSON"; exit 1; }
204
+ SUCCESS_CRITERIA="$2"
205
+ shift 2
206
+ ;;
207
+ --expected-files)
208
+ if [[ $# -lt 2 ]]; then
209
+ echo "Error: --expected-files requires a value"
210
+ exit 1
211
+ fi
212
+ # Optional: validate each expected file name if not empty
213
+ if [ -n "$2" ]; then
214
+ IFS=',' read -ra FILES <<< "$2"
215
+ for file in "${FILES[@]}"; do
216
+ sanitize_input "$file" 256 || { echo "Invalid expected filename: $file"; exit 1; }
217
+ done
218
+ fi
219
+ EXPECTED_FILES="$2"
220
+ shift 2
221
+ ;;
222
+ --phase-id)
223
+ if [[ $# -lt 2 ]]; then
224
+ echo "Error: --phase-id requires a value"
225
+ exit 1
226
+ fi
227
+ PHASE_ID=$(sanitize_input "$2") || { echo "Invalid phase ID"; exit 1; }
228
+ shift 2
229
+ ;;
230
+ *)
231
+ echo "Error: Unknown option: '$1'"
232
+ echo ""
233
+ echo "Usage: $0 [OPTIONS]"
234
+ echo ""
235
+ echo "Required options:"
236
+ echo " --task-id <id> Unique task identifier"
237
+ echo " --loop3-agents <agents> Comma-separated list of Loop 3 agents"
238
+ echo " --loop2-agents <agents> Comma-separated list of Loop 2 agents"
239
+ echo " --product-owner <agent> Product owner agent ID"
240
+ echo ""
241
+ echo "Optional options:"
242
+ echo " --mode <mode> CFN mode: mvp, standard, enterprise (default: standard)"
243
+ echo " --max-iterations <n> Maximum iterations (default: 10)"
244
+ echo " --min-quorum-loop3 <n> Loop 3 quorum threshold (default: 0.66)"
245
+ echo " --min-quorum-loop2 <n> Loop 2 quorum threshold (default: 0.66)"
246
+ echo " --epic-context <json> Epic context JSON"
247
+ echo " --phase-context <json> Phase context JSON"
248
+ echo " --success-criteria <json> Success criteria JSON"
249
+ echo " --expected-files <files> Comma-separated expected deliverables"
250
+ echo " --phase-id <id> Phase identifier for timeout calculation"
251
+ exit 1
252
+ ;;
253
+ esac
254
+ done
255
+
256
+ # Validation
257
+ if [ -z "$TASK_ID" ] || [ -z "$LOOP3_AGENTS" ] || [ -z "$LOOP2_AGENTS" ] || [ -z "$PRODUCT_OWNER" ]; then
258
+ echo "Error: Required parameters missing"
259
+ echo "Usage: $0 --task-id <id> --mode <mode> --loop3-agents <agents> --loop2-agents <agents> --product-owner <agent>"
260
+ exit 1
261
+ fi
262
+
263
+ # Get thresholds for mode
264
+ # Add additional mode validation with safe fallback
265
+ case "$MODE" in
266
+ mvp)
267
+ GATE=${GATE_THRESHOLD[mvp]:-0.70}
268
+ CONSENSUS=${CONSENSUS_THRESHOLD[mvp]:-0.80}
269
+ ;;
270
+ standard)
271
+ GATE=${GATE_THRESHOLD[standard]:-0.75}
272
+ CONSENSUS=${CONSENSUS_THRESHOLD[standard]:-0.90}
273
+ ;;
274
+ enterprise)
275
+ GATE=${GATE_THRESHOLD[enterprise]:-0.85}
276
+ CONSENSUS=${CONSENSUS_THRESHOLD[enterprise]:-0.95}
277
+ ;;
278
+ *)
279
+ echo "Invalid mode: $MODE"
280
+ exit 1
281
+ ;;
282
+ esac
283
+
284
+ # Calculate timeout
285
+ TIMEOUT=$("$HELPERS_DIR/timeout-calculator.sh" --phase-id "${PHASE_ID:-unknown}")
286
+
287
+ echo "=============================================="
288
+ echo "CFN Loop Orchestration v1.0.0"
289
+ echo "=============================================="
290
+ echo "Task ID: $TASK_ID"
291
+ echo "Mode: $MODE"
292
+ echo "Gate Threshold: $GATE"
293
+ echo "Consensus Threshold: $CONSENSUS"
294
+ echo "Max Iterations: $MAX_ITERATIONS"
295
+ echo "Timeout: ${TIMEOUT}s"
296
+ echo "=============================================="
297
+ echo ""
298
+
299
+ ##############################################################################
300
+ # Helper Functions
301
+ ##############################################################################
302
+
303
+ function store_context() {
304
+ local task_id="$1"
305
+
306
+ # Store epic context if provided using Redis coordination primitive
307
+ if [ -n "$EPIC_CONTEXT" ]; then
308
+ "$REDIS_COORD_SKILL/store-context.sh" \
309
+ --task-id "$task_id" \
310
+ --key "epic-context" \
311
+ --value "$EPIC_CONTEXT" \
312
+ --namespace "swarm" >/dev/null
313
+ echo "Stored epic context"
314
+ fi
315
+
316
+ # Store phase context if provided using Redis coordination primitive
317
+ if [ -n "$PHASE_CONTEXT" ]; then
318
+ "$REDIS_COORD_SKILL/store-context.sh" \
319
+ --task-id "$task_id" \
320
+ --key "phase-context" \
321
+ --value "$PHASE_CONTEXT" \
322
+ --namespace "swarm" >/dev/null
323
+ echo "Stored phase context"
324
+ fi
325
+
326
+ # Store success criteria if provided using Redis coordination primitive
327
+ if [ -n "$SUCCESS_CRITERIA" ]; then
328
+ "$REDIS_COORD_SKILL/store-context.sh" \
329
+ --task-id "$task_id" \
330
+ --key "success-criteria" \
331
+ --value "$SUCCESS_CRITERIA" \
332
+ --namespace "swarm" >/dev/null
333
+ echo "Stored success criteria"
334
+ fi
335
+
336
+ echo ""
337
+ }
338
+
339
+ build_agent_context() {
340
+ local task_id="$1"
341
+ local iteration="$2"
342
+ local agent_type="$3"
343
+ local feedback="$4"
344
+ local loop_type="${5:-}" # NEW: loop3, loop2, or loop4 (optional)
345
+
346
+ # Initialize context variables
347
+ local task_desc="CFN Loop implementation"
348
+ local deliverables=""
349
+ local acceptance=""
350
+ local epic_context=""
351
+ local phase_context=""
352
+ local target_files=""
353
+
354
+ # Try to retrieve complete context from Redis
355
+ if command -v "$REDIS_COORD_SKILL/get-context.sh" >/dev/null 2>&1; then
356
+ if redis_context=$("$REDIS_COORD_SKILL/get-context.sh" --task-id "$task_id" --namespace "swarm" 2>/dev/null); then
357
+ echo "📥 Retrieved Redis context for task: $task_id" >&2
358
+
359
+ # Extract fields from Redis context
360
+ task_desc=$(echo "$redis_context" | jq -r '.["epic-context"] // .epic_context // "CFN Loop implementation"' 2>/dev/null || echo "CFN Loop implementation")
361
+ deliverables=$(echo "$redis_context" | jq -r '.deliverables // [] | if type == "array" then join(", ") else . end' 2>/dev/null || echo "")
362
+ acceptance=$(echo "$redis_context" | jq -r '.acceptanceCriteria // .["acceptance-criteria"] // [] | if type == "array" then join(", ") else . end' 2>/dev/null || echo "")
363
+ epic_context=$(echo "$redis_context" | jq -r '.["epic-context"] // ""' 2>/dev/null || echo "")
364
+ phase_context=$(echo "$redis_context" | jq -r '.["phase-context"] // ""' 2>/dev/null || echo "")
365
+ target_files=$(echo "$redis_context" | jq -r '.["target-files"] // ""' 2>/dev/null || echo "")
366
+
367
+ echo "📋 Redis context extracted - Task: $task_desc" >&2
368
+ else
369
+ echo "⚠️ Failed to retrieve Redis context, using local SUCCESS_CRITERIA" >&2
370
+ fi
371
+ else
372
+ echo "⚠️ get-context.sh not found, using local SUCCESS_CRITERIA" >&2
373
+ fi
374
+
375
+ # Fallback to local SUCCESS_CRITERIA if Redis retrieval failed or incomplete
376
+ if [ -z "$deliverables" ] && [ -n "$SUCCESS_CRITERIA" ]; then
377
+ deliverables=$(echo "$SUCCESS_CRITERIA" | jq -r '.deliverables // [] | join(", ")' 2>/dev/null || echo "")
378
+ acceptance=$(echo "$SUCCESS_CRITERIA" | jq -r '.acceptanceCriteria // [] | join(", ")' 2>/dev/null || echo "")
379
+ echo "🔄 Using local SUCCESS_CRITERIA as fallback" >&2
380
+ fi
381
+
382
+ # Build comprehensive context string
383
+ local context="Task: $task_desc"
384
+
385
+ if [ -n "$deliverables" ]; then
386
+ context="$context | Deliverables: $deliverables"
387
+ fi
388
+
389
+ if [ -n "$acceptance" ]; then
390
+ context="$context | Acceptance Criteria: $acceptance"
391
+ fi
392
+
393
+ if [ -n "$target_files" ]; then
394
+ context="$context | Target Files: $target_files"
395
+ fi
396
+
397
+ context="$context | Iteration: $iteration"
398
+
399
+ if [[ -n "$feedback" ]]; then
400
+ context="$context | Feedback: $feedback"
401
+ fi
402
+
403
+ # Add epic/phase context if available
404
+ if [ -n "$epic_context" ]; then
405
+ context="$context | Epic: $epic_context"
406
+ fi
407
+
408
+ if [ -n "$phase_context" ]; then
409
+ context="$context | Phase: $phase_context"
410
+ fi
411
+
412
+ # Inject CFN Loop context if injection script exists and loop_type provided
413
+ if [[ -n "$loop_type" ]] && [[ -x "$SCRIPT_DIR/inject-loop-context.sh" ]]; then
414
+ context=$("$SCRIPT_DIR/inject-loop-context.sh" "$loop_type" "$context" 2>/dev/null || echo "$context")
415
+ fi
416
+
417
+ echo "$context"
418
+ }
419
+
420
+ function spawn_loop3_agents() {
421
+ local task_id="$1"
422
+ local iteration="$2"
423
+ local agents="$3"
424
+
425
+ echo "[Loop 3] Spawning implementer agents (iteration $iteration)..."
426
+
427
+ # Convert comma-separated agents to array
428
+ IFS=',' read -ra AGENT_ARRAY <<< "$agents"
429
+
430
+ # Track agent instance counts for unique ID generation
431
+ declare -A AGENT_INSTANCE_COUNTS
432
+
433
+ # Spawn each agent via CLI
434
+ for agent_type in "${AGENT_ARRAY[@]}"; do
435
+ # Generate unique agent ID (agent-type-iteration-instance)
436
+ AGENT_INSTANCE_COUNTS["$agent_type"]=$((${AGENT_INSTANCE_COUNTS["$agent_type"]:-0} + 1))
437
+ INSTANCE_NUM="${AGENT_INSTANCE_COUNTS["$agent_type"]}"
438
+ UNIQUE_AGENT_ID="${agent_type}-${iteration}-${INSTANCE_NUM}"
439
+
440
+ echo " Spawning: $agent_type (ID: $UNIQUE_AGENT_ID)"
441
+
442
+ # Validate agent input
443
+ local safe_agent_type safe_task_id safe_agent_id
444
+ safe_agent_type=$(sanitize_input "$agent_type") || continue
445
+ safe_task_id=$(sanitize_input "$task_id") || continue
446
+ safe_agent_id=$(sanitize_input "$UNIQUE_AGENT_ID") || continue
447
+
448
+ # Spawn agent in background with explicit agent ID
449
+ npx claude-flow-novice agent "$safe_agent_type" \
450
+ --task-id "$safe_task_id" \
451
+ --agent-id "$safe_agent_id" \
452
+ --iteration "$iteration" \
453
+ --context "$(build_agent_context "$safe_task_id" "$iteration" "$safe_agent_type" "" "loop3")" &
454
+
455
+ # Store PID for monitoring using unique agent ID
456
+ AGENT_PID=$!
457
+ "$REDIS_COORD_SKILL/store-context.sh" \
458
+ --task-id "$task_id" \
459
+ --key "${UNIQUE_AGENT_ID}:pid" \
460
+ --value "{\"pid\": $AGENT_PID}" \
461
+ --namespace "swarm" >/dev/null
462
+
463
+ # Store agent ID mapping for later retrieval using Redis SADD for set storage
464
+ redis-cli SADD "swarm:${task_id}:loop3:agent_ids:iteration${iteration}" "$UNIQUE_AGENT_ID" >/dev/null
465
+ done
466
+
467
+ echo "[Loop 3] All agents spawned"
468
+ echo ""
469
+ }
470
+
471
+ function wait_for_agents() {
472
+ local task_id="$1"
473
+ local agents="$2"
474
+ local timeout="$3"
475
+ local iteration="${4:-1}"
476
+
477
+ echo "Waiting for agents to complete (timeout: ${timeout}s)..."
478
+
479
+ # Retrieve actual agent IDs from Redis (stored during spawn using SADD)
480
+ local stored_ids
481
+ stored_ids=$(redis-cli SMEMBERS "swarm:${task_id}:loop3:agent_ids:iteration${iteration}" 2>/dev/null | tr '\n' ',' | sed 's/,$//')
482
+
483
+ # If stored IDs exist, use them; otherwise fallback to generating from agent types
484
+ local -a AGENT_IDS
485
+ if [ -n "$stored_ids" ]; then
486
+ IFS=',' read -ra AGENT_IDS <<< "$stored_ids"
487
+ echo " Retrieved ${#AGENT_IDS[@]} agent IDs from Redis"
488
+ else
489
+ # Fallback: Convert agent types to IDs (legacy compatibility)
490
+ echo " Warning: No stored agent IDs, using agent types as fallback"
491
+ IFS=',' read -ra AGENT_TYPES <<< "$agents"
492
+
493
+ # Track instance counts to match spawn behavior
494
+ declare -A AGENT_INSTANCE_COUNTS
495
+ for agent_type in "${AGENT_TYPES[@]}"; do
496
+ AGENT_INSTANCE_COUNTS["$agent_type"]=$((${AGENT_INSTANCE_COUNTS["$agent_type"]:-0} + 1))
497
+ INSTANCE_NUM="${AGENT_INSTANCE_COUNTS["$agent_type"]}"
498
+ AGENT_IDS+=("${agent_type}-${iteration}-${INSTANCE_NUM}")
499
+ done
500
+ fi
501
+
502
+ # Parallel BLPOP implementation with shared timeout
503
+ # Track start time for global timeout calculation
504
+ local start_time=$(date +%s)
505
+
506
+ # Spawn parallel BLPOP processes for each agent
507
+ local pids=()
508
+ local temp_files=()
509
+
510
+ for unique_agent_id in "${AGENT_IDS[@]}"; do
511
+ # Create temporary file for this agent's result
512
+ local temp_file="/tmp/cfn-wait-${task_id}-${unique_agent_id}-$$.tmp"
513
+ temp_files+=("$temp_file")
514
+
515
+ echo " Waiting for: $unique_agent_id"
516
+
517
+ # Spawn BLPOP in background, write result to temp file
518
+ (
519
+ local result
520
+ if redis-cli blpop "swarm:${task_id}:${unique_agent_id}:done" "$timeout" >/dev/null 2>&1; then
521
+ echo "success" > "$temp_file"
522
+ else
523
+ echo "timeout" > "$temp_file"
524
+ fi
525
+ exit 0
526
+ ) &
527
+
528
+ pids+=($!)
529
+ done
530
+
531
+ # Wait for all parallel BLPOP processes to complete
532
+ # This ensures timeout is global (60s total), not per-agent (60s * N)
533
+ for pid in "${pids[@]}"; do
534
+ wait "$pid" 2>/dev/null || true
535
+ done
536
+
537
+ # Calculate actual elapsed time
538
+ local end_time=$(date +%s)
539
+ local elapsed=$((end_time - start_time))
540
+
541
+ # Check results and report status
542
+ local completed=0
543
+ local timed_out=0
544
+
545
+ for i in "${!AGENT_IDS[@]}"; do
546
+ local unique_agent_id="${AGENT_IDS[$i]}"
547
+ local temp_file="${temp_files[$i]}"
548
+
549
+ if [ -f "$temp_file" ]; then
550
+ local result=$(cat "$temp_file")
551
+ if [ "$result" = "success" ]; then
552
+ ((completed++))
553
+ echo " ✅ $unique_agent_id completed"
554
+ else
555
+ ((timed_out++))
556
+ echo " ⚠️ $unique_agent_id did not complete within timeout"
557
+ fi
558
+ rm -f "$temp_file"
559
+ else
560
+ ((timed_out++))
561
+ echo " ❌ $unique_agent_id result file missing"
562
+ fi
563
+ done
564
+
565
+ echo "Agents completed: $completed/${#AGENT_IDS[@]} (elapsed: ${elapsed}s)"
566
+ echo ""
567
+ }
568
+
569
+ function wait_for_loop2_agents() {
570
+ local task_id="$1"
571
+ local agents="$2"
572
+ local timeout="$3"
573
+ local iteration="${4:-1}"
574
+
575
+ echo "Waiting for Loop 2 validators to complete (timeout: ${timeout}s)..."
576
+
577
+ # Retrieve actual agent IDs from Redis (stored during spawn using SADD)
578
+ local stored_ids
579
+ stored_ids=$(redis-cli SMEMBERS "swarm:${task_id}:loop2:agent_ids:iteration${iteration}" 2>/dev/null | tr '\n' ',' | sed 's/,$//')
580
+
581
+ # If stored IDs exist, use them; otherwise fallback to generating from agent types
582
+ local -a VALIDATOR_IDS
583
+ if [ -n "$stored_ids" ]; then
584
+ IFS=',' read -ra VALIDATOR_IDS <<< "$stored_ids"
585
+ echo " Retrieved ${#VALIDATOR_IDS[@]} validator IDs from Redis"
586
+ else
587
+ # Fallback: Convert agent types to IDs (legacy compatibility)
588
+ echo " Warning: No stored validator IDs, using agent types as fallback"
589
+ IFS=',' read -ra AGENT_TYPES <<< "$agents"
590
+
591
+ # Track instance counts to match spawn behavior
592
+ declare -A AGENT_INSTANCE_COUNTS
593
+ for agent_type in "${AGENT_TYPES[@]}"; do
594
+ AGENT_INSTANCE_COUNTS["$agent_type"]=$((${AGENT_INSTANCE_COUNTS["$agent_type"]:-0} + 1))
595
+ INSTANCE_NUM="${AGENT_INSTANCE_COUNTS["$agent_type"]}"
596
+ VALIDATOR_IDS+=("${agent_type}-${iteration}-${INSTANCE_NUM}")
597
+ done
598
+ fi
599
+
600
+ # Parallel BLPOP implementation
601
+ local start_time=$(date +%s)
602
+ local pids=()
603
+ local temp_files=()
604
+
605
+ for unique_validator_id in "${VALIDATOR_IDS[@]}"; do
606
+ local temp_file="/tmp/cfn-wait-${task_id}-${unique_validator_id}-$$.tmp"
607
+ temp_files+=("$temp_file")
608
+
609
+ echo " Waiting for: $unique_validator_id"
610
+
611
+ # Spawn BLPOP in background
612
+ (
613
+ if redis-cli blpop "swarm:${task_id}:${unique_validator_id}:done" "$timeout" >/dev/null 2>&1; then
614
+ echo "success" > "$temp_file"
615
+ else
616
+ echo "timeout" > "$temp_file"
617
+ fi
618
+ exit 0
619
+ ) &
620
+
621
+ pids+=($!)
622
+ done
623
+
624
+ # Wait for all processes
625
+ for pid in "${pids[@]}"; do
626
+ wait "$pid" 2>/dev/null || true
627
+ done
628
+
629
+ # Check results
630
+ local end_time=$(date +%s)
631
+ local elapsed=$((end_time - start_time))
632
+ local completed=0
633
+ local timed_out=0
634
+
635
+ for i in "${!VALIDATOR_IDS[@]}"; do
636
+ local unique_validator_id="${VALIDATOR_IDS[$i]}"
637
+ local temp_file="${temp_files[$i]}"
638
+
639
+ if [ -f "$temp_file" ]; then
640
+ local result=$(cat "$temp_file")
641
+ if [ "$result" = "success" ]; then
642
+ ((completed++))
643
+ echo " ✅ $unique_validator_id completed"
644
+ else
645
+ ((timed_out++))
646
+ echo " ⚠️ $unique_validator_id did not complete within timeout"
647
+ fi
648
+ rm -f "$temp_file"
649
+ else
650
+ ((timed_out++))
651
+ echo " ❌ $unique_validator_id result file missing"
652
+ fi
653
+ done
654
+
655
+ echo "Validators completed: $completed/${#VALIDATOR_IDS[@]} (elapsed: ${elapsed}s)"
656
+ echo ""
657
+ }
658
+
659
+ function spawn_loop2_agents() {
660
+ local task_id="$1"
661
+ local iteration="$2"
662
+ local agents="$3"
663
+
664
+ echo "[Loop 2] Spawning validator agents (iteration $iteration)..."
665
+
666
+ # Convert comma-separated agents to array
667
+ IFS=',' read -ra AGENT_ARRAY <<< "$agents"
668
+
669
+ # Track agent instance counts for unique ID generation
670
+ declare -A AGENT_INSTANCE_COUNTS
671
+
672
+ # Spawn each agent via CLI
673
+ for agent_type in "${AGENT_ARRAY[@]}"; do
674
+ # Generate unique agent ID (agent-type-iteration-instance)
675
+ AGENT_INSTANCE_COUNTS["$agent_type"]=$((${AGENT_INSTANCE_COUNTS["$agent_type"]:-0} + 1))
676
+ INSTANCE_NUM="${AGENT_INSTANCE_COUNTS["$agent_type"]}"
677
+ UNIQUE_VALIDATOR_ID="${agent_type}-${iteration}-${INSTANCE_NUM}"
678
+
679
+ echo " Spawning: $agent_type (ID: $UNIQUE_VALIDATOR_ID)"
680
+
681
+ # Spawn agent in background with explicit agent ID
682
+ npx claude-flow-novice agent "$agent_type" \
683
+ --task-id "$task_id" \
684
+ --agent-id "$UNIQUE_VALIDATOR_ID" \
685
+ --iteration "$iteration" \
686
+ --context "$(build_agent_context "$task_id" "$iteration" "$agent_type" "" "loop2")" &
687
+
688
+ # Store PID for monitoring using unique agent ID
689
+ AGENT_PID=$!
690
+ "$REDIS_COORD_SKILL/store-context.sh" \
691
+ --task-id "$task_id" \
692
+ --key "${UNIQUE_VALIDATOR_ID}:pid" \
693
+ --value "{\"pid\": $AGENT_PID}" \
694
+ --namespace "swarm" >/dev/null
695
+
696
+ # Store agent ID mapping for later retrieval using Redis SADD for set storage
697
+ redis-cli SADD "swarm:${task_id}:loop2:agent_ids:iteration${iteration}" "$UNIQUE_VALIDATOR_ID" >/dev/null
698
+ done
699
+
700
+ echo "[Loop 2] All agents spawned"
701
+ echo ""
702
+ }
703
+
704
+ function spawn_product_owner() {
705
+ local task_id="$1"
706
+ local iteration="$2"
707
+
708
+ echo "[Product Owner] Spawning decision agent..."
709
+
710
+ # BLOCKER #2 FIX: Match execute-decision.sh actual parameters
711
+ # Required: --task-id, --agent-id, --consensus, --threshold, --iteration, --max-iterations
712
+ local decision_output
713
+ decision_output=$("$SCRIPT_DIR/.claude/skills/cfn-product-owner-decision/execute-decision.sh" \
714
+ --task-id "$task_id" \
715
+ --agent-id "$PRODUCT_OWNER" \
716
+ --consensus "$LOOP2_FINAL_CONSENSUS" \
717
+ --threshold "$CONSENSUS" \
718
+ --iteration "$iteration" \
719
+ --max-iterations "$MAX_ITERATIONS")
720
+
721
+ # Parse decision from output
722
+ if echo "$decision_output" | grep -q "PROCEED"; then
723
+ FINAL_DECISION="PROCEED"
724
+ elif echo "$decision_output" | grep -q "ITERATE"; then
725
+ FINAL_DECISION="ITERATE"
726
+ elif echo "$decision_output" | grep -q "ABORT"; then
727
+ FINAL_DECISION="ABORT"
728
+ else
729
+ echo "Warning: Could not parse Product Owner decision, defaulting to ITERATE"
730
+ FINAL_DECISION="ITERATE"
731
+ fi
732
+
733
+ echo "[Product Owner] Decision: $FINAL_DECISION"
734
+ echo ""
735
+ }
736
+
737
+ function output_result() {
738
+ local status="$1"
739
+ local end_time=$(date +%s)
740
+ local execution_time=$((end_time - START_TIME))
741
+
742
+ echo "=============================================="
743
+ echo "CFN Loop Execution Complete"
744
+ echo "=============================================="
745
+ echo "Status: $status"
746
+ echo "Iterations: $ITERATIONS_COMPLETED"
747
+ echo "Final Decision: $FINAL_DECISION"
748
+ echo "Loop 3 Confidence: $LOOP3_FINAL_CONFIDENCE"
749
+ echo "Loop 2 Consensus: $LOOP2_FINAL_CONSENSUS"
750
+ echo "Deliverables Verified: $DELIVERABLES_VERIFIED"
751
+ echo "Execution Time: ${execution_time}s"
752
+ echo "=============================================="
753
+
754
+ # Output structured JSON result
755
+ cat <<EOF
756
+ {
757
+ "status": "$status",
758
+ "iterations_completed": $ITERATIONS_COMPLETED,
759
+ "final_decision": "$FINAL_DECISION",
760
+ "loop3_confidence": $LOOP3_FINAL_CONFIDENCE,
761
+ "loop2_consensus": $LOOP2_FINAL_CONSENSUS,
762
+ "deliverables_verified": $DELIVERABLES_VERIFIED,
763
+ "execution_time_seconds": $execution_time
764
+ }
765
+ EOF
766
+ }
767
+
768
+ ##############################################################################
769
+ # Main CFN Loop
770
+ ##############################################################################
771
+
772
+ # Store context in Redis
773
+ store_context "$TASK_ID"
774
+
775
+ # Iteration loop
776
+ for ((ITERATION=1; ITERATION<=MAX_ITERATIONS; ITERATION++)); do
777
+ echo ""
778
+ echo "=========================================="
779
+ echo "Iteration $ITERATION / $MAX_ITERATIONS"
780
+ echo "=========================================="
781
+ echo ""
782
+
783
+ ITERATIONS_COMPLETED=$ITERATION
784
+
785
+ # Step 1: Spawn Loop 3 agents (implementers)
786
+ spawn_loop3_agents "$TASK_ID" "$ITERATION" "$LOOP3_AGENTS"
787
+
788
+ # Step 2: Wait for Loop 3 completion
789
+ wait_for_agents "$TASK_ID" "$LOOP3_AGENTS" "$TIMEOUT" "$ITERATION"
790
+
791
+ # Step 3: Verify deliverables (prevent "consensus on vapor")
792
+ if [ -n "$EXPECTED_FILES" ] || [ -n "$EPIC_CONTEXT" ]; then
793
+ # Extract task type from epic context for keyword detection
794
+ TASK_TYPE=""
795
+ if [ -n "$EPIC_CONTEXT" ]; then
796
+ TASK_TYPE=$(echo "$EPIC_CONTEXT" | jq -r '.epicGoal // ""' 2>/dev/null || echo "")
797
+ fi
798
+
799
+ if "$HELPERS_DIR/deliverable-verifier.sh" \
800
+ --expected-files "${EXPECTED_FILES:-}" \
801
+ --task-type "${TASK_TYPE:-}"; then
802
+ DELIVERABLES_VERIFIED=true
803
+ else
804
+ echo "❌ Deliverable verification failed - forcing Loop 3 iteration"
805
+ # Use iteration manager to wake Loop 3 agents with explicit feedback
806
+ "$HELPERS_DIR/iteration-manager.sh" \
807
+ --task-id "$TASK_ID" \
808
+ --iteration "$((ITERATION + 1))" \
809
+ --agents "$LOOP3_AGENTS" \
810
+ --feedback-source "swarm:${TASK_ID}:feedback"
811
+ continue
812
+ fi
813
+ fi
814
+
815
+ # Step 4: Gate check (Loop 3 self-validation)
816
+ # Retrieve actual Loop 3 agent IDs for validation
817
+ LOOP3_IDS=$(redis-cli SMEMBERS "swarm:${TASK_ID}:loop3:agent_ids:iteration${ITERATION}" 2>/dev/null | tr '\n' ',' | sed 's/,$//')
818
+
819
+ if [ -z "$LOOP3_IDS" ]; then
820
+ echo "⚠️ WARNING: No Loop 3 agent IDs found in Redis, using agent types as fallback"
821
+ LOOP3_IDS="$LOOP3_AGENTS"
822
+ fi
823
+
824
+ if "$HELPERS_DIR/gate-check.sh" \
825
+ --task-id "$TASK_ID" \
826
+ --agents "$LOOP3_IDS" \
827
+ --threshold "$GATE" \
828
+ --min-quorum "$MIN_QUORUM_LOOP3"; then
829
+ # Gate passed - store confidence
830
+ LOOP3_FINAL_CONFIDENCE=$("$REDIS_COORD_SKILL/invoke-waiting-mode.sh" collect \
831
+ --task-id "$TASK_ID" \
832
+ --agent-ids "$LOOP3_IDS" \
833
+ --min-quorum "$MIN_QUORUM_LOOP3")
834
+ else
835
+ # Gate failed - iterate Loop 3
836
+ echo "❌ Gate check failed - iterating Loop 3"
837
+ "$HELPERS_DIR/iteration-manager.sh" \
838
+ --task-id "$TASK_ID" \
839
+ --iteration "$((ITERATION + 1))" \
840
+ --agents "$LOOP3_AGENTS" \
841
+ --feedback-source "swarm:${TASK_ID}:feedback"
842
+ continue
843
+ fi
844
+
845
+ # Step 5: Spawn Loop 2 agents (validators)
846
+ spawn_loop2_agents "$TASK_ID" "$ITERATION" "$LOOP2_AGENTS"
847
+
848
+ # Step 6: Wait for Loop 2 completion
849
+ wait_for_loop2_agents "$TASK_ID" "$LOOP2_AGENTS" "$TIMEOUT" "$ITERATION"
850
+
851
+ # Step 7: Consensus check (Loop 2 validation)
852
+ # Retrieve actual Loop 2 agent IDs for validation
853
+ LOOP2_IDS=$(redis-cli SMEMBERS "swarm:${TASK_ID}:loop2:agent_ids:iteration${ITERATION}" 2>/dev/null | tr '\n' ',' | sed 's/,$//')
854
+
855
+ if [ -z "$LOOP2_IDS" ]; then
856
+ echo "⚠️ WARNING: No Loop 2 agent IDs found in Redis, using agent types as fallback"
857
+ LOOP2_IDS="$LOOP2_AGENTS"
858
+ fi
859
+
860
+ if "$HELPERS_DIR/consensus.sh" \
861
+ --task-id "$TASK_ID" \
862
+ --agents "$LOOP2_IDS" \
863
+ --threshold "$CONSENSUS" \
864
+ --min-quorum "$MIN_QUORUM_LOOP2"; then
865
+ # Consensus reached - store score
866
+ LOOP2_FINAL_CONSENSUS=$("$REDIS_COORD_SKILL/invoke-waiting-mode.sh" collect \
867
+ --task-id "$TASK_ID" \
868
+ --agent-ids "$LOOP2_IDS" \
869
+ --min-quorum "$MIN_QUORUM_LOOP2")
870
+ else
871
+ # Consensus failed - iterate all agents
872
+ echo "❌ Consensus check failed - iterating all agents"
873
+ "$HELPERS_DIR/iteration-manager.sh" \
874
+ --task-id "$TASK_ID" \
875
+ --iteration "$((ITERATION + 1))" \
876
+ --agents "$LOOP3_AGENTS,$LOOP2_AGENTS" \
877
+ --feedback-source "swarm:${TASK_ID}:feedback"
878
+ continue
879
+ fi
880
+
881
+ # Step 8: Product Owner Decision
882
+ spawn_product_owner "$TASK_ID" "$ITERATION"
883
+
884
+ # Step 9: Execute decision
885
+ case "$FINAL_DECISION" in
886
+ PROCEED)
887
+ # Launch ACE reflection in background (Loop 5)
888
+ echo "[Loop 5] Launching reflection in background..."
889
+
890
+ # Ensure log directory exists
891
+ mkdir -p "$PROJECT_ROOT/.artifacts/logs"
892
+
893
+ # Build reflection context from CFN Loop execution
894
+ REFLECTION_CONTEXT=$(cat <<EOF
895
+ {
896
+ "task_id": "$TASK_ID",
897
+ "task_type": "cfn_loop",
898
+ "mode": "$MODE",
899
+ "iterations_completed": $ITERATIONS_COMPLETED,
900
+ "loop3_agents": "$LOOP3_AGENTS",
901
+ "loop2_agents": "$LOOP2_AGENTS",
902
+ "loop3_confidence": $LOOP3_FINAL_CONFIDENCE,
903
+ "loop2_consensus": $LOOP2_FINAL_CONSENSUS,
904
+ "gate_threshold": $GATE,
905
+ "consensus_threshold": $CONSENSUS,
906
+ "deliverables_verified": $DELIVERABLES_VERIFIED,
907
+ "epic_context": $EPIC_CONTEXT,
908
+ "phase_context": $PHASE_CONTEXT,
909
+ "success_criteria": $SUCCESS_CRITERIA
910
+ }
911
+ EOF
912
+ )
913
+
914
+ # Launch reflection in background (non-blocking)
915
+ (
916
+ "$PROJECT_ROOT/.claude/skills/cfn-ace-system/invoke-context-reflect.sh" \
917
+ --context "$REFLECTION_CONTEXT" \
918
+ --output "/tmp/reflection-${TASK_ID}.json" 2>&1 | \
919
+ tee -a "$PROJECT_ROOT/.artifacts/logs/ace-reflection-${TASK_ID}.log"
920
+
921
+ # Log completion
922
+ echo "[$(date -Iseconds)] Reflection complete for task $TASK_ID" >> \
923
+ "$PROJECT_ROOT/.artifacts/logs/ace-reflection-${TASK_ID}.log"
924
+ ) &
925
+
926
+ REFLECTION_PID=$!
927
+ echo "[Loop 5] Reflection launched (PID: $REFLECTION_PID)"
928
+ echo ""
929
+
930
+ # Continue with output (don't wait for reflection)
931
+ output_result "success"
932
+ exit 0
933
+ ;;
934
+ ABORT)
935
+ output_result "aborted"
936
+ exit 1
937
+ ;;
938
+ ITERATE)
939
+ if [ $ITERATION -ge $MAX_ITERATIONS ]; then
940
+ echo "❌ Max iterations reached"
941
+ output_result "failed"
942
+ exit 1
943
+ fi
944
+
945
+ echo "🔄 Product Owner requested iteration"
946
+ "$HELPERS_DIR/iteration-manager.sh" \
947
+ --task-id "$TASK_ID" \
948
+ --iteration "$((ITERATION + 1))" \
949
+ --agents "$LOOP3_AGENTS,$LOOP2_AGENTS" \
950
+ --feedback-source "swarm:${TASK_ID}:feedback"
951
+ continue
952
+ ;;
953
+ esac
954
+ done
955
+
956
+ # Max iterations reached without success
957
+ echo "❌ Max iterations ($MAX_ITERATIONS) reached without PROCEED decision"
958
+ output_result "failed"
959
+ exit 1