@hueyexe/opencode-ensemble 0.14.0 → 0.14.1

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 (3) hide show
  1. package/README.md +97 -62
  2. package/dist/index.js +1702 -765
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@hueyexe/opencode-ensemble.svg)](https://www.npmjs.com/package/@hueyexe/opencode-ensemble)
8
8
  [![npm downloads](https://img.shields.io/npm/dm/@hueyexe/opencode-ensemble.svg)](https://www.npmjs.com/package/@hueyexe/opencode-ensemble)
9
- [![tests](https://img.shields.io/badge/tests-558%20passing-brightgreen.svg)]()
9
+ [![tests](https://img.shields.io/badge/tests-561%20passing-brightgreen.svg)]()
10
10
  [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue.svg)]()
11
11
  [![OpenCode SDK](https://img.shields.io/badge/deps-OpenCode%20SDK%20only-blue.svg)]()
12
12
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
@@ -19,7 +19,7 @@ Plugin built on the public OpenCode SDK. No internal dependencies.
19
19
 
20
20
  ```json
21
21
  {
22
- "plugin": ["@hueyexe/opencode-ensemble@0.14.0"]
22
+ "plugin": ["@hueyexe/opencode-ensemble@0.14.1"]
23
23
  }
24
24
  ```
25
25
 
@@ -29,79 +29,114 @@ Add to your `opencode.json`, restart OpenCode, and ask it to do something that b
29
29
 
30
30
  You ask the agent to do something complex. It creates a team, spawns teammates, and they work in parallel. Each teammate runs in its own OpenCode session with a fresh context window.
31
31
 
32
- A real interaction:
32
+ A realistic development-team interaction:
33
33
 
34
34
  ```
35
- You: "Add input validation to all API endpoints and write tests for each one."
35
+ You: "Fix checkout idempotency so duplicate Stripe webhooks cannot create
36
+ duplicate orders. Add regression tests and review the final diff for risk."
36
37
 
37
38
  The lead agent:
38
- 1. Creates a team called "validation"
39
- 2. Adds tasks to the shared board, one per endpoint
40
- 3. Spawns 3 teammates:
41
- - alice: validate user endpoints (POST /users, PUT /users/:id)
42
- - bob: validate order endpoints (POST /orders, PUT /orders/:id)
43
- - carol: write integration tests for all validated endpoints
44
- 4. carol's tasks depend on alice and bob finishing first
39
+ 1. Creates a team called "checkout-idempotency".
40
+ 2. Adds independent tasks first and records the generated task IDs.
41
+ 3. Adds dependent QA and review tasks with `depends_on` using real returned IDs.
42
+ 4. Spawns a small team with explicit roles:
43
+ - scout: explore agent, worktree disabled, model openai/gpt-5.3-codex-spark
44
+ - api-dev: build agent, own worktree, model anthropic/claude-opus-4-7, plan_approval: true
45
+ - qa: build agent, own worktree, model anthropic/claude-sonnet-4-6
46
+ - reviewer: explore agent, worktree disabled, model openai/gpt-5.3-codex-spark
45
47
  ```
46
48
 
47
- Alice and bob work simultaneously. You see toast notifications as they progress:
48
-
49
- ```
50
- [toast] Teammate alice spawned (build)
51
- [toast] Teammate bob spawned (build)
52
- [toast] Teammate carol spawned (build)
49
+ The lead uses the task board to make sequencing visible. Record the returned task IDs before creating dependent tasks:
50
+
51
+ ```ts
52
+ team_tasks_add({
53
+ tasks: [
54
+ { content: "Map checkout webhook flow and identify idempotency risks", priority: "high" },
55
+ { content: "Implement duplicate-webhook idempotency guard", priority: "high" },
56
+ ],
57
+ })
58
+ // -> Added 2 tasks: task_abc123, task_def456
59
+
60
+ team_tasks_add({
61
+ tasks: [
62
+ { content: "Add regression tests for duplicate webhook delivery", priority: "high", depends_on: ["task_def456"] },
63
+ ],
64
+ })
65
+ // -> Added 1 task: task_ghi789
66
+
67
+ team_tasks_add({
68
+ tasks: [
69
+ { content: "Review final diff for order, payment, and retry risks", priority: "medium", depends_on: ["task_def456", "task_ghi789"] },
70
+ ],
71
+ })
72
+ // -> Added 1 task: task_jkl012
53
73
  ```
54
74
 
55
- Teammates talk to each other and to the lead:
56
-
57
- ```
58
- alice -> lead: "User validation done. Added zod schemas to POST /users and PUT /users/:id."
59
- bob -> lead: "Order validation done. Found an edge case in PUT /orders/:id, negative quantities were allowed."
60
- bob -> alice: "Did you handle email format validation? I want to match the pattern for order contact emails."
61
- alice -> bob: "Yes, using z.string().email(). See src/validators/user.ts line 12."
75
+ Then it spawns teammates one at a time:
76
+
77
+ ```ts
78
+ team_spawn({
79
+ name: "scout",
80
+ agent: "explore",
81
+ worktree: false,
82
+ model: "openai/gpt-5.3-codex-spark",
83
+ claim_task: "task_abc123",
84
+ prompt: "Trace the checkout webhook flow. Report the files, data model, existing tests, and the smallest safe implementation plan. Do not edit files.",
85
+ })
86
+
87
+ team_spawn({
88
+ name: "api-dev",
89
+ agent: "build",
90
+ model: "anthropic/claude-opus-4-7",
91
+ plan_approval: true,
92
+ claim_task: "task_def456",
93
+ prompt: "After scout reports, implement the idempotency guard. Keep the change narrow. Commit your work and send a task-result message.",
94
+ })
62
95
  ```
63
96
 
64
- When alice and bob finish, carol's blocked tasks unblock automatically. Carol starts writing tests using the validation schemas they created.
97
+ The same pattern assigns `qa` to regression tests and `reviewer` to final review. The reviewer stays read-only (`worktree: false`) so it can inspect merged changes without producing another branch.
65
98
 
66
- Check on things at any time:
99
+ Teammates coordinate without the lead polling:
67
100
 
68
101
  ```
69
- You: "How's the team doing?"
70
-
71
- Lead calls team_status:
72
- Team: validation (you are the lead)
73
- Members:
74
- alice [idle 2m, last msg: 1m ago] agent: build branch: ensemble-validation-alice
75
- bob [idle 1m, last msg: 30s ago] agent: build branch: ensemble-validation-bob
76
- carol [working 5m, last msg: 3m ago] agent: build branch: ensemble-validation-carol
77
- task: Write integration tests for validated endpoints
78
- Tasks: 5 total (3 completed, 1 in_progress, 1 pending)
102
+ scout -> lead: "Checkout flow is src/webhooks/stripe.ts -> createOrderFromPayment(). Existing tests are in test/checkout-webhook.test.ts. Risk: retries race before order insert commits."
103
+ api-dev -> lead: "Plan ready: add unique event_id insert before order creation, treat duplicate insert as success, add a transaction around order creation."
104
+ lead -> api-dev: approves plan
105
+ qa -> api-dev: "Which duplicate signal should tests assert: event_id conflict or existing order lookup?"
106
+ api-dev -> qa: "Assert duplicate event_id returns success and creates one order. See src/webhooks/stripe.ts."
79
107
  ```
80
108
 
81
- Want to see what carol is doing? The lead can switch your view to her session:
109
+ When work is done, the lead reviews and integrates deliberately:
82
110
 
83
111
  ```
84
- You: "Show me what carol is working on."
112
+ team_results({ from: "api-dev" })
113
+ team_shutdown({ member: "api-dev" })
114
+ team_merge({ member: "api-dev" })
115
+
116
+ team_results({ from: "qa" })
117
+ team_shutdown({ member: "qa" })
118
+ team_merge({ member: "qa" })
85
119
 
86
- Lead calls team_view({ member: "carol" })
87
- -> TUI switches to carol's session, showing her full chat log
88
- -> Use the session picker (ctrl+p) to go back to the lead
120
+ team_spawn({ name: "reviewer", agent: "explore", worktree: false, claim_task: "task_jkl012", prompt: "Review the merged diff for correctness, missed tests, and risky behavior. Do not edit files." })
89
121
  ```
90
122
 
91
- When everything is done, the lead shuts down teammates and cleans up. Worktree branches are automatically merged into your working directory as unstaged changes for review:
123
+ The lead runs the repository verification commands, summarizes the result, and only then cleans up the team. All merged teammate changes remain in your working directory as unstaged changes for review with `git diff`.
92
124
 
125
+ ## Agent Skill
126
+
127
+ Install the companion skill to teach your AI how to form useful Ensemble teams, write better teammate prompts, choose models, and avoid common coordination failures:
128
+
129
+ ```bash
130
+ npx skills@latest add hueyexe/opencode-ensemble --skill opencode-ensemble
93
131
  ```
94
- [toast] alice shut down
95
- [toast] bob shut down
96
- [toast] carol shut down
97
-
98
- Lead: "All validation and tests are complete. 5 endpoints validated,
99
- 12 test cases added. Team cleaned up.
100
- Merged 3 branch(es) into working directory (unstaged).
101
- Review changes with: git diff"
102
- ```
103
132
 
104
- All teammate changes are now in your working directory, unstaged, ready for you to review file-by-file with `git diff`.
133
+ The skill is useful when you want the agent to decide whether parallel work is appropriate, split work into independent slices, use `depends_on` correctly, or pick a safe mix of `explore` and `build` teammates.
134
+
135
+ Good team shapes:
136
+
137
+ - **Scout, builder, reviewer**: one read-only `explore` agent maps the code, one `build` agent changes it, one read-only `explore` agent reviews the diff.
138
+ - **Parallel slices**: two or three `build` agents own independent files or vertical slices, then one reviewer checks the combined result.
139
+ - **Risky change**: use `plan_approval: true` on the implementing teammate, then approve or reject the plan through `team_message` before edits begin.
105
140
 
106
141
  ## Dashboard
107
142
 
@@ -140,7 +175,7 @@ Add to your OpenCode config with a pinned version. Project-level or global.
140
175
 
141
176
  ```json
142
177
  {
143
- "plugin": ["@hueyexe/opencode-ensemble@0.14.0"]
178
+ "plugin": ["@hueyexe/opencode-ensemble@0.14.1"]
144
179
  }
145
180
  ```
146
181
 
@@ -148,7 +183,7 @@ Add to your OpenCode config with a pinned version. Project-level or global.
148
183
 
149
184
  ```json
150
185
  {
151
- "plugin": ["@hueyexe/opencode-ensemble@0.14.0"]
186
+ "plugin": ["@hueyexe/opencode-ensemble@0.14.1"]
152
187
  }
153
188
  ```
154
189
 
@@ -278,8 +313,8 @@ Control which AI models your agents use. By default, agents use whatever model O
278
313
  ```json
279
314
  {
280
315
  "modelsByAgent": {
281
- "build": "anthropic/claude-opus-4-6",
282
- "explore": "opencode/gpt-5-nano"
316
+ "build": "anthropic/claude-opus-4-7",
317
+ "explore": "openai/gpt-5.3-codex-spark"
283
318
  }
284
319
  }
285
320
  ```
@@ -287,7 +322,7 @@ Control which AI models your agents use. By default, agents use whatever model O
287
322
  **Rotate through a pool for diverse perspectives:**
288
323
  ```json
289
324
  {
290
- "modelPool": ["anthropic/claude-opus-4-6", "anthropic/claude-sonnet-4-6", "openai/gpt-5.4"],
325
+ "modelPool": ["anthropic/claude-opus-4-7", "anthropic/claude-sonnet-4-6", "openai/gpt-5.4"],
291
326
  "modelAssignment": "rotate"
292
327
  }
293
328
  ```
@@ -296,7 +331,7 @@ Control which AI models your agents use. By default, agents use whatever model O
296
331
  ```json
297
332
  {
298
333
  "promptForModels": true,
299
- "modelPool": ["anthropic/claude-opus-4-6", "opencode/big-pickle", "opencode/gpt-5-nano"]
334
+ "modelPool": ["anthropic/claude-opus-4-7", "opencode/big-pickle", "openai/gpt-5.3-codex-spark"]
300
335
  }
301
336
  ```
302
337
 
@@ -311,7 +346,7 @@ When `promptForModels` is true, the lead uses the question tool to ask which mod
311
346
 
312
347
  The lead can always override by passing `model` directly on `team_spawn`, regardless of config.
313
348
 
314
- Model IDs use the `provider/model` format from [models.dev](https://models.dev) (e.g. `anthropic/claude-opus-4-6`, `openai/gpt-5.4`). For OpenCode Zen models, use the `opencode/` prefix (e.g. `opencode/big-pickle`).
349
+ Model IDs use the `provider/model` format from [models.dev](https://models.dev) (e.g. `anthropic/claude-opus-4-7`, `openai/gpt-5.4`). For OpenCode Zen models, use the `opencode/` prefix (e.g. `opencode/big-pickle`).
315
350
 
316
351
  ## Configuration
317
352
 
@@ -331,7 +366,7 @@ Configure via JSON files, environment variables, or both. Project config overrid
331
366
  "rateLimitCapacity": 10,
332
367
  "dashboardPort": 4747,
333
368
  "defaultModel": "anthropic/claude-sonnet-4-6",
334
- "modelPool": ["anthropic/claude-opus-4-6", "anthropic/claude-sonnet-4-6", "openai/gpt-5.4"],
369
+ "modelPool": ["anthropic/claude-opus-4-7", "anthropic/claude-sonnet-4-6", "openai/gpt-5.4"],
335
370
  "modelsByAgent": {},
336
371
  "modelAssignment": "default",
337
372
  "promptForModels": false
@@ -353,7 +388,7 @@ All fields are optional. Missing fields use defaults.
353
388
  | `dashboardPort` | `4747` | Dashboard server port. `0` disables. |
354
389
  | `defaultModel` | `""` | Default model for all agents (e.g. `"anthropic/claude-sonnet-4-6"`). Empty = OpenCode's default. |
355
390
  | `modelPool` | `[]` | List of models for rotation/random assignment. |
356
- | `modelsByAgent` | `{}` | Map agent type to model (e.g. `{"build": "anthropic/claude-opus-4-6"}`). |
391
+ | `modelsByAgent` | `{}` | Map agent type to model (e.g. `{"build": "anthropic/claude-opus-4-7"}`). |
357
392
  | `modelAssignment` | `"default"` | How to assign models: `"default"`, `"rotate"`, or `"random"`. |
358
393
  | `promptForModels` | `false` | Lead asks user about model preferences before spawning. |
359
394
 
@@ -412,7 +447,7 @@ Same coordination model (shared tasks, peer messaging, lead coordination) with s
412
447
  ```bash
413
448
  bun install
414
449
  bun run typecheck
415
- bun test # 558 tests
450
+ bun test # 561 tests
416
451
  bun run build
417
452
  ```
418
453