@devo-bmad-custom/agent-orchestration 1.0.8 → 1.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devo-bmad-custom/agent-orchestration",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "BMAD Method — AI-native agile workflow system for Claude Code and compatible AI assistants",
5
5
  "keywords": [
6
6
  "bmad",
@@ -5,8 +5,9 @@ Verified, tested tmux command templates for agent orchestration. Every command i
5
5
  **CRITICAL RULES:**
6
6
  1. `sleep 10` before AND after every tmux command — no exceptions
7
7
  2. Always append `Enter` to every `tmux send-keys` call
8
- 3. Verify pane exists before any operation targeting it
9
- 4. Use `/rename` and `/color` Claude Code commands (not OSC 2 or `select-pane -T`) for agent identity
8
+ 3. **Use `-l` (literal) flag for all free-form message content** — prevents `|`, `:`, and other chars being interpreted as tmux key sequences. Send `Enter` as a separate call after. Do NOT use `-l` for slash commands (`/color`, `/rename`, `/exit`) — those must be interpreted.
9
+ 4. Verify pane exists before any operation targeting it
10
+ 5. **`/color` and `/rename` are sent by the spawner** via separate `tmux send-keys` calls after the agent starts — never rely on the agent's prompt to self-invoke them. Each command is its own `send-keys` call with `Enter`, with `sleep 10` between.
10
11
 
11
12
  ---
12
13
 
@@ -55,31 +56,38 @@ ROLE="dev"
55
56
  ROLE_COLOR=$(get_role_color "$ROLE")
56
57
  SPAWNER_PANE=$(tmux display-message -p "#{pane_id}")
57
58
 
58
- # 1. Split the pane
59
+ # 1. Split the pane — wait 15s for WSL bash + Claude to initialize before sending commands
59
60
  sleep 10
60
61
  tmux split-window -h -c "$PROJECT_ROOT" \
61
62
  "claude --dangerously-skip-permissions 'You are the $ROLE agent. \
62
- FIRST: run /color $ROLE_COLOR then /rename $ROLE-agent. \
63
- Spawner pane: $SPAWNER_PANE. Session file: $SESSION_FILE. \
63
+ Your spawner pane is $SPAWNER_PANE. Session file: $SESSION_FILE. \
64
+ Always use -l flag for message content in tmux send-keys. \
64
65
  Always sleep 10 before and after every tmux command. \
65
66
  Always append Enter to every tmux send-keys call. \
66
67
  Always verify pane exists before targeting it. \
67
68
  $TASK_CONTEXT'"
68
- sleep 10
69
+ sleep 15
69
70
 
70
71
  # 2. Capture new pane ID
71
72
  NEW_PANE_ID=$(tmux list-panes -F "#{pane_id}" | tail -1)
73
+
74
+ # 3. Set agent identity — spawner sends /color and /rename as separate commands.
75
+ # Do NOT combine into one send-keys call; each must be submitted individually.
76
+ sleep 10
77
+ tmux send-keys -t "$NEW_PANE_ID" "/color $ROLE_COLOR" Enter
78
+ sleep 10
79
+ tmux send-keys -t "$NEW_PANE_ID" "/rename ${ROLE}-agent" Enter
72
80
  sleep 10
73
81
 
74
- # 3. Disable OSC 2 auto-rename (we use /rename instead)
82
+ # 4. Disable OSC 2 auto-rename (we use /rename instead)
75
83
  tmux set-option -t "$NEW_PANE_ID" -p allow-rename off
76
84
  sleep 10
77
85
 
78
- # 4. Set pane border title (visible in tmux, separate from /rename)
86
+ # 5. Set pane border title (visible in tmux, separate from /rename)
79
87
  tmux select-pane -t "$NEW_PANE_ID" -T "${ROLE}-${NEW_PANE_ID}"
80
88
  sleep 10
81
89
 
82
- # 5. Rebalance layout with master awareness
90
+ # 6. Rebalance layout with master awareness
83
91
  tmux select-pane -t "$MASTER_PANE"
84
92
  sleep 10
85
93
  tmux select-layout main-vertical
@@ -103,9 +111,11 @@ if [ -z "$PANE_EXISTS" ]; then
103
111
  exit 1
104
112
  fi
105
113
 
106
- # 2. Send the message (ALWAYS with Enter)
114
+ # 2. Send the message — use -l (literal) to prevent | : and other chars being
115
+ # interpreted as tmux key sequences. ALWAYS append Enter separately.
107
116
  sleep 10
108
- tmux send-keys -t "$TARGET_PANE_ID" "$MESSAGE" Enter
117
+ tmux send-keys -t "$TARGET_PANE_ID" -l "$MESSAGE"
118
+ tmux send-keys -t "$TARGET_PANE_ID" Enter
109
119
  sleep 10
110
120
 
111
121
  # 3. Verify delivery — grep for first 2 words of message in pane buffer
@@ -115,7 +125,8 @@ if [ -z "$DELIVERED" ]; then
115
125
  # Retry once
116
126
  echo "WARN: message not found in buffer, retrying..."
117
127
  sleep 10
118
- tmux send-keys -t "$TARGET_PANE_ID" "$MESSAGE" Enter
128
+ tmux send-keys -t "$TARGET_PANE_ID" -l "$MESSAGE"
129
+ tmux send-keys -t "$TARGET_PANE_ID" Enter
119
130
  sleep 10
120
131
  fi
121
132
  ```
@@ -200,9 +211,11 @@ else
200
211
  fi
201
212
  ```
202
213
 
203
- ### 6. `tmux_register_agent` — Agent startup: find session, register, set identity
214
+ ### 6. `tmux_register_agent` — Agent startup: find session, register
215
+
216
+ Spawned agents do NOT self-invoke `/color` or `/rename` — the spawner sends those via `tmux send-keys` before handing off the task. This template handles session registration only.
204
217
 
205
- Every agent — including the master/coordinator conversation runs this on startup BEFORE doing any work. The master conversation always runs `/color blue` + `/rename master-agent` first.
218
+ The master/coordinator conversation is the exception: it runs `/color blue` and `/rename master-agent` manually as its first two actions since there is no spawner above it.
206
219
 
207
220
  ```bash
208
221
  # Inputs: ROLE, SESSION_FILE (passed in spawn context)
@@ -213,11 +226,6 @@ SESSION_NAME=$(tmux display-message -p "#{session_name}")
213
226
  WINDOW_ID=$(tmux display-message -p "#{window_id}")
214
227
  PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")
215
228
 
216
- # 2. Set own identity via Claude Code commands
217
- # (These are sent as slash commands in the Claude conversation, not bash)
218
- # /color <role_color>
219
- # /rename <role>-agent
220
-
221
229
  # 3. Find session file
222
230
  if [ -n "$BMAD_SESSION_ID" ]; then
223
231
  SESSION_FILE="$PROJECT_ROOT/_bmad-output/sessions/$BMAD_SESSION_ID/agent-sessions.md"
@@ -250,8 +258,10 @@ RESULT="pass"
250
258
  SESSION_ID="<claude_session_id>"
251
259
 
252
260
  sleep 10
253
- tmux send-keys -t "$SPAWNER_PANE" \
254
- "STEP COMPLETE: $TASK_ID | result: $RESULT | session: $SESSION_ID" Enter
261
+ # Use -l (literal) so | and : are not interpreted as tmux key sequences
262
+ tmux send-keys -t "$SPAWNER_PANE" -l \
263
+ "STEP COMPLETE: $TASK_ID | result: $RESULT | session: $SESSION_ID"
264
+ tmux send-keys -t "$SPAWNER_PANE" Enter
255
265
  sleep 10
256
266
 
257
267
  # 4. Check for more pending tasks for this role
@@ -336,18 +346,107 @@ tmux send-keys -t "$AGENT_PANE" "/color $NEW_COLOR" Enter
336
346
  sleep 10
337
347
  tmux send-keys -t "$AGENT_PANE" "/rename $NEW_ROLE-agent" Enter
338
348
  sleep 10
339
- tmux send-keys -t "$AGENT_PANE" "Handle TASK-003 from the session file" Enter
349
+ tmux send-keys -t "$AGENT_PANE" -l "Handle TASK-003 from the session file"
350
+ tmux send-keys -t "$AGENT_PANE" Enter
340
351
  sleep 10
341
352
  ```
342
353
 
343
354
  ---
344
355
 
356
+ ## Verification & Retry Protocol
357
+
358
+ Every tmux operation must be verified after execution. Never assume a command worked.
359
+
360
+ ### Verifying `/color` and `/rename` applied
361
+
362
+ After the spawner sends identity commands, verify the pane is alive and responsive:
363
+
364
+ ```bash
365
+ # After sending /color and /rename, verify pane is still active (not crashed)
366
+ sleep 10
367
+ PANE_ALIVE=$(tmux list-panes -a -F "#{pane_id}" | grep -Fx "$NEW_PANE_ID")
368
+ if [ -z "$PANE_ALIVE" ]; then
369
+ echo "ERROR: agent pane $NEW_PANE_ID died after identity commands"
370
+ exit 1
371
+ fi
372
+ # Note: /color and /rename visual effects are immediate in Claude Code.
373
+ # If the pane is alive, the commands were received.
374
+ ```
375
+
376
+ ### Verifying message delivery
377
+
378
+ Always capture the pane buffer after sending a message and grep for the key token:
379
+
380
+ ```bash
381
+ tmux_verify_delivery() {
382
+ local PANE="$1"
383
+ local TOKEN="$2" # unique substring from the message
384
+ local RETRIES=3
385
+
386
+ for i in $(seq 1 $RETRIES); do
387
+ sleep 10
388
+ FOUND=$(tmux capture-pane -t "$PANE" -p -S - | grep -F "$TOKEN")
389
+ if [ -n "$FOUND" ]; then
390
+ echo "OK: message confirmed in pane $PANE (attempt $i)"
391
+ return 0
392
+ fi
393
+ if [ $i -lt $RETRIES ]; then
394
+ echo "WARN: '$TOKEN' not found in pane $PANE, retrying ($i/$RETRIES)..."
395
+ fi
396
+ done
397
+
398
+ echo "ERROR: message '$TOKEN' never confirmed in pane $PANE after $RETRIES attempts"
399
+ return 1
400
+ }
401
+
402
+ # Usage after sending a message:
403
+ tmux send-keys -t "$TARGET_PANE" -l "$MESSAGE"
404
+ tmux send-keys -t "$TARGET_PANE" Enter
405
+ tmux_verify_delivery "$TARGET_PANE" "TASK-001" # use a unique token from the message
406
+ ```
407
+
408
+ ### Verifying agent spawned and initialized
409
+
410
+ After splitting, confirm the pane exists and Claude has started (prompt visible):
411
+
412
+ ```bash
413
+ # Wait for Claude prompt to appear in new pane (up to 30s)
414
+ READY=0
415
+ for i in 1 2 3; do
416
+ sleep 10
417
+ PROMPT=$(tmux capture-pane -t "$NEW_PANE_ID" -p -S - | grep -c "❯\|>\|Claude\|Human")
418
+ if [ "$PROMPT" -gt 0 ]; then
419
+ READY=1
420
+ break
421
+ fi
422
+ echo "Waiting for agent to initialize (attempt $i)..."
423
+ done
424
+ if [ "$READY" -eq 0 ]; then
425
+ echo "ERROR: agent pane $NEW_PANE_ID did not show prompt after 30s"
426
+ exit 1
427
+ fi
428
+ ```
429
+
430
+ ### Retry rules
431
+
432
+ | Operation | Verify by | Max retries | On failure |
433
+ |---|---|---|---|
434
+ | Message send | grep token in pane buffer | 3 | Log error, write to session file |
435
+ | `/color` / `/rename` | pane still alive | 1 | Re-send both commands |
436
+ | Pane spawn | pane ID in list + prompt visible | 3 | Kill and re-spawn |
437
+ | Layout rebalance | `tmux list-panes` shows expected count | 1 | Re-run `select-layout` |
438
+
439
+ ---
440
+
345
441
  ## Common Mistakes (Avoid These)
346
442
 
347
443
  1. **No `Enter` on send-keys** — message typed but never submitted
348
444
  2. **No sleep between tmux commands** — race conditions, stale pane lists
349
- 3. **Using OSC 2 / `select-pane -T` for naming** — Claude Code overwrites these
350
- 4. **Killing pane without `/exit` first** — leaves partial writes, git locks
351
- 5. **Using `tiled` layout instead of `main-vertical`/`main-horizontal`** breaks master position
352
- 6. **Reading pane titles for routing**unreliable; use session file pane IDs
353
- 7. **Spawning without `--dangerously-skip-permissions`**agent halts on every tool use
445
+ 3. **Combining `/color` and `/rename` in one send-keys call** — only the first command runs; send each as a separate call with `sleep 10` between
446
+ 4. **Using OSC 2 / `select-pane -T` for naming** — Claude Code overwrites these
447
+ 5. **Killing pane without `/exit` first** leaves partial writes, git locks
448
+ 6. **Using `tiled` layout instead of `main-vertical`/`main-horizontal`** breaks master position
449
+ 7. **Reading pane titles for routing** unreliable; use session file pane IDs
450
+ 8. **Spawning without `--dangerously-skip-permissions`** — agent halts on every tool use
451
+ 9. **No `-l` flag on message content** — `|` and `:` get interpreted as key sequences, message is garbled
452
+ 10. **Agent self-invoking `/color`+`/rename`** — unreliable; spawner sends these via `tmux send-keys` after the agent starts