opencode-swarm-plugin 0.36.0 → 0.37.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.
Files changed (54) hide show
  1. package/.hive/issues.jsonl +16 -4
  2. package/.hive/memories.jsonl +274 -1
  3. package/.turbo/turbo-build.log +4 -4
  4. package/.turbo/turbo-test.log +318 -318
  5. package/CHANGELOG.md +113 -0
  6. package/bin/swarm.test.ts +106 -0
  7. package/bin/swarm.ts +413 -179
  8. package/dist/compaction-hook.d.ts +54 -4
  9. package/dist/compaction-hook.d.ts.map +1 -1
  10. package/dist/eval-capture.d.ts +122 -17
  11. package/dist/eval-capture.d.ts.map +1 -1
  12. package/dist/index.d.ts +1 -7
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1278 -619
  15. package/dist/planning-guardrails.d.ts +121 -0
  16. package/dist/planning-guardrails.d.ts.map +1 -1
  17. package/dist/plugin.d.ts +9 -9
  18. package/dist/plugin.d.ts.map +1 -1
  19. package/dist/plugin.js +1283 -329
  20. package/dist/schemas/task.d.ts +0 -1
  21. package/dist/schemas/task.d.ts.map +1 -1
  22. package/dist/swarm-decompose.d.ts +0 -8
  23. package/dist/swarm-decompose.d.ts.map +1 -1
  24. package/dist/swarm-orchestrate.d.ts.map +1 -1
  25. package/dist/swarm-prompts.d.ts +0 -4
  26. package/dist/swarm-prompts.d.ts.map +1 -1
  27. package/dist/swarm-review.d.ts.map +1 -1
  28. package/dist/swarm.d.ts +0 -6
  29. package/dist/swarm.d.ts.map +1 -1
  30. package/evals/README.md +38 -0
  31. package/evals/coordinator-session.eval.ts +154 -0
  32. package/evals/fixtures/coordinator-sessions.ts +328 -0
  33. package/evals/lib/data-loader.ts +69 -0
  34. package/evals/scorers/coordinator-discipline.evalite-test.ts +536 -0
  35. package/evals/scorers/coordinator-discipline.ts +315 -0
  36. package/evals/scorers/index.ts +12 -0
  37. package/examples/plugin-wrapper-template.ts +303 -4
  38. package/package.json +2 -2
  39. package/src/compaction-hook.test.ts +8 -1
  40. package/src/compaction-hook.ts +31 -21
  41. package/src/eval-capture.test.ts +390 -0
  42. package/src/eval-capture.ts +163 -4
  43. package/src/hive.integration.test.ts +148 -0
  44. package/src/hive.ts +89 -0
  45. package/src/index.ts +68 -1
  46. package/src/planning-guardrails.test.ts +387 -2
  47. package/src/planning-guardrails.ts +289 -0
  48. package/src/plugin.ts +10 -10
  49. package/src/swarm-decompose.test.ts +195 -0
  50. package/src/swarm-decompose.ts +72 -1
  51. package/src/swarm-orchestrate.ts +44 -0
  52. package/src/swarm-prompts.ts +20 -0
  53. package/src/swarm-review.integration.test.ts +24 -29
  54. package/src/swarm-review.ts +41 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,118 @@
1
1
  # opencode-swarm-plugin
2
2
 
3
+ ## 0.37.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`66b5795`](https://github.com/joelhooks/swarm-tools/commit/66b57951e2c114702c663b98829d5f7626607a16) Thanks [@joelhooks](https://github.com/joelhooks)! - ## 🐝 `swarm cells` - Query Your Hive Like a Pro
8
+
9
+ New CLI command AND plugin tool for querying cells directly from the database.
10
+
11
+ ### CLI: `swarm cells`
12
+
13
+ ```bash
14
+ swarm cells # List all cells (table format)
15
+ swarm cells --status open # Filter by status
16
+ swarm cells --type bug # Filter by type
17
+ swarm cells --ready # Next unblocked cell
18
+ swarm cells mjkmd # Partial ID lookup
19
+ swarm cells --json # Raw JSON for scripting
20
+ ```
21
+
22
+ **Replaces:** The awkward `swarm tool hive_query --json '{"status":"open"}'` pattern.
23
+
24
+ ### Plugin Tool: `hive_cells`
25
+
26
+ ```typescript
27
+ // Agents can now query cells directly
28
+ hive_cells({ status: "open", type: "task" });
29
+ hive_cells({ id: "mjkmd" }); // Partial ID works!
30
+ hive_cells({ ready: true }); // Next unblocked
31
+ ```
32
+
33
+ **Why this matters:**
34
+
35
+ - Reads from DATABASE (fast, indexed) not JSONL files
36
+ - Partial ID resolution built-in
37
+ - Consistent JSON array output
38
+ - Rich descriptions encourage agentic use
39
+
40
+ ### Also Fixed
41
+
42
+ - `swarm_review_feedback` tests updated for coordinator-driven retry architecture
43
+ - 425 tests passing
44
+
45
+ ## 0.36.1
46
+
47
+ ### Patch Changes
48
+
49
+ - [`9c1f3f3`](https://github.com/joelhooks/swarm-tools/commit/9c1f3f3e7204f02c133c4a036fa34e83d8376a8c) Thanks [@joelhooks](https://github.com/joelhooks)! - ## 🐝 Coordinator Discipline: Prohibition-First Enforcement
50
+
51
+ Coordinators kept "just doing it themselves" after compaction. Now they can't.
52
+
53
+ **The Problem:**
54
+ After context compaction, coordinators would ignore their own instructions to "spawn workers for remaining subtasks" and edit files directly. The compaction context was narrative ("do this") rather than prescriptive ("NEVER do that").
55
+
56
+ **The Fix:**
57
+
58
+ ### 1. Prohibition-First Compaction Context
59
+
60
+ The `SWARM_COMPACTION_CONTEXT` now leads with explicit anti-patterns:
61
+
62
+ ```markdown
63
+ ### ⛔ NEVER DO THESE (Coordinator Anti-Patterns)
64
+
65
+ - ❌ **NEVER** use `edit` or `write` tools - SPAWN A WORKER
66
+ - ❌ **NEVER** run tests with `bash` - SPAWN A WORKER
67
+ - ❌ **NEVER** implement features yourself - SPAWN A WORKER
68
+ - ❌ **NEVER** "just do it myself to save time" - NO. SPAWN A WORKER.
69
+ ```
70
+
71
+ ### 2. Runtime Violation Detection
72
+
73
+ `detectCoordinatorViolation()` is now wired up in `tool.execute.before`:
74
+
75
+ - Detects when coordinators call `edit`, `write`, or test commands
76
+ - Emits warnings to help coordinators self-correct
77
+ - Captures VIOLATION events for post-hoc analysis
78
+
79
+ ### 3. Coordinator Context Tracking
80
+
81
+ New functions track when we're in coordinator mode:
82
+
83
+ - `setCoordinatorContext()` - Activated when `hive_create_epic` or `swarm_decompose` is called
84
+ - `isInCoordinatorContext()` - Checks if we're currently coordinating
85
+ - `clearCoordinatorContext()` - Cleared when epic is closed
86
+
87
+ **Why This Matters:**
88
+
89
+ Coordinators that do implementation work burn context, create conflicts, and defeat the purpose of swarm coordination. This fix makes the anti-pattern visible and provides guardrails to prevent it.
90
+
91
+ **Validation:**
92
+
93
+ - Check `~/.config/swarm-tools/sessions/` for VIOLATION events
94
+ - Run `coordinator-behavior.eval.ts` to score coordinator discipline
95
+
96
+ - [`4c23c7a`](https://github.com/joelhooks/swarm-tools/commit/4c23c7a31013bc6537d83a9294b51540056cde93) Thanks [@joelhooks](https://github.com/joelhooks)! - ## Fix Double Hook Registration
97
+
98
+ The compaction hook was firing twice per compaction event because OpenCode's plugin loader
99
+ calls ALL exports as plugin functions. We were exporting `SwarmPlugin` as both:
100
+
101
+ 1. Named export: `export const SwarmPlugin`
102
+ 2. Default export: `export default SwarmPlugin`
103
+
104
+ This caused the plugin to register twice, doubling all hook invocations.
105
+
106
+ **Fix:** Changed to default-only export pattern:
107
+
108
+ - `src/index.ts`: `const SwarmPlugin` (no export keyword)
109
+ - `src/plugin.ts`: `export default SwarmPlugin` (no named re-export)
110
+
111
+ **Impact:** Compaction hooks now fire once. LLM calls during compaction reduced by 50%.
112
+
113
+ - Updated dependencies [[`e0c422d`](https://github.com/joelhooks/swarm-tools/commit/e0c422de3f5e15c117cc0cc655c0b03242245be4), [`43c8c93`](https://github.com/joelhooks/swarm-tools/commit/43c8c93ef90b2f04ce59317192334f69d7c4204e)]:
114
+ - swarm-mail@1.5.1
115
+
3
116
  ## 0.36.0
4
117
 
5
118
  ### Minor Changes
package/bin/swarm.test.ts CHANGED
@@ -197,6 +197,112 @@ READ-ONLY research agent. Never modifies code - only gathers intel and stores fi
197
197
  // Log Command Tests (TDD)
198
198
  // ============================================================================
199
199
 
200
+ // ============================================================================
201
+ // Cells Command Tests (TDD)
202
+ // ============================================================================
203
+
204
+ /**
205
+ * Format cells as table output
206
+ */
207
+ function formatCellsTable(cells: Array<{
208
+ id: string;
209
+ title: string;
210
+ status: string;
211
+ priority: number;
212
+ }>): string {
213
+ if (cells.length === 0) {
214
+ return "No cells found";
215
+ }
216
+
217
+ const rows = cells.map(c => ({
218
+ id: c.id,
219
+ title: c.title.length > 50 ? c.title.slice(0, 47) + "..." : c.title,
220
+ status: c.status,
221
+ priority: String(c.priority),
222
+ }));
223
+
224
+ // Calculate column widths
225
+ const widths = {
226
+ id: Math.max(2, ...rows.map(r => r.id.length)),
227
+ title: Math.max(5, ...rows.map(r => r.title.length)),
228
+ status: Math.max(6, ...rows.map(r => r.status.length)),
229
+ priority: Math.max(8, ...rows.map(r => r.priority.length)),
230
+ };
231
+
232
+ // Build header
233
+ const header = [
234
+ "ID".padEnd(widths.id),
235
+ "TITLE".padEnd(widths.title),
236
+ "STATUS".padEnd(widths.status),
237
+ "PRIORITY".padEnd(widths.priority),
238
+ ].join(" ");
239
+
240
+ const separator = "-".repeat(header.length);
241
+
242
+ // Build rows
243
+ const bodyRows = rows.map(r =>
244
+ [
245
+ r.id.padEnd(widths.id),
246
+ r.title.padEnd(widths.title),
247
+ r.status.padEnd(widths.status),
248
+ r.priority.padEnd(widths.priority),
249
+ ].join(" ")
250
+ );
251
+
252
+ return [header, separator, ...bodyRows].join("\n");
253
+ }
254
+
255
+ describe("Cells command", () => {
256
+ describe("formatCellsTable", () => {
257
+ test("formats cells as table with id, title, status, priority", () => {
258
+ const cells = [
259
+ {
260
+ id: "test-abc123-xyz",
261
+ title: "Fix bug",
262
+ status: "open",
263
+ priority: 0,
264
+ type: "bug",
265
+ created_at: 1234567890,
266
+ updated_at: 1234567890,
267
+ },
268
+ {
269
+ id: "test-def456-abc",
270
+ title: "Add feature",
271
+ status: "in_progress",
272
+ priority: 2,
273
+ type: "feature",
274
+ created_at: 1234567890,
275
+ updated_at: 1234567890,
276
+ },
277
+ ];
278
+
279
+ const table = formatCellsTable(cells);
280
+
281
+ // Should contain headers
282
+ expect(table).toContain("ID");
283
+ expect(table).toContain("TITLE");
284
+ expect(table).toContain("STATUS");
285
+ expect(table).toContain("PRIORITY");
286
+
287
+ // Should contain cell data
288
+ expect(table).toContain("test-abc123-xyz");
289
+ expect(table).toContain("Fix bug");
290
+ expect(table).toContain("open");
291
+ expect(table).toContain("0");
292
+
293
+ expect(table).toContain("test-def456-abc");
294
+ expect(table).toContain("Add feature");
295
+ expect(table).toContain("in_progress");
296
+ expect(table).toContain("2");
297
+ });
298
+
299
+ test("returns 'No cells found' for empty array", () => {
300
+ const table = formatCellsTable([]);
301
+ expect(table).toBe("No cells found");
302
+ });
303
+ });
304
+ });
305
+
200
306
  describe("Log command helpers", () => {
201
307
  let testDir: string;
202
308