@devo-bmad-custom/agent-orchestration 1.0.15 → 1.0.18
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/lib/installer.js
CHANGED
|
@@ -234,6 +234,19 @@ async function install(opts) {
|
|
|
234
234
|
console.log(chalk.green(` ✓ .agents/skills/ (${skillFiles.length} files)`));
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
// ── Orchestration template ─────────────────────────────────────────────────
|
|
238
|
+
const pkgOrchSrc = path.join(SRC_DIR, '.agents', 'orchestration', 'session-template.md');
|
|
239
|
+
if (await fs.pathExists(pkgOrchSrc)) {
|
|
240
|
+
const destOrch = path.join(projectRoot, '.agents', 'orchestration');
|
|
241
|
+
await fs.ensureDir(destOrch);
|
|
242
|
+
const destFile = path.join(destOrch, 'session-template.md');
|
|
243
|
+
await fs.copy(pkgOrchSrc, destFile, { overwrite: true });
|
|
244
|
+
const content = await fs.readFile(pkgOrchSrc);
|
|
245
|
+
newFileEntries.push({ relPath: '.agents/orchestration/session-template.md', hash: sha256(content) });
|
|
246
|
+
installedCount++;
|
|
247
|
+
console.log(chalk.green(' ✓ .agents/orchestration/session-template.md'));
|
|
248
|
+
}
|
|
249
|
+
|
|
237
250
|
// ── Orphan removal (update only) ──────────────────────────────────────────
|
|
238
251
|
if (isUpdate) {
|
|
239
252
|
const oldEntries = await readFilesManifest(bmadDir);
|
|
@@ -711,19 +724,22 @@ async function setupTmux(projectRoot, chalk) {
|
|
|
711
724
|
console.log(' ' + chalk.cyan('sudo apt-get install -y wl-clipboard imagemagick wslu'));
|
|
712
725
|
console.log(' ' + chalk.white('⑤ Docker Desktop WSL integration') + chalk.dim(' — GUI only:'));
|
|
713
726
|
console.log(' ' + chalk.dim('Docker Desktop → Settings → Resources → WSL Integration → toggle Ubuntu → Apply & Restart'));
|
|
727
|
+
console.log(' ' + chalk.white('⑥ gsudo') + chalk.dim(' (Windows sudo — allows WSL to run elevated PowerShell):'));
|
|
728
|
+
console.log(' ' + chalk.cyan('winget install gerardog.gsudo'));
|
|
729
|
+
console.log(' ' + chalk.dim(' Or via scoop: scoop install gsudo'));
|
|
714
730
|
|
|
715
731
|
console.log('');
|
|
716
732
|
console.log(chalk.bold.yellow(' ✦ Can be done manually OR by an AI with relaxed permissions:'));
|
|
717
733
|
console.log(chalk.dim(' These are safe to automate — no sudo or system-level access needed.\n'));
|
|
718
|
-
console.log(' ' + chalk.white('
|
|
734
|
+
console.log(' ' + chalk.white('⑧ NVM + Node') + chalk.dim(' (required for Node-based MCP servers):'));
|
|
719
735
|
console.log(' ' + chalk.cyan('curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash'));
|
|
720
736
|
console.log(' ' + chalk.cyan('source ~/.bashrc && nvm install --lts'));
|
|
721
|
-
console.log(' ' + chalk.white('
|
|
737
|
+
console.log(' ' + chalk.white('⑨ TPM (tmux Plugin Manager):'));
|
|
722
738
|
console.log(' ' + chalk.cyan('git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm'));
|
|
723
739
|
console.log(' ' + chalk.dim(' Then inside tmux: press Ctrl+B I to install plugins'));
|
|
724
|
-
console.log(' ' + chalk.white('
|
|
740
|
+
console.log(' ' + chalk.white('⑩ fzf') + chalk.dim(' (required for Actions popup menu):'));
|
|
725
741
|
console.log(' ' + chalk.cyan('mkdir -p ~/.local/bin && curl -Lo /tmp/fzf.tar.gz https://github.com/junegunn/fzf/releases/download/v0.54.3/fzf-0.54.3-linux_amd64.tar.gz && tar -xzf /tmp/fzf.tar.gz -C ~/.local/bin'));
|
|
726
|
-
console.log(' ' + chalk.white('
|
|
742
|
+
console.log(' ' + chalk.white('⑪ Nerd Fonts') + chalk.dim(' (required for Powerline status bar separators):'));
|
|
727
743
|
console.log(' ' + chalk.dim(' Download JetBrainsMono NFM from https://www.nerdfonts.com/'));
|
|
728
744
|
console.log(' ' + chalk.dim(' Install JetBrainsMonoNerdFontMono-Regular.ttf to Windows (double-click → Install for all users)'));
|
|
729
745
|
console.log(' ' + chalk.white(' Cursor/VS Code:') + ' ' + chalk.cyan('"terminal.integrated.fontFamily": "JetBrainsMono NFM"'));
|
|
@@ -785,6 +801,33 @@ async function setupTmux(projectRoot, chalk) {
|
|
|
785
801
|
console.log(chalk.dim(` ○ ${xdgOpenPath} already exists`));
|
|
786
802
|
}
|
|
787
803
|
|
|
804
|
+
// gsudo shim — lets WSL call Windows-side gsudo.exe without full path
|
|
805
|
+
const gsudoShimPath = path.join(homeDir, '.local', 'bin', 'gsudo');
|
|
806
|
+
if (!await fs.pathExists(gsudoShimPath)) {
|
|
807
|
+
// Find gsudo.exe on Windows side
|
|
808
|
+
const { execSync } = require('child_process');
|
|
809
|
+
let gsudoExe = null;
|
|
810
|
+
try {
|
|
811
|
+
// cmd.exe /c where gsudo returns Windows paths — convert first result to WSL path
|
|
812
|
+
const winPath = execSync('cmd.exe /c where gsudo 2>NUL', { stdio: 'pipe' })
|
|
813
|
+
.toString().split('\n')[0].trim();
|
|
814
|
+
if (winPath && winPath.endsWith('.exe')) {
|
|
815
|
+
// Convert C:\... → /mnt/c/...
|
|
816
|
+
gsudoExe = '/mnt/' + winPath.replace(/\\/g, '/').replace(/^([A-Za-z]):/, (_, d) => d.toLowerCase());
|
|
817
|
+
}
|
|
818
|
+
} catch { /* gsudo not installed on Windows yet */ }
|
|
819
|
+
|
|
820
|
+
if (gsudoExe) {
|
|
821
|
+
const shimContent = `#!/bin/bash\nexec '${gsudoExe}' "$@"\n`;
|
|
822
|
+
await fs.writeFile(gsudoShimPath, shimContent, { mode: 0o755 });
|
|
823
|
+
console.log(chalk.green(` ✓ gsudo shim → ${gsudoShimPath} (delegates to ${gsudoExe})`));
|
|
824
|
+
} else {
|
|
825
|
+
console.log(chalk.yellow(' ⚠ gsudo not found on Windows — install it first (winget install gerardog.gsudo), then re-run setup'));
|
|
826
|
+
}
|
|
827
|
+
} else {
|
|
828
|
+
console.log(chalk.dim(` ○ gsudo shim already exists at ${gsudoShimPath}`));
|
|
829
|
+
}
|
|
830
|
+
|
|
788
831
|
// ── Step 3: TPM check ────────────────────────────────────────────────────
|
|
789
832
|
console.log('\n' + chalk.bold('Step 3 — TPM check'));
|
|
790
833
|
if (await fs.pathExists(tpmPath)) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Agent Session: {{session_id}}
|
|
2
|
+
<!-- Fill all {{placeholders}} on creation. Do not leave unfilled placeholders in an active session. -->
|
|
3
|
+
|
|
4
|
+
## Context
|
|
5
|
+
| Field | Value |
|
|
6
|
+
|-------|-------|
|
|
7
|
+
| **Session ID** | `{{session_id}}` |
|
|
8
|
+
| **Created** | {{iso_timestamp}} |
|
|
9
|
+
| **Creator** | {{creator_role}} (pane `{{creator_pane_id}}`) |
|
|
10
|
+
| **Project Root** | `{{project_root}}` |
|
|
11
|
+
| **Branch** | `{{git_branch}}` |
|
|
12
|
+
| **Base Branch** | `{{base_branch}}` |
|
|
13
|
+
| **Track** | {{track}} <!-- Nano / Small / Compact / Medium / Extended / Large / Review / General --> |
|
|
14
|
+
| **Execution Mode** | {{execution_mode}} <!-- inline / command-blocks / scripts / agent-teams --> |
|
|
15
|
+
| **Session File** | `{{session_file_path}}` |
|
|
16
|
+
|
|
17
|
+
## Git Snapshot
|
|
18
|
+
<!-- Captured at session start. Refresh with `git status` if session runs long. -->
|
|
19
|
+
|
|
20
|
+
**Uncommitted files:**
|
|
21
|
+
```
|
|
22
|
+
{{git_status_output}}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Recent commits (last 5):**
|
|
26
|
+
```
|
|
27
|
+
{{git_log_output}}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Diff summary (base..HEAD):**
|
|
31
|
+
```
|
|
32
|
+
{{git_diff_stat}}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Track Progress
|
|
38
|
+
<!-- Master agent updates this at the START of each step and marks done when complete. -->
|
|
39
|
+
<!-- Step status: ⬜ pending · 🔄 in-progress · ✅ done · ⛔ blocked · ⏭ skipped -->
|
|
40
|
+
|
|
41
|
+
**Current Step:** {{current_step_name}} ({{current_step_number, or 1 if General track}} / {{total_steps, or ? if General track}})
|
|
42
|
+
|
|
43
|
+
| # | Step | Status | Started | Notes |
|
|
44
|
+
|---|------|--------|---------|-------|
|
|
45
|
+
<!-- Master fills this table as the track runs. One row per step. -->
|
|
46
|
+
<!-- Example: | 1 | Target Definition | ✅ done | 14:02 | Targeted depth, branch feature/x | -->
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Active Agents
|
|
51
|
+
<!-- Register on startup. Update Status as work progresses. -->
|
|
52
|
+
|
|
53
|
+
| Pane ID | Role | Status | CWD | Claude Session ID |
|
|
54
|
+
|---------|------|--------|-----|-------------------|
|
|
55
|
+
| {{creator_pane_id}} | {{creator_role}} | active | `{{project_root}}` | — |
|
|
56
|
+
|
|
57
|
+
**Status values:** `active` · `busy` · `idle` · `ready-to-close` · `closed`
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Pane Lifecycle
|
|
62
|
+
<!-- Coordinator checks after every task. Close any pane showing `ready-to-close`. -->
|
|
63
|
+
|
|
64
|
+
| Pane ID | Role | Task | Status | Agent ✓ | Coord ✓ |
|
|
65
|
+
|---------|------|------|--------|---------|---------|
|
|
66
|
+
<!-- Agent ✓ columns: rb=report-back · sid=session-id · done=task-done -->
|
|
67
|
+
<!-- Coord ✓ columns: exit=/exit sent · kill=kill-pane · closed=status updated · rebal=layout rebalanced -->
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Tasks
|
|
72
|
+
<!-- Format: ### TASK-NNN · {status} · {assigned_role} -->
|
|
73
|
+
<!-- Status values: pending · in-progress · blocked · done -->
|
|
74
|
+
|
|
75
|
+
<!-- Add tasks below. Example:
|
|
76
|
+
### TASK-001 · pending · dev
|
|
77
|
+
- **Description:** Fix the user profile API endpoint
|
|
78
|
+
- **Status:** pending
|
|
79
|
+
- **Acceptance:** API returns 200 with correct user data
|
|
80
|
+
-->
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Decisions & Notes
|
|
85
|
+
<!-- Running log of decisions made during this session. Append, never overwrite. -->
|
|
86
|
+
|
|
87
|
+
- `{{iso_timestamp}}` — Session created. Branch: `{{git_branch}}`.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Blockers
|
|
92
|
+
<!-- Items requiring user input before work can continue. -->
|
|
93
|
+
|
|
94
|
+
<!-- | ID | Description | Needs | Since | -->
|
|
@@ -212,7 +212,7 @@ case "$MASTER_POS" in
|
|
|
212
212
|
tmux select-layout main-horizontal
|
|
213
213
|
;;
|
|
214
214
|
*)
|
|
215
|
-
tmux select-layout
|
|
215
|
+
tmux select-layout main-vertical
|
|
216
216
|
;;
|
|
217
217
|
esac
|
|
218
218
|
sleep 10
|
|
@@ -254,7 +254,11 @@ SESSION_NAME=$(tmux display-message -p "#{session_name}")
|
|
|
254
254
|
WINDOW_ID=$(tmux display-message -p "#{window_id}")
|
|
255
255
|
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")
|
|
256
256
|
|
|
257
|
-
#
|
|
257
|
+
# 2. Determine role (passed via spawn context — $ROLE should be set)
|
|
258
|
+
ROLE="${ROLE:-unknown}"
|
|
259
|
+
|
|
260
|
+
# 3. Find session file — SESSION_FILE should be passed explicitly in spawn context.
|
|
261
|
+
# Fall back to most recent only if not provided (fragile — prefer explicit pass).
|
|
258
262
|
if [ -n "$BMAD_SESSION_ID" ]; then
|
|
259
263
|
SESSION_FILE="$PROJECT_ROOT/_bmad-output/sessions/$BMAD_SESSION_ID/agent-sessions.md"
|
|
260
264
|
else
|
|
@@ -336,16 +340,22 @@ SPAWNER_PANE=$(tmux display-message -p "#{pane_id}")
|
|
|
336
340
|
sleep 10
|
|
337
341
|
tmux split-window -h -c "$PROJECT_ROOT" \
|
|
338
342
|
"claude --dangerously-skip-permissions 'You are the $ROLE agent. \
|
|
339
|
-
FIRST: run /color $ROLE_COLOR then /rename $ROLE-agent. \
|
|
340
343
|
Spawner pane: $SPAWNER_PANE. Session file: $SESSION_FILE. \
|
|
344
|
+
Always use -l flag for message content in tmux send-keys. \
|
|
341
345
|
Always sleep 10 before and after every tmux command. \
|
|
342
346
|
Always append Enter to every tmux send-keys call. \
|
|
343
347
|
Always verify pane exists before targeting it. \
|
|
344
348
|
$TASK_CONTEXT'"
|
|
345
|
-
sleep
|
|
349
|
+
sleep 15
|
|
346
350
|
|
|
347
351
|
# Capture ID
|
|
348
352
|
NEW_PANE_ID=$(tmux list-panes -F "#{pane_id}" | tail -1)
|
|
353
|
+
|
|
354
|
+
# Set agent identity — spawner sends /color and /rename as separate commands
|
|
355
|
+
sleep 10
|
|
356
|
+
tmux send-keys -t "$NEW_PANE_ID" "/color $ROLE_COLOR" Enter
|
|
357
|
+
sleep 10
|
|
358
|
+
tmux send-keys -t "$NEW_PANE_ID" "/rename ${ROLE}-agent" Enter
|
|
349
359
|
sleep 10
|
|
350
360
|
|
|
351
361
|
# Set tmux pane title (border label)
|
|
@@ -475,7 +485,7 @@ fi
|
|
|
475
485
|
|
|
476
486
|
1. **Killing own pane** — always check `TARGET_PANE_ID != $(tmux display-message -p "#{pane_id}")` AND `TARGET_PANE_ID != MASTER_PANE` before `kill-pane`
|
|
477
487
|
2. **No `Enter` on send-keys** — message typed but never submitted
|
|
478
|
-
|
|
488
|
+
3. **No sleep between tmux commands** — race conditions, stale pane lists
|
|
479
489
|
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
|
|
480
490
|
4. **Using OSC 2 / `select-pane -T` for naming** — Claude Code overwrites these
|
|
481
491
|
5. **Killing pane without `/exit` first** — leaves partial writes, git locks
|