claude-flow-novice 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/CLAUDE.md +740 -978
- package/.claude/agents/core-agents/cost-savings-cfn-loop-coordinator.md +47 -2
- package/.claude/agents/custom/agent-builder.md +637 -0
- package/.claude/api-configs/config-current-zai-config.env +62 -0
- package/.claude/api-configs/config-test-zai-config.env +62 -0
- package/.claude/api-configs/env-backups/before-anthropic-20251020-025404.env +62 -0
- package/.claude/api-configs/env-backups/before-restore-20251020-025431.env +62 -0
- package/.claude/artifacts/reflection-merge-logs/cli-agent-spawning-v2.5.2-merge-report.md +61 -0
- package/.claude/commands/cfn-loop-epic.md +41 -17
- package/.claude/commands/cfn-loop.md +43 -30
- package/.claude/commands/custom-routing-activate.md +37 -123
- package/.claude/commands/custom-routing-deactivate.md +27 -124
- package/.claude/commands/switch-api.md +41 -16
- package/.claude/skills/agent-execution/execute-agent.sh +126 -0
- package/.claude/skills/redis-coordination/AGENT_LOGGING.md +280 -0
- package/.claude/skills/redis-coordination/agent-log.sh +124 -0
- package/.claude/skills/redis-coordination/init-swarm.sh +6 -1
- package/.claude/skills/redis-coordination/invoke-waiting-mode.sh +62 -5
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh +68 -8
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-1760949407 +933 -0
- package/.claude/skills/redis-coordination/store-epic-context.sh +123 -0
- package/.claude/skills/redis-coordination/test-iteration-feedback.sh +320 -0
- package/.claude/skills/skill-builder/SKILL.md +910 -0
- package/CLAUDE.md +76 -2
- package/dist/cli/agent-command.js +151 -0
- package/dist/cli/agent-command.js.map +1 -0
- package/dist/cli/agent-definition-parser.js +176 -0
- package/dist/cli/agent-definition-parser.js.map +1 -0
- package/dist/cli/agent-executor.js +176 -0
- package/dist/cli/agent-executor.js.map +1 -0
- package/dist/cli/agent-prompt-builder.js +188 -0
- package/dist/cli/agent-prompt-builder.js.map +1 -0
- package/dist/cli/agent-spawn.js +46 -1
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/anthropic-client.js +242 -0
- package/dist/cli/anthropic-client.js.map +1 -0
- package/dist/cli/cli-agent-context.js +353 -0
- package/dist/cli/cli-agent-context.js.map +1 -0
- package/dist/cli/cli-agent-context.test.js +451 -0
- package/dist/cli/cli-agent-context.test.js.map +1 -0
- package/dist/cli/index.js +115 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/iteration-history.js +188 -0
- package/dist/cli/iteration-history.js.map +1 -0
- package/package.json +3 -1
- package/scripts/switch-api.sh +233 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# Agent Logging System
|
|
2
|
+
|
|
3
|
+
Dual-output logging for CLI-spawned agents: terminal + Redis + portal visibility.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
✅ **Terminal output** - Colored logs for debugging in tmux/terminal
|
|
8
|
+
✅ **File logging** - Persisted to `/tmp/agent-*.log`
|
|
9
|
+
✅ **Redis pub/sub** - Real-time streaming to web portal
|
|
10
|
+
✅ **Redis history** - Last 7 days stored in sorted sets
|
|
11
|
+
✅ **Portal filters** - Filter by repository, agent, or log level
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Source in Agent Scripts
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
#!/usr/bin/env bash
|
|
19
|
+
source .claude/skills/redis-coordination/agent-log.sh
|
|
20
|
+
|
|
21
|
+
# Set context
|
|
22
|
+
export AGENT_ID="backend-dev-1"
|
|
23
|
+
export TASK_ID="$1" # Pass from command line
|
|
24
|
+
|
|
25
|
+
# Log throughout execution
|
|
26
|
+
agent_log "info" "Starting task execution"
|
|
27
|
+
agent_log "debug" "Loading configuration from $CONFIG_FILE"
|
|
28
|
+
agent_log "warn" "High memory usage detected: ${MEMORY}MB"
|
|
29
|
+
agent_log "error" "Connection failed: $ERROR_MSG"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Standalone Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Direct command-line usage
|
|
36
|
+
./.claude/skills/redis-coordination/agent-log.sh info "Agent initialized" \
|
|
37
|
+
--agent-id researcher-1 \
|
|
38
|
+
--task-id task-auth-123
|
|
39
|
+
|
|
40
|
+
# From any script
|
|
41
|
+
./.claude/skills/redis-coordination/agent-log.sh error "Validation failed" \
|
|
42
|
+
--agent-id reviewer-2 \
|
|
43
|
+
--task-id task-auth-123
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. Log Levels
|
|
47
|
+
|
|
48
|
+
- **debug** - Detailed debugging information (cyan)
|
|
49
|
+
- **info** - General informational messages (green)
|
|
50
|
+
- **warn** - Warning messages (yellow)
|
|
51
|
+
- **error** - Error conditions (red)
|
|
52
|
+
|
|
53
|
+
## Output Destinations
|
|
54
|
+
|
|
55
|
+
**1. Terminal (with colors)**
|
|
56
|
+
```
|
|
57
|
+
[INFO] [backend-dev-1] Starting authentication implementation
|
|
58
|
+
[WARN] [backend-dev-1] Database connection slow
|
|
59
|
+
[ERROR] [reviewer-1] JWT validation failed
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**2. File (`/tmp/agent-<id>.log`)**
|
|
63
|
+
```
|
|
64
|
+
[2025-10-20T07:02:48Z] [INFO] [backend-dev-1] Starting authentication implementation
|
|
65
|
+
[2025-10-20T07:02:48Z] [WARN] [backend-dev-1] Database connection slow
|
|
66
|
+
[2025-10-20T07:02:48Z] [ERROR] [reviewer-1] JWT validation failed
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**3. Redis (`swarm:<task-id>:logs`)**
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"level": "info",
|
|
73
|
+
"message": "Starting authentication implementation",
|
|
74
|
+
"agentId": "backend-dev-1",
|
|
75
|
+
"taskId": "task-auth-123",
|
|
76
|
+
"repository": "claude-flow-novice",
|
|
77
|
+
"timestamp": "2025-10-20T07:02:48Z"
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**4. Web Portal (http://localhost:3456 → Logs tab)**
|
|
82
|
+
- Real-time streaming via WebSocket
|
|
83
|
+
- Filter by repository, agent, or level
|
|
84
|
+
- Shows last 1000 logs (100 displayed)
|
|
85
|
+
- Auto-refreshes on new logs
|
|
86
|
+
|
|
87
|
+
## Integration Points
|
|
88
|
+
|
|
89
|
+
### Option 1: Source in Main Agent Script
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# In your main agent script
|
|
93
|
+
source .claude/skills/redis-coordination/agent-log.sh
|
|
94
|
+
|
|
95
|
+
# Set global context once
|
|
96
|
+
export AGENT_ID="${AGENT_TYPE}-${AGENT_NUM}"
|
|
97
|
+
export TASK_ID="$TASK_ID"
|
|
98
|
+
|
|
99
|
+
# Then log freely
|
|
100
|
+
agent_log "info" "Agent spawned successfully"
|
|
101
|
+
# ... agent work ...
|
|
102
|
+
agent_log "info" "Task completed with confidence 0.95"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Option 2: Wrap Agent Spawning
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# In orchestrate-cfn-loop.sh or spawn-agent.sh
|
|
109
|
+
./.claude/skills/redis-coordination/agent-log.sh info \
|
|
110
|
+
"Spawning agent: $AGENT_ID for task: $TASK_ID" \
|
|
111
|
+
--agent-id "$AGENT_ID" \
|
|
112
|
+
--task-id "$TASK_ID"
|
|
113
|
+
|
|
114
|
+
# Spawn agent
|
|
115
|
+
npx claude-flow-novice agent "$AGENT_TYPE" --task-id "$TASK_ID"
|
|
116
|
+
|
|
117
|
+
# Log completion
|
|
118
|
+
./.claude/skills/redis-coordination/agent-log.sh info \
|
|
119
|
+
"Agent $AGENT_ID completed" \
|
|
120
|
+
--agent-id "$AGENT_ID" \
|
|
121
|
+
--task-id "$TASK_ID"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Option 3: Add to Existing Agent Logic
|
|
125
|
+
|
|
126
|
+
If you have existing CLI agent code, wrap key operations:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Before long operation
|
|
130
|
+
agent_log "info" "Starting database migration"
|
|
131
|
+
|
|
132
|
+
# During operation
|
|
133
|
+
if [ "$ROWS_UPDATED" -gt 10000 ]; then
|
|
134
|
+
agent_log "warn" "Large migration in progress: $ROWS_UPDATED rows"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# On error
|
|
138
|
+
if ! run_migration; then
|
|
139
|
+
agent_log "error" "Migration failed: $ERROR"
|
|
140
|
+
exit 1
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# On success
|
|
144
|
+
agent_log "info" "Migration completed: $ROWS_UPDATED rows updated"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Advanced Options
|
|
148
|
+
|
|
149
|
+
### Skip Terminal Output (Quiet Mode)
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
agent_log "info" "Background task started" --no-terminal
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Skip Redis Output (Local Only)
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
agent_log "debug" "Local debug info" --no-redis
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Manual Context Override
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
agent_log "error" "Connection timeout" \
|
|
165
|
+
--agent-id "custom-agent" \
|
|
166
|
+
--task-id "override-task-id"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Portal Usage
|
|
170
|
+
|
|
171
|
+
1. **Open portal:** http://localhost:3456
|
|
172
|
+
2. **Go to Logs tab** (📝 Logs)
|
|
173
|
+
3. **Filter logs:**
|
|
174
|
+
- Repository: Select specific repo or "All Repositories"
|
|
175
|
+
- Agent: Select specific agent or "All Agents"
|
|
176
|
+
- Level: debug/info/warn/error or "All Levels"
|
|
177
|
+
4. **Clear logs:** Click "Clear Logs" button
|
|
178
|
+
|
|
179
|
+
**Stats shown:**
|
|
180
|
+
- Total logs in memory
|
|
181
|
+
- Number of repositories logging
|
|
182
|
+
- Number of active agents
|
|
183
|
+
|
|
184
|
+
## Redis Keys
|
|
185
|
+
|
|
186
|
+
**Pub/Sub Channel:**
|
|
187
|
+
```
|
|
188
|
+
swarm:<task-id>:logs
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Sorted Set (History):**
|
|
192
|
+
```
|
|
193
|
+
swarm:<task-id>:logs:history
|
|
194
|
+
```
|
|
195
|
+
- Score: Unix timestamp
|
|
196
|
+
- Value: JSON log entry
|
|
197
|
+
- TTL: 7 days (604800 seconds)
|
|
198
|
+
|
|
199
|
+
## Examples
|
|
200
|
+
|
|
201
|
+
### Example 1: CFN Loop Agent
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
#!/usr/bin/env bash
|
|
205
|
+
source .claude/skills/redis-coordination/agent-log.sh
|
|
206
|
+
|
|
207
|
+
AGENT_ID="coder-3"
|
|
208
|
+
TASK_ID="$1"
|
|
209
|
+
|
|
210
|
+
agent_log "info" "Starting Loop 3 implementation phase"
|
|
211
|
+
|
|
212
|
+
# Implement feature
|
|
213
|
+
agent_log "debug" "Reading specification from spec.md"
|
|
214
|
+
agent_log "info" "Implementing authentication service"
|
|
215
|
+
|
|
216
|
+
if ! run_tests; then
|
|
217
|
+
agent_log "error" "Tests failed - iteration needed"
|
|
218
|
+
exit 1
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
agent_log "info" "Implementation complete - confidence: 0.88"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Example 2: Orchestrator Logging
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# In orchestrate-cfn-loop.sh
|
|
228
|
+
agent_log "info" "CFN Loop started - mode: $MODE" \
|
|
229
|
+
--agent-id "orchestrator" \
|
|
230
|
+
--task-id "$TASK_ID"
|
|
231
|
+
|
|
232
|
+
agent_log "info" "Spawning Loop 3 agents: $LOOP3_AGENTS" \
|
|
233
|
+
--agent-id "orchestrator" \
|
|
234
|
+
--task-id "$TASK_ID"
|
|
235
|
+
|
|
236
|
+
# ... spawn agents ...
|
|
237
|
+
|
|
238
|
+
agent_log "info" "Loop 3 consensus: $CONSENSUS (gate: $GATE_THRESHOLD)" \
|
|
239
|
+
--agent-id "orchestrator" \
|
|
240
|
+
--task-id "$TASK_ID"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Troubleshooting
|
|
244
|
+
|
|
245
|
+
**Logs not appearing in portal:**
|
|
246
|
+
1. Check Redis connection: `redis-cli ping`
|
|
247
|
+
2. Check portal subscription: Look for "✅ Subscribed to swarm:*:logs" in portal startup
|
|
248
|
+
3. Verify task ID matches swarm task ID
|
|
249
|
+
4. Check Redis pub/sub: `redis-cli psubscribe "swarm:*:logs"`
|
|
250
|
+
|
|
251
|
+
**Colors not showing in terminal:**
|
|
252
|
+
- WSL/Linux should show colors automatically
|
|
253
|
+
- tmux: Colors should work by default
|
|
254
|
+
- If colors missing, terminal may not support ANSI codes
|
|
255
|
+
|
|
256
|
+
**Log file not created:**
|
|
257
|
+
- Check permissions on `/tmp/`
|
|
258
|
+
- Verify `AGENT_ID` is set (file named `/tmp/agent-${AGENT_ID}.log`)
|
|
259
|
+
|
|
260
|
+
## Performance
|
|
261
|
+
|
|
262
|
+
- **Minimal overhead:** ~5ms per log entry
|
|
263
|
+
- **Non-blocking:** Redis operations use `> /dev/null 2>&1 || true`
|
|
264
|
+
- **Memory efficient:** Portal keeps max 1000 logs, shows 100
|
|
265
|
+
- **Auto-cleanup:** Redis history expires after 7 days
|
|
266
|
+
|
|
267
|
+
## Migration from Old Logging
|
|
268
|
+
|
|
269
|
+
**Before:**
|
|
270
|
+
```bash
|
|
271
|
+
echo "[INFO] Agent started"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**After:**
|
|
275
|
+
```bash
|
|
276
|
+
source .claude/skills/redis-coordination/agent-log.sh
|
|
277
|
+
agent_log "info" "Agent started"
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Benefits: Same terminal output + Redis pub/sub + portal visibility + file logging
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Agent Logging Utility - Dual output (terminal + Redis)
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# source agent-log.sh
|
|
7
|
+
# agent_log "info" "Message here"
|
|
8
|
+
# agent_log "error" "Error occurred"
|
|
9
|
+
#
|
|
10
|
+
# Or as standalone:
|
|
11
|
+
# ./agent-log.sh "info" "Agent started" --agent-id "researcher-1" --task-id "task-123"
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
# Color codes for terminal output
|
|
16
|
+
COLOR_RESET="\033[0m"
|
|
17
|
+
COLOR_DEBUG="\033[0;36m" # Cyan
|
|
18
|
+
COLOR_INFO="\033[0;32m" # Green
|
|
19
|
+
COLOR_WARN="\033[0;33m" # Yellow
|
|
20
|
+
COLOR_ERROR="\033[0;31m" # Red
|
|
21
|
+
COLOR_AGENT="\033[0;35m" # Magenta
|
|
22
|
+
|
|
23
|
+
# Get color for log level
|
|
24
|
+
get_log_color() {
|
|
25
|
+
local level="$1"
|
|
26
|
+
case "$level" in
|
|
27
|
+
debug) echo "$COLOR_DEBUG" ;;
|
|
28
|
+
info) echo "$COLOR_INFO" ;;
|
|
29
|
+
warn) echo "$COLOR_WARN" ;;
|
|
30
|
+
error) echo "$COLOR_ERROR" ;;
|
|
31
|
+
*) echo "$COLOR_RESET" ;;
|
|
32
|
+
esac
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Main logging function
|
|
36
|
+
# Usage: agent_log <level> <message> [--agent-id <id>] [--task-id <id>] [--no-terminal] [--no-redis]
|
|
37
|
+
agent_log() {
|
|
38
|
+
local LEVEL="${1:-info}"
|
|
39
|
+
local MESSAGE="${2:-}"
|
|
40
|
+
local AGENT_ID="${AGENT_ID:-unknown}"
|
|
41
|
+
local TASK_ID="${TASK_ID:-unknown}"
|
|
42
|
+
local REPOSITORY=$(basename "$(pwd)")
|
|
43
|
+
local NO_TERMINAL=false
|
|
44
|
+
local NO_REDIS=false
|
|
45
|
+
|
|
46
|
+
# Parse optional arguments
|
|
47
|
+
shift 2 || true
|
|
48
|
+
while [[ $# -gt 0 ]]; do
|
|
49
|
+
case "$1" in
|
|
50
|
+
--agent-id)
|
|
51
|
+
AGENT_ID="$2"
|
|
52
|
+
shift 2
|
|
53
|
+
;;
|
|
54
|
+
--task-id)
|
|
55
|
+
TASK_ID="$2"
|
|
56
|
+
shift 2
|
|
57
|
+
;;
|
|
58
|
+
--no-terminal)
|
|
59
|
+
NO_TERMINAL=true
|
|
60
|
+
shift
|
|
61
|
+
;;
|
|
62
|
+
--no-redis)
|
|
63
|
+
NO_REDIS=true
|
|
64
|
+
shift
|
|
65
|
+
;;
|
|
66
|
+
*)
|
|
67
|
+
shift
|
|
68
|
+
;;
|
|
69
|
+
esac
|
|
70
|
+
done
|
|
71
|
+
|
|
72
|
+
local TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
73
|
+
local COLOR=$(get_log_color "$LEVEL")
|
|
74
|
+
|
|
75
|
+
# 1. Terminal output (with colors)
|
|
76
|
+
if [ "$NO_TERMINAL" = false ]; then
|
|
77
|
+
echo -e "${COLOR}[${LEVEL^^}]${COLOR_RESET} ${COLOR_AGENT}[${AGENT_ID}]${COLOR_RESET} ${MESSAGE}"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# 2. File output (no colors, in /tmp)
|
|
81
|
+
local LOG_FILE="/tmp/agent-${AGENT_ID}.log"
|
|
82
|
+
echo "[${TIMESTAMP}] [${LEVEL^^}] [${AGENT_ID}] ${MESSAGE}" >> "$LOG_FILE"
|
|
83
|
+
|
|
84
|
+
# 3. Redis pub/sub (for portal)
|
|
85
|
+
if [ "$NO_REDIS" = false ]; then
|
|
86
|
+
local LOG_PAYLOAD=$(cat <<EOF
|
|
87
|
+
{
|
|
88
|
+
"level": "${LEVEL}",
|
|
89
|
+
"message": "${MESSAGE}",
|
|
90
|
+
"agentId": "${AGENT_ID}",
|
|
91
|
+
"taskId": "${TASK_ID}",
|
|
92
|
+
"repository": "${REPOSITORY}",
|
|
93
|
+
"timestamp": "${TIMESTAMP}"
|
|
94
|
+
}
|
|
95
|
+
EOF
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Publish to Redis channel: swarm:<task-id>:logs
|
|
99
|
+
redis-cli publish "swarm:${TASK_ID}:logs" "$LOG_PAYLOAD" > /dev/null 2>&1 || true
|
|
100
|
+
|
|
101
|
+
# Also add to sorted set for persistence (with timestamp as score)
|
|
102
|
+
local SCORE=$(date +%s)
|
|
103
|
+
redis-cli zadd "swarm:${TASK_ID}:logs:history" "$SCORE" "$LOG_PAYLOAD" > /dev/null 2>&1 || true
|
|
104
|
+
|
|
105
|
+
# Set TTL on history (7 days)
|
|
106
|
+
redis-cli expire "swarm:${TASK_ID}:logs:history" 604800 > /dev/null 2>&1 || true
|
|
107
|
+
fi
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# If script is executed directly (not sourced)
|
|
111
|
+
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
|
|
112
|
+
if [ $# -lt 2 ]; then
|
|
113
|
+
echo "Usage: $0 <level> <message> [--agent-id <id>] [--task-id <id>]"
|
|
114
|
+
echo ""
|
|
115
|
+
echo "Levels: debug, info, warn, error"
|
|
116
|
+
echo ""
|
|
117
|
+
echo "Examples:"
|
|
118
|
+
echo " $0 info \"Agent started\" --agent-id researcher-1 --task-id task-123"
|
|
119
|
+
echo " $0 error \"Connection failed\" --agent-id reviewer-2 --task-id task-456"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
agent_log "$@"
|
|
124
|
+
fi
|
|
@@ -116,6 +116,9 @@ echo "[Swarm] TTL: $TTL seconds ($(($TTL / 86400)) days)"
|
|
|
116
116
|
METADATA_KEY="swarm:${SWARM_ID}:metadata"
|
|
117
117
|
|
|
118
118
|
# Store base metadata
|
|
119
|
+
# Extract repository name from PWD
|
|
120
|
+
REPO_NAME=$(basename "$(pwd)")
|
|
121
|
+
|
|
119
122
|
redis-cli hset "$METADATA_KEY" \
|
|
120
123
|
swarm_id "$SWARM_ID" \
|
|
121
124
|
task_id "$TASK_ID" \
|
|
@@ -123,7 +126,9 @@ redis-cli hset "$METADATA_KEY" \
|
|
|
123
126
|
max_agents "$MAX_AGENTS" \
|
|
124
127
|
agents "$AGENTS" \
|
|
125
128
|
created_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
126
|
-
status "in_progress"
|
|
129
|
+
status "in_progress" \
|
|
130
|
+
repository "$REPO_NAME" \
|
|
131
|
+
cwd "$(pwd)" > /dev/null
|
|
127
132
|
|
|
128
133
|
# Add extra metadata if provided (JSON string)
|
|
129
134
|
if [ -n "$METADATA_EXTRA" ]; then
|
|
@@ -199,6 +199,40 @@ case "$COMMAND" in
|
|
|
199
199
|
timestamp: ($ts | tonumber)
|
|
200
200
|
}')
|
|
201
201
|
|
|
202
|
+
# Store feedback in Redis for agent to read (if provided and iteration > 0)
|
|
203
|
+
# Debug: Echo values before conditional (only if feedback provided)
|
|
204
|
+
if [ -n "$FEEDBACK" ]; then
|
|
205
|
+
[ "$DEBUG" = "true" ] && echo "[DEBUG] Checking feedback storage: FEEDBACK='$FEEDBACK', ITERATION='${ITERATION:-0}'"
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
# Only store feedback if: feedback is non-empty AND iteration > 0
|
|
209
|
+
# Check iteration value explicitly (not just default)
|
|
210
|
+
if [ -n "$FEEDBACK" ] && [ -n "$ITERATION" ] && [ "$ITERATION" -gt 0 ]; then
|
|
211
|
+
FEEDBACK_KEY="swarm:${TASK_ID}:${AGENT_ID}:feedback:iteration-${ITERATION}"
|
|
212
|
+
FEEDBACK_ARRAY=$(echo "$FEEDBACK" | jq -Rc 'split(",") | map(select(length > 0))')
|
|
213
|
+
|
|
214
|
+
# Only store if feedback array is not empty after filtering
|
|
215
|
+
ARRAY_LENGTH=$(echo "$FEEDBACK_ARRAY" | jq 'length')
|
|
216
|
+
if [ "$ARRAY_LENGTH" -gt 0 ]; then
|
|
217
|
+
# Store as JSON array with 24-hour TTL using redis-cli -x (reads from stdin)
|
|
218
|
+
# Note: -x reads LAST argument from stdin, so we can't use SET key value EX ttl
|
|
219
|
+
# Instead: SET key (value from stdin), then EXPIRE key ttl
|
|
220
|
+
REDIS_RESULT=$(printf '%s' "$FEEDBACK_ARRAY" | redis-cli -x SET "$FEEDBACK_KEY")
|
|
221
|
+
redis-cli EXPIRE "$FEEDBACK_KEY" 86400 >/dev/null
|
|
222
|
+
|
|
223
|
+
# Always log feedback storage (not just in DEBUG mode)
|
|
224
|
+
if [ "$REDIS_RESULT" = "OK" ]; then
|
|
225
|
+
echo " [Feedback] Stored $ARRAY_LENGTH items in Redis (TTL: 24h)"
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
if [ "$DEBUG" = "true" ]; then
|
|
229
|
+
echo "[DEBUG] Stored feedback in $FEEDBACK_KEY (TTL: 24h)"
|
|
230
|
+
echo "[DEBUG] Feedback: $FEEDBACK_ARRAY"
|
|
231
|
+
echo "[DEBUG] Redis SET result: $REDIS_RESULT"
|
|
232
|
+
fi
|
|
233
|
+
fi
|
|
234
|
+
fi
|
|
235
|
+
|
|
202
236
|
# Calculate priority score (lower score = higher priority, popped first)
|
|
203
237
|
# Score = (100 - priority) * 1000000 + timestamp
|
|
204
238
|
# This ensures higher priority messages are processed first, with FIFO for same priority
|
|
@@ -231,14 +265,16 @@ case "$COMMAND" in
|
|
|
231
265
|
|
|
232
266
|
RESULT_KEY="swarm:${TASK_ID}:${AGENT_ID}:result"
|
|
233
267
|
|
|
234
|
-
# Build result message
|
|
268
|
+
# Build result message with optional feedback
|
|
235
269
|
RESULT_MSG=$(jq -n \
|
|
236
270
|
--arg confidence "$CONFIDENCE" \
|
|
237
271
|
--arg iteration "${ITERATION:-0}" \
|
|
272
|
+
--arg feedback "${FEEDBACK:-}" \
|
|
238
273
|
--arg ts "$(date +%s)" \
|
|
239
274
|
'{
|
|
240
275
|
confidence: ($confidence | tonumber),
|
|
241
276
|
iteration: ($iteration | tonumber),
|
|
277
|
+
feedback: ($feedback | split(",") | map(select(length > 0))),
|
|
242
278
|
timestamp: ($ts | tonumber)
|
|
243
279
|
}')
|
|
244
280
|
|
|
@@ -247,6 +283,9 @@ case "$COMMAND" in
|
|
|
247
283
|
echo "[$AGENT_ID] ✅ Result reported"
|
|
248
284
|
echo " Confidence: $CONFIDENCE"
|
|
249
285
|
[ -n "$ITERATION" ] && echo " Iteration: $ITERATION"
|
|
286
|
+
if [ -n "$FEEDBACK" ]; then
|
|
287
|
+
echo " Feedback items: $(echo "$FEEDBACK" | tr ',' '\n' | wc -l)"
|
|
288
|
+
fi
|
|
250
289
|
;;
|
|
251
290
|
|
|
252
291
|
collect)
|
|
@@ -263,6 +302,7 @@ case "$COMMAND" in
|
|
|
263
302
|
|
|
264
303
|
RESULTS=()
|
|
265
304
|
CONFIDENCES=()
|
|
305
|
+
ALL_FEEDBACK=()
|
|
266
306
|
|
|
267
307
|
for AGENT in "${AGENTS[@]}"; do
|
|
268
308
|
RESULT_KEY="swarm:${TASK_ID}:${AGENT}:result"
|
|
@@ -271,12 +311,22 @@ case "$COMMAND" in
|
|
|
271
311
|
RESULT=$(redis-cli LPOP "$RESULT_KEY")
|
|
272
312
|
|
|
273
313
|
if [ -n "$RESULT" ] && [ "$RESULT" != "(nil)" ]; then
|
|
274
|
-
echo " [$AGENT] $(echo "$RESULT" | jq -r '.confidence')"
|
|
275
|
-
RESULTS+=("$RESULT")
|
|
276
|
-
|
|
277
|
-
# Extract confidence for consensus calculation
|
|
278
314
|
CONF=$(echo "$RESULT" | jq -r '.confidence')
|
|
315
|
+
echo " [$AGENT] Confidence: $CONF"
|
|
316
|
+
RESULTS+=("$RESULT")
|
|
279
317
|
CONFIDENCES+=("$CONF")
|
|
318
|
+
|
|
319
|
+
# Check if result includes feedback array
|
|
320
|
+
FEEDBACK=$(echo "$RESULT" | jq -r '.feedback // empty | .[]?' 2>/dev/null)
|
|
321
|
+
if [ -n "$FEEDBACK" ]; then
|
|
322
|
+
echo " [$AGENT] Feedback provided:"
|
|
323
|
+
echo "$RESULT" | jq -r '.feedback[]' | sed 's/^/ - /'
|
|
324
|
+
|
|
325
|
+
# Collect all feedback items
|
|
326
|
+
while IFS= read -r ITEM; do
|
|
327
|
+
ALL_FEEDBACK+=("$ITEM")
|
|
328
|
+
done < <(echo "$RESULT" | jq -r '.feedback[]')
|
|
329
|
+
fi
|
|
280
330
|
else
|
|
281
331
|
echo " [$AGENT] ⚠️ No result found"
|
|
282
332
|
fi
|
|
@@ -293,6 +343,13 @@ case "$COMMAND" in
|
|
|
293
343
|
|
|
294
344
|
echo ""
|
|
295
345
|
echo "[Coordinator] Consensus: $CONSENSUS"
|
|
346
|
+
|
|
347
|
+
# Print aggregated feedback if available
|
|
348
|
+
if [ ${#ALL_FEEDBACK[@]} -gt 0 ]; then
|
|
349
|
+
echo "[Coordinator] Aggregated Feedback (${#ALL_FEEDBACK[@]} items):"
|
|
350
|
+
printf '%s\n' "${ALL_FEEDBACK[@]}" | sort -u | sed 's/^/ - /'
|
|
351
|
+
fi
|
|
352
|
+
|
|
296
353
|
echo "$CONSENSUS"
|
|
297
354
|
else
|
|
298
355
|
echo ""
|
|
@@ -389,7 +389,11 @@ function check_heartbeats_loop() {
|
|
|
389
389
|
if [[ " ${LOOP3_AGENTS} " =~ " ${AGENT} " ]]; then
|
|
390
390
|
REMAINING=$((${#LOOP3_COMPLETED_AGENTS[@]}))
|
|
391
391
|
REQUIRED=$(calculate_quorum "$MIN_QUORUM_LOOP3" "$LOOP3_TOTAL")
|
|
392
|
-
elif [[ " ${LOOP2_AGENTS} " =~ " ${
|
|
392
|
+
elif [[ " ${LOOP2_AGENTS} " =~ " ${AGENT} " ]]; then
|
|
393
|
+
# Safety check: LOOP2_COMPLETED_AGENTS may not be initialized during Loop 3
|
|
394
|
+
if [ -z "${LOOP2_COMPLETED_AGENTS+x}" ]; then
|
|
395
|
+
continue
|
|
396
|
+
fi
|
|
393
397
|
REMAINING=$((${#LOOP2_COMPLETED_AGENTS[@]}))
|
|
394
398
|
REQUIRED=$(calculate_quorum "$MIN_QUORUM_LOOP2" "$LOOP2_TOTAL")
|
|
395
399
|
else
|
|
@@ -787,12 +791,22 @@ for ITERATION in $(seq 1 $MAX_ITERATIONS); do
|
|
|
787
791
|
fi
|
|
788
792
|
echo ""
|
|
789
793
|
|
|
790
|
-
# Step 4: Collect Loop 2 consensus scores (only from completed agents)
|
|
794
|
+
# Step 4: Collect Loop 2 consensus scores and feedback (only from completed agents)
|
|
791
795
|
echo "[Loop 2] Collecting consensus scores from ${#LOOP2_COMPLETED_AGENTS[@]} agents..."
|
|
792
796
|
LOOP2_COMPLETED_IDS=$(IFS=','; echo "${LOOP2_COMPLETED_AGENTS[*]}")
|
|
793
|
-
|
|
797
|
+
|
|
798
|
+
# Capture full output to extract both consensus and feedback
|
|
799
|
+
COLLECT_OUTPUT=$(./.claude/skills/redis-coordination/invoke-waiting-mode.sh collect \
|
|
794
800
|
--task-id "$TASK_ID" \
|
|
795
|
-
--agent-ids "$LOOP2_COMPLETED_IDS"
|
|
801
|
+
--agent-ids "$LOOP2_COMPLETED_IDS")
|
|
802
|
+
|
|
803
|
+
LOOP2_CONSENSUS=$(echo "$COLLECT_OUTPUT" | tail -1)
|
|
804
|
+
|
|
805
|
+
# Extract aggregated feedback from collect output
|
|
806
|
+
LOOP2_FEEDBACK=""
|
|
807
|
+
if echo "$COLLECT_OUTPUT" | grep -q "Aggregated Feedback"; then
|
|
808
|
+
LOOP2_FEEDBACK=$(echo "$COLLECT_OUTPUT" | sed -n '/Aggregated Feedback/,/Consensus:/p' | grep '^\s*-' | sed 's/^\s*-\s*//' | paste -sd ',' -)
|
|
809
|
+
fi
|
|
796
810
|
|
|
797
811
|
echo "[Loop 2] Average consensus: $LOOP2_CONSENSUS (from ${#LOOP2_COMPLETED_AGENTS[@]}/${LOOP2_TOTAL} agents)"
|
|
798
812
|
|
|
@@ -803,6 +817,44 @@ for ITERATION in $(seq 1 $MAX_ITERATIONS); do
|
|
|
803
817
|
'{consensus: ($consensus | tonumber), iteration: ($iteration | tonumber)}')
|
|
804
818
|
echo "$LOOP2_METRIC" | redis-cli -x LPUSH "swarm:${TASK_ID}:metrics:loop2_consensus" >/dev/null
|
|
805
819
|
|
|
820
|
+
# SPRINT 3 - Phase 2: Store iteration results for all agents
|
|
821
|
+
echo "[Coordinator] Storing iteration results for history..."
|
|
822
|
+
IFS=',' read -ra ALL_AGENTS_ARRAY <<< "$LOOP3_AGENTS,$LOOP2_AGENTS"
|
|
823
|
+
for AGENT in "${ALL_AGENTS_ARRAY[@]}"; do
|
|
824
|
+
# Get agent's confidence score
|
|
825
|
+
AGENT_CONFIDENCE=$(redis-cli get "swarm:${TASK_ID}:${AGENT}:confidence:iteration-${ITERATION}" || echo "0")
|
|
826
|
+
if [ "$AGENT_CONFIDENCE" = "(nil)" ]; then
|
|
827
|
+
AGENT_CONFIDENCE="0"
|
|
828
|
+
fi
|
|
829
|
+
|
|
830
|
+
# Get agent's result/output (try multiple possible keys)
|
|
831
|
+
AGENT_RESULT=$(redis-cli get "swarm:${TASK_ID}:${AGENT}:output" || echo "")
|
|
832
|
+
if [ "$AGENT_RESULT" = "(nil)" ] || [ -z "$AGENT_RESULT" ]; then
|
|
833
|
+
AGENT_RESULT="Completed iteration $ITERATION"
|
|
834
|
+
fi
|
|
835
|
+
|
|
836
|
+
# Store result with metadata
|
|
837
|
+
RESULT_DATA=$(jq -nc \
|
|
838
|
+
--arg result "$AGENT_RESULT" \
|
|
839
|
+
--arg confidence "$AGENT_CONFIDENCE" \
|
|
840
|
+
--arg iteration "$ITERATION" \
|
|
841
|
+
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
842
|
+
'{result: $result, confidence: ($confidence | tonumber), iteration: ($iteration | tonumber), timestamp: $timestamp}')
|
|
843
|
+
|
|
844
|
+
echo "$RESULT_DATA" | redis-cli -x setex "swarm:${TASK_ID}:${AGENT}:result:iteration-${ITERATION}" 86400 >/dev/null
|
|
845
|
+
|
|
846
|
+
# Store feedback if available (from Loop 2 validators)
|
|
847
|
+
if [ -n "$LOOP2_FEEDBACK" ]; then
|
|
848
|
+
FEEDBACK_DATA=$(jq -nc \
|
|
849
|
+
--arg feedback "$LOOP2_FEEDBACK" \
|
|
850
|
+
--arg iteration "$ITERATION" \
|
|
851
|
+
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
852
|
+
'{feedback: $feedback, iteration: ($iteration | tonumber), timestamp: $timestamp}')
|
|
853
|
+
echo "$FEEDBACK_DATA" | redis-cli -x setex "swarm:${TASK_ID}:${AGENT}:feedback:iteration-${ITERATION}" 86400 >/dev/null
|
|
854
|
+
fi
|
|
855
|
+
done
|
|
856
|
+
echo "[Coordinator] Iteration results stored for ${#ALL_AGENTS_ARRAY[@]} agents"
|
|
857
|
+
|
|
806
858
|
# Consensus check
|
|
807
859
|
if (( $(echo "$LOOP2_CONSENSUS >= $CONSENSUS" | bc -l) )); then
|
|
808
860
|
echo "✅ CONSENSUS REACHED ($LOOP2_CONSENSUS >= $CONSENSUS)"
|
|
@@ -899,8 +951,16 @@ for ITERATION in $(seq 1 $MAX_ITERATIONS); do
|
|
|
899
951
|
exit 1
|
|
900
952
|
fi
|
|
901
953
|
|
|
902
|
-
# Wake agents for next iteration with role-based priorities
|
|
903
|
-
echo "[Coordinator] Waking agents for iteration $((ITERATION + 1)) with priorities..."
|
|
954
|
+
# Wake agents for next iteration with role-based priorities and specific feedback
|
|
955
|
+
echo "[Coordinator] Waking agents for iteration $((ITERATION + 1)) with priorities and feedback..."
|
|
956
|
+
|
|
957
|
+
# Build feedback message for Loop 3 implementers
|
|
958
|
+
LOOP3_FEEDBACK="Improve consensus from $LOOP2_CONSENSUS to >=$CONSENSUS"
|
|
959
|
+
if [ -n "$LOOP2_FEEDBACK" ]; then
|
|
960
|
+
# Include specific validator feedback
|
|
961
|
+
LOOP3_FEEDBACK="$LOOP3_FEEDBACK,$LOOP2_FEEDBACK"
|
|
962
|
+
echo "[Coordinator] Passing validator feedback to Loop 3: $(echo "$LOOP2_FEEDBACK" | tr ',' '\n' | wc -l) items"
|
|
963
|
+
fi
|
|
904
964
|
|
|
905
965
|
# Wake Loop 3 implementers with MEDIUM priority (priority=30)
|
|
906
966
|
IFS=',' read -ra LOOP3_ARRAY <<< "$LOOP3_AGENTS"
|
|
@@ -911,7 +971,7 @@ for ITERATION in $(seq 1 $MAX_ITERATIONS); do
|
|
|
911
971
|
--priority 30 \
|
|
912
972
|
--reason "cfn_loop_iteration" \
|
|
913
973
|
--iteration $((ITERATION + 1)) \
|
|
914
|
-
--feedback "
|
|
974
|
+
--feedback "$LOOP3_FEEDBACK"
|
|
915
975
|
done
|
|
916
976
|
|
|
917
977
|
# Wake Loop 2 validators with HIGH priority (priority=10)
|
|
@@ -923,7 +983,7 @@ for ITERATION in $(seq 1 $MAX_ITERATIONS); do
|
|
|
923
983
|
--priority 10 \
|
|
924
984
|
--reason "cfn_loop_iteration" \
|
|
925
985
|
--iteration $((ITERATION + 1)) \
|
|
926
|
-
--feedback "
|
|
986
|
+
--feedback "Re-validate iteration $((ITERATION + 1)) work against threshold >=$CONSENSUS"
|
|
927
987
|
done
|
|
928
988
|
|
|
929
989
|
echo ""
|