@devo-bmad-custom/agent-orchestration 1.0.9 → 1.0.11

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.9",
3
+ "version": "1.0.11",
4
4
  "description": "BMAD Method — AI-native agile workflow system for Claude Code and compatible AI assistants",
5
5
  "keywords": [
6
6
  "bmad",
@@ -7,7 +7,7 @@ Verified, tested tmux command templates for agent orchestration. Every command i
7
7
  2. Always append `Enter` to every `tmux send-keys` call
8
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
9
  4. Verify pane exists before any operation targeting it
10
- 5. Use `/rename` and `/color` Claude Code commands (not OSC 2 or `select-pane -T`) for agent identity
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.
11
11
 
12
12
  ---
13
13
 
@@ -56,31 +56,38 @@ ROLE="dev"
56
56
  ROLE_COLOR=$(get_role_color "$ROLE")
57
57
  SPAWNER_PANE=$(tmux display-message -p "#{pane_id}")
58
58
 
59
- # 1. Split the pane
59
+ # 1. Split the pane — wait 15s for WSL bash + Claude to initialize before sending commands
60
60
  sleep 10
61
61
  tmux split-window -h -c "$PROJECT_ROOT" \
62
62
  "claude --dangerously-skip-permissions 'You are the $ROLE agent. \
63
- FIRST: run /color $ROLE_COLOR then /rename $ROLE-agent. \
64
- 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. \
65
65
  Always sleep 10 before and after every tmux command. \
66
66
  Always append Enter to every tmux send-keys call. \
67
67
  Always verify pane exists before targeting it. \
68
68
  $TASK_CONTEXT'"
69
- sleep 10
69
+ sleep 15
70
70
 
71
71
  # 2. Capture new pane ID
72
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
73
80
  sleep 10
74
81
 
75
- # 3. Disable OSC 2 auto-rename (we use /rename instead)
82
+ # 4. Disable OSC 2 auto-rename (we use /rename instead)
76
83
  tmux set-option -t "$NEW_PANE_ID" -p allow-rename off
77
84
  sleep 10
78
85
 
79
- # 4. Set pane border title (visible in tmux, separate from /rename)
86
+ # 5. Set pane border title (visible in tmux, separate from /rename)
80
87
  tmux select-pane -t "$NEW_PANE_ID" -T "${ROLE}-${NEW_PANE_ID}"
81
88
  sleep 10
82
89
 
83
- # 5. Rebalance layout with master awareness
90
+ # 6. Rebalance layout with master awareness
84
91
  tmux select-pane -t "$MASTER_PANE"
85
92
  sleep 10
86
93
  tmux select-layout main-vertical
@@ -126,18 +133,25 @@ fi
126
133
 
127
134
  ### 3. `tmux_kill_agent` — Gracefully close an agent pane
128
135
 
136
+ **Trigger:** Coordinator sees a pane with status `ready-to-close` in the session file Pane Lifecycle table.
137
+
138
+ **Pre-conditions (verify all before killing):**
139
+ - [ ] Agent's report-back received (STEP COMPLETE message seen in this pane or session file updated)
140
+ - [ ] Task marked `done` in session file Tasks section
141
+ - [ ] Claude session ID saved to session file
142
+
129
143
  ```bash
130
- # Inputs: TARGET_PANE_ID, MASTER_PANE, SESSION_NAME, WINDOW_ID
144
+ # Inputs: TARGET_PANE_ID, MASTER_PANE, SESSION_FILE
131
145
  TARGET_PANE_ID="%31"
132
146
  MASTER_PANE="%0"
133
147
 
134
- # 1. Verify pane exists in expected context
148
+ # 1. Verify pane exists
135
149
  sleep 10
136
- VERIFIED=$(tmux list-panes -a -F "#{pane_id} #{session_name} #{window_id}" \
137
- | grep "^$TARGET_PANE_ID ")
150
+ VERIFIED=$(tmux list-panes -a -F "#{pane_id}" | grep -Fx "$TARGET_PANE_ID")
138
151
  if [ -z "$VERIFIED" ]; then
139
- echo "ERROR: pane $TARGET_PANE_ID not foundaborting kill"
140
- exit 1
152
+ echo "WARN: pane $TARGET_PANE_ID already gonemarking closed in session file"
153
+ # Update session file status to closed and exit
154
+ exit 0
141
155
  fi
142
156
 
143
157
  # 2. Send /exit (lets Claude flush writes and exit cleanly)
@@ -145,17 +159,24 @@ sleep 10
145
159
  tmux send-keys -t "$TARGET_PANE_ID" "/exit" Enter
146
160
  sleep 10
147
161
 
148
- # 3. Kill the pane
149
- tmux kill-pane -t "$TARGET_PANE_ID"
150
- sleep 10
162
+ # 3. Verify pane closed on its own (Claude exits after /exit)
163
+ STILL_ALIVE=$(tmux list-panes -a -F "#{pane_id}" | grep -Fx "$TARGET_PANE_ID")
164
+ if [ -n "$STILL_ALIVE" ]; then
165
+ # Force kill if still up after /exit
166
+ tmux kill-pane -t "$TARGET_PANE_ID"
167
+ sleep 10
168
+ fi
151
169
 
152
- # 4. Rebalance remaining panes
170
+ # 4. Update session file — mark pane as closed
171
+ # Edit Pane Lifecycle row: change status to `closed`, check off remaining boxes
172
+
173
+ # 5. Rebalance remaining panes
153
174
  tmux select-pane -t "$MASTER_PANE"
154
175
  sleep 10
155
176
  tmux select-layout main-vertical
156
177
  sleep 10
157
178
 
158
- echo "Killed pane $TARGET_PANE_ID and rebalanced"
179
+ echo "Closed pane $TARGET_PANE_ID session file updated, layout rebalanced"
159
180
  ```
160
181
 
161
182
  ### 4. `tmux_rebalance` — Equalize pane sizes with master awareness
@@ -204,9 +225,11 @@ else
204
225
  fi
205
226
  ```
206
227
 
207
- ### 6. `tmux_register_agent` — Agent startup: find session, register, set identity
228
+ ### 6. `tmux_register_agent` — Agent startup: find session, register
229
+
230
+ 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.
208
231
 
209
- 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.
232
+ 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.
210
233
 
211
234
  ```bash
212
235
  # Inputs: ROLE, SESSION_FILE (passed in spawn context)
@@ -217,11 +240,6 @@ SESSION_NAME=$(tmux display-message -p "#{session_name}")
217
240
  WINDOW_ID=$(tmux display-message -p "#{window_id}")
218
241
  PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")
219
242
 
220
- # 2. Set own identity via Claude Code commands
221
- # (These are sent as slash commands in the Claude conversation, not bash)
222
- # /color <role_color>
223
- # /rename <role>-agent
224
-
225
243
  # 3. Find session file
226
244
  if [ -n "$BMAD_SESSION_ID" ]; then
227
245
  SESSION_FILE="$PROJECT_ROOT/_bmad-output/sessions/$BMAD_SESSION_ID/agent-sessions.md"
@@ -261,8 +279,13 @@ tmux send-keys -t "$SPAWNER_PANE" Enter
261
279
  sleep 10
262
280
 
263
281
  # 4. Check for more pending tasks for this role
264
- # 5. If found: claim next task
265
- # 6. If none: set status to idle in Active Agents table
282
+ # 5. If found: claim next task and continue
283
+ # 6. If none:
284
+ # a. Set status to `ready-to-close` in Pane Lifecycle table (NOT Active Agents)
285
+ # b. Check all close-down boxes in Pane Lifecycle row:
286
+ # ☑ report-back sent · ☑ session ID saved · ☑ task marked done · ☑ ready-to-close set
287
+ # c. The COORDINATOR is responsible for executing /exit + kill-pane.
288
+ # Do NOT self-exit unless you are the coordinator or explicitly told to.
266
289
  ```
267
290
 
268
291
  ---
@@ -349,12 +372,100 @@ sleep 10
349
372
 
350
373
  ---
351
374
 
375
+ ## Verification & Retry Protocol
376
+
377
+ Every tmux operation must be verified after execution. Never assume a command worked.
378
+
379
+ ### Verifying `/color` and `/rename` applied
380
+
381
+ After the spawner sends identity commands, verify the pane is alive and responsive:
382
+
383
+ ```bash
384
+ # After sending /color and /rename, verify pane is still active (not crashed)
385
+ sleep 10
386
+ PANE_ALIVE=$(tmux list-panes -a -F "#{pane_id}" | grep -Fx "$NEW_PANE_ID")
387
+ if [ -z "$PANE_ALIVE" ]; then
388
+ echo "ERROR: agent pane $NEW_PANE_ID died after identity commands"
389
+ exit 1
390
+ fi
391
+ # Note: /color and /rename visual effects are immediate in Claude Code.
392
+ # If the pane is alive, the commands were received.
393
+ ```
394
+
395
+ ### Verifying message delivery
396
+
397
+ Always capture the pane buffer after sending a message and grep for the key token:
398
+
399
+ ```bash
400
+ tmux_verify_delivery() {
401
+ local PANE="$1"
402
+ local TOKEN="$2" # unique substring from the message
403
+ local RETRIES=3
404
+
405
+ for i in $(seq 1 $RETRIES); do
406
+ sleep 10
407
+ FOUND=$(tmux capture-pane -t "$PANE" -p -S - | grep -F "$TOKEN")
408
+ if [ -n "$FOUND" ]; then
409
+ echo "OK: message confirmed in pane $PANE (attempt $i)"
410
+ return 0
411
+ fi
412
+ if [ $i -lt $RETRIES ]; then
413
+ echo "WARN: '$TOKEN' not found in pane $PANE, retrying ($i/$RETRIES)..."
414
+ fi
415
+ done
416
+
417
+ echo "ERROR: message '$TOKEN' never confirmed in pane $PANE after $RETRIES attempts"
418
+ return 1
419
+ }
420
+
421
+ # Usage after sending a message:
422
+ tmux send-keys -t "$TARGET_PANE" -l "$MESSAGE"
423
+ tmux send-keys -t "$TARGET_PANE" Enter
424
+ tmux_verify_delivery "$TARGET_PANE" "TASK-001" # use a unique token from the message
425
+ ```
426
+
427
+ ### Verifying agent spawned and initialized
428
+
429
+ After splitting, confirm the pane exists and Claude has started (prompt visible):
430
+
431
+ ```bash
432
+ # Wait for Claude prompt to appear in new pane (up to 30s)
433
+ READY=0
434
+ for i in 1 2 3; do
435
+ sleep 10
436
+ PROMPT=$(tmux capture-pane -t "$NEW_PANE_ID" -p -S - | grep -c "❯\|>\|Claude\|Human")
437
+ if [ "$PROMPT" -gt 0 ]; then
438
+ READY=1
439
+ break
440
+ fi
441
+ echo "Waiting for agent to initialize (attempt $i)..."
442
+ done
443
+ if [ "$READY" -eq 0 ]; then
444
+ echo "ERROR: agent pane $NEW_PANE_ID did not show prompt after 30s"
445
+ exit 1
446
+ fi
447
+ ```
448
+
449
+ ### Retry rules
450
+
451
+ | Operation | Verify by | Max retries | On failure |
452
+ |---|---|---|---|
453
+ | Message send | grep token in pane buffer | 3 | Log error, write to session file |
454
+ | `/color` / `/rename` | pane still alive | 1 | Re-send both commands |
455
+ | Pane spawn | pane ID in list + prompt visible | 3 | Kill and re-spawn |
456
+ | Layout rebalance | `tmux list-panes` shows expected count | 1 | Re-run `select-layout` |
457
+
458
+ ---
459
+
352
460
  ## Common Mistakes (Avoid These)
353
461
 
354
462
  1. **No `Enter` on send-keys** — message typed but never submitted
355
463
  2. **No sleep between tmux commands** — race conditions, stale pane lists
356
- 3. **Using OSC 2 / `select-pane -T` for naming** — Claude Code overwrites these
357
- 4. **Killing pane without `/exit` first** — leaves partial writes, git locks
358
- 5. **Using `tiled` layout instead of `main-vertical`/`main-horizontal`** breaks master position
359
- 6. **Reading pane titles for routing**unreliable; use session file pane IDs
360
- 7. **Spawning without `--dangerously-skip-permissions`**agent halts on every tool use
464
+ 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
465
+ 4. **Using OSC 2 / `select-pane -T` for naming** — Claude Code overwrites these
466
+ 5. **Killing pane without `/exit` first** leaves partial writes, git locks
467
+ 6. **Using `tiled` layout instead of `main-vertical`/`main-horizontal`** breaks master position
468
+ 7. **Reading pane titles for routing** unreliable; use session file pane IDs
469
+ 8. **Spawning without `--dangerously-skip-permissions`** — agent halts on every tool use
470
+ 9. **No `-l` flag on message content** — `|` and `:` get interpreted as key sequences, message is garbled
471
+ 10. **Agent self-invoking `/color`+`/rename`** — unreliable; spawner sends these via `tmux send-keys` after the agent starts