opencode-swarm-plugin 0.29.0 → 0.30.2

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 (42) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +94 -0
  3. package/README.md +3 -6
  4. package/bin/swarm.test.ts +163 -0
  5. package/bin/swarm.ts +304 -72
  6. package/dist/hive.d.ts.map +1 -1
  7. package/dist/index.d.ts +94 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +18825 -3469
  10. package/dist/memory-tools.d.ts +209 -0
  11. package/dist/memory-tools.d.ts.map +1 -0
  12. package/dist/memory.d.ts +124 -0
  13. package/dist/memory.d.ts.map +1 -0
  14. package/dist/plugin.js +18775 -3430
  15. package/dist/schemas/index.d.ts +7 -0
  16. package/dist/schemas/index.d.ts.map +1 -1
  17. package/dist/schemas/worker-handoff.d.ts +78 -0
  18. package/dist/schemas/worker-handoff.d.ts.map +1 -0
  19. package/dist/swarm-orchestrate.d.ts +50 -0
  20. package/dist/swarm-orchestrate.d.ts.map +1 -1
  21. package/dist/swarm-prompts.d.ts +1 -1
  22. package/dist/swarm-prompts.d.ts.map +1 -1
  23. package/dist/swarm-review.d.ts +4 -0
  24. package/dist/swarm-review.d.ts.map +1 -1
  25. package/docs/planning/ADR-008-worker-handoff-protocol.md +293 -0
  26. package/examples/plugin-wrapper-template.ts +157 -28
  27. package/package.json +3 -1
  28. package/src/hive.integration.test.ts +114 -0
  29. package/src/hive.ts +33 -22
  30. package/src/index.ts +41 -8
  31. package/src/memory-tools.test.ts +111 -0
  32. package/src/memory-tools.ts +273 -0
  33. package/src/memory.integration.test.ts +266 -0
  34. package/src/memory.test.ts +334 -0
  35. package/src/memory.ts +441 -0
  36. package/src/schemas/index.ts +18 -0
  37. package/src/schemas/worker-handoff.test.ts +271 -0
  38. package/src/schemas/worker-handoff.ts +131 -0
  39. package/src/swarm-orchestrate.ts +262 -24
  40. package/src/swarm-prompts.ts +48 -5
  41. package/src/swarm-review.ts +7 -0
  42. package/src/swarm.integration.test.ts +386 -9
@@ -1,9 +1,9 @@
1
1
  $ bun build ./src/index.ts --outdir ./dist --target node --external @electric-sql/pglite --external swarm-mail && bun build ./src/plugin.ts --outfile ./dist/plugin.js --target node --external @electric-sql/pglite --external swarm-mail && tsc
2
- Bundled 200 modules in 35ms
2
+ Bundled 811 modules in 121ms
3
3
 
4
- index.js 1.20 MB (entry point)
4
+ index.js 1.71 MB (entry point)
5
5
 
6
- Bundled 201 modules in 34ms
6
+ Bundled 812 modules in 142ms
7
7
 
8
- plugin.js 1.16 MB (entry point)
8
+ plugin.js 1.67 MB (entry point)
9
9
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,99 @@
1
1
  # opencode-swarm-plugin
2
2
 
3
+ ## 0.30.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`5858148`](https://github.com/joelhooks/swarm-tools/commit/5858148d5785393c0a6993a2595fba275f305707) Thanks [@joelhooks](https://github.com/joelhooks)! - chore: trigger publish workflow
8
+
9
+ ## 0.30.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [`57d5600`](https://github.com/joelhooks/swarm-tools/commit/57d5600a53e148ce1d1da48b3b5a8723a5552e04) Thanks [@joelhooks](https://github.com/joelhooks)! - ## 🚦 Review Gate UX Fix + Verbose Setup
14
+
15
+ > _"A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."_
16
+ > — Douglas Adams, _Mostly Harmless_
17
+
18
+ Two UX improvements that make swarm coordination feel less like shouting into the void.
19
+
20
+ ### What Changed
21
+
22
+ **Review Gate Response Fix:**
23
+
24
+ - `swarm_complete` no longer returns `success: false` when code review is pending
25
+ - Now returns `success: true` with `status: "pending_review"` or `status: "needs_changes"`
26
+ - **Why it matters**: The old format made review checkpoints look like errors. Agents would retry unnecessarily or report failures when the workflow was actually working as designed. Review gates are a feature, not a bug.
27
+
28
+ **Setup Command Verbosity:**
29
+
30
+ - Added `p.log.step()` and `p.log.success()` throughout swarm setup
31
+ - Users can now see exactly what's happening: dependency checks, git init, swarm-mail connection
32
+ - **Why it matters**: Silent setup commands feel broken. Explicit progress logs build trust and make debugging easier when setup actually does fail.
33
+
34
+ ### Why It Matters
35
+
36
+ **For Agents:**
37
+
38
+ - No more false-negative responses from review gates
39
+ - Clear workflow state (pending vs. needs changes vs. complete)
40
+ - Reduced retry loops and error noise
41
+
42
+ **For Users:**
43
+
44
+ - Setup command shows its work (not a black box)
45
+ - Review process is transparent in logs
46
+ - Easier to diagnose when things actually break
47
+
48
+ **Backward compatible:** Yes. Existing agents checking for `success: false` will still work, they just won't see false errors anymore.
49
+
50
+ ## 0.30.0
51
+
52
+ ### Minor Changes
53
+
54
+ - [`f3917ad`](https://github.com/joelhooks/swarm-tools/commit/f3917ad911d3c716a2470a01c66bce3500f644f4) Thanks [@joelhooks](https://github.com/joelhooks)! - ## 🐝 The Great bd CLI Purge
55
+
56
+ The `bd` CLI is officially dead. Long live HiveAdapter!
57
+
58
+ **What changed:**
59
+
60
+ ### `swarm init` Command Rewritten
61
+
62
+ - No longer shells out to `bd init` or `bd create`
63
+ - Uses `ensureHiveDirectory()` and `getHiveAdapter()` directly
64
+ - Supports `.beads` → `.hive` migration with user prompts
65
+ - Creates cells via HiveAdapter, not CLI
66
+
67
+ ### Auto-sync Removed from `index.ts`
68
+
69
+ - Removed `void $\`bd sync\`.quiet().nothrow()`after`hive_close`
70
+ - Users should call `hive_sync` explicitly at session end
71
+ - This was a fire-and-forget that could race with other operations
72
+
73
+ ### Plugin Template Updated
74
+
75
+ - `detectSwarm()` now has confidence levels (HIGH/MEDIUM/LOW/NONE)
76
+ - Added `SWARM_DETECTION_FALLBACK` for uncertain cases
77
+ - Compaction hook injects context based on confidence:
78
+ - HIGH/MEDIUM → Full swarm context
79
+ - LOW → Fallback detection prompt
80
+ - NONE → No injection
81
+
82
+ ### Error Handling Fixed
83
+
84
+ - `execTool()` now handles both string and object error formats
85
+ - Fixes "Tool execution failed" generic error from `swarm_complete`
86
+ - Actual error messages now propagate to the agent
87
+
88
+ **Why it matters:**
89
+
90
+ - No external CLI dependency for core functionality
91
+ - HiveAdapter is type-safe and testable
92
+ - Plugin works in environments without `bd` installed
93
+ - Better error messages for debugging
94
+
95
+ **Migration:** Run `swarm setup` to update your deployed plugin.
96
+
3
97
  ## 0.29.0
4
98
 
5
99
  ### Minor Changes
package/README.md CHANGED
@@ -220,7 +220,8 @@ These tools significantly enhance the swarm experience:
220
220
  |------|---------|---------|
221
221
  | [CASS](https://github.com/Dicklesworthstone/coding_agent_session_search) | Historical context - queries past sessions for similar decompositions | See below |
222
222
  | [UBS](https://github.com/Dicklesworthstone/ultimate_bug_scanner) | Bug scanning - runs on subtask completion to catch issues | See below |
223
- | [semantic-memory](https://github.com/joelhooks/semantic-memory) | Learning persistence - stores patterns across sessions | Requires Ollama (see above) |
223
+
224
+ > **Note:** Semantic memory is now embedded in the plugin. No separate installation needed - just install Ollama for vector embeddings.
224
225
 
225
226
  #### Installing CASS
226
227
 
@@ -243,15 +244,11 @@ cd ultimate_bug_scanner
243
244
  pip install -e .
244
245
  ```
245
246
 
246
- #### Installing semantic-memory
247
-
248
- The `semantic-memory_check` tool verifies Ollama is ready (see installation steps above).
249
-
250
247
  **Why install these?**
251
248
 
252
249
  - **CASS** - When you run `/swarm "Add OAuth"`, the coordinator queries CASS for similar past tasks. Without it, decomposition is based only on the current task description.
253
250
  - **UBS** - Every `swarm_complete` runs UBS to scan for bugs. Without it, you lose automatic bug detection.
254
- - **semantic-memory** - Pattern maturity and anti-pattern detection persist across sessions. Without it, learning resets each session.
251
+ - **Ollama** - Enables vector similarity search for semantic memory. Without it, memory falls back to full-text search (still functional, less semantic).
255
252
 
256
253
  Run `swarm doctor` to check which dependencies are installed.
257
254
 
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Tests for swarm CLI file operation helpers
4
+ *
5
+ * These tests verify the verbose output helpers used in `swarm setup`:
6
+ * - writeFileWithStatus: logs created/updated/unchanged status
7
+ * - mkdirWithStatus: logs directory creation
8
+ * - rmWithStatus: logs file removal
9
+ */
10
+ import { describe, test, expect, beforeEach, afterEach } from "bun:test";
11
+ import { mkdirSync, rmSync, writeFileSync, existsSync, readFileSync } from "fs";
12
+ import { join } from "path";
13
+ import { tmpdir } from "os";
14
+
15
+ type FileStatus = "created" | "updated" | "unchanged";
16
+
17
+ /**
18
+ * Mock logger for testing (matches @clack/prompts API)
19
+ */
20
+ class MockLogger {
21
+ logs: Array<{ type: string; message: string }> = [];
22
+
23
+ success(msg: string) {
24
+ this.logs.push({ type: "success", message: msg });
25
+ }
26
+
27
+ message(msg: string) {
28
+ this.logs.push({ type: "message", message: msg });
29
+ }
30
+
31
+ reset() {
32
+ this.logs = [];
33
+ }
34
+ }
35
+
36
+ describe("File operation helpers", () => {
37
+ let testDir: string;
38
+ let logger: MockLogger;
39
+
40
+ beforeEach(() => {
41
+ testDir = join(tmpdir(), `swarm-test-${Date.now()}`);
42
+ mkdirSync(testDir, { recursive: true });
43
+ logger = new MockLogger();
44
+ });
45
+
46
+ afterEach(() => {
47
+ if (existsSync(testDir)) {
48
+ rmSync(testDir, { recursive: true, force: true });
49
+ }
50
+ });
51
+
52
+ describe("writeFileWithStatus", () => {
53
+ // Helper that mimics the implementation
54
+ function writeFileWithStatus(path: string, content: string, label: string): FileStatus {
55
+ const exists = existsSync(path);
56
+
57
+ if (exists) {
58
+ const current = readFileSync(path, "utf-8");
59
+ if (current === content) {
60
+ logger.message(` ${label}: ${path} (unchanged)`);
61
+ return "unchanged";
62
+ }
63
+ }
64
+
65
+ writeFileSync(path, content);
66
+ const status: FileStatus = exists ? "updated" : "created";
67
+ logger.success(`${label}: ${path} (${status})`);
68
+ return status;
69
+ }
70
+
71
+ test("returns 'created' for new file", () => {
72
+ const filePath = join(testDir, "new.txt");
73
+ const result = writeFileWithStatus(filePath, "content", "Test");
74
+
75
+ expect(result).toBe("created");
76
+ expect(logger.logs[0].type).toBe("success");
77
+ expect(logger.logs[0].message).toContain("(created)");
78
+ expect(existsSync(filePath)).toBe(true);
79
+ });
80
+
81
+ test("returns 'unchanged' if content is same", () => {
82
+ const filePath = join(testDir, "existing.txt");
83
+ writeFileSync(filePath, "same content");
84
+
85
+ const result = writeFileWithStatus(filePath, "same content", "Test");
86
+
87
+ expect(result).toBe("unchanged");
88
+ expect(logger.logs[0].type).toBe("message");
89
+ expect(logger.logs[0].message).toContain("(unchanged)");
90
+ });
91
+
92
+ test("returns 'updated' if content differs", () => {
93
+ const filePath = join(testDir, "existing.txt");
94
+ writeFileSync(filePath, "old content");
95
+
96
+ const result = writeFileWithStatus(filePath, "new content", "Test");
97
+
98
+ expect(result).toBe("updated");
99
+ expect(logger.logs[0].type).toBe("success");
100
+ expect(logger.logs[0].message).toContain("(updated)");
101
+ expect(readFileSync(filePath, "utf-8")).toBe("new content");
102
+ });
103
+ });
104
+
105
+ describe("mkdirWithStatus", () => {
106
+ function mkdirWithStatus(path: string): boolean {
107
+ if (!existsSync(path)) {
108
+ mkdirSync(path, { recursive: true });
109
+ logger.message(` Created directory: ${path}`);
110
+ return true;
111
+ }
112
+ return false;
113
+ }
114
+
115
+ test("creates directory and logs when it doesn't exist", () => {
116
+ const dirPath = join(testDir, "newdir");
117
+ const result = mkdirWithStatus(dirPath);
118
+
119
+ expect(result).toBe(true);
120
+ expect(existsSync(dirPath)).toBe(true);
121
+ expect(logger.logs[0].type).toBe("message");
122
+ expect(logger.logs[0].message).toContain("Created directory");
123
+ });
124
+
125
+ test("returns false when directory already exists", () => {
126
+ const dirPath = join(testDir, "existing");
127
+ mkdirSync(dirPath);
128
+
129
+ const result = mkdirWithStatus(dirPath);
130
+
131
+ expect(result).toBe(false);
132
+ expect(logger.logs.length).toBe(0);
133
+ });
134
+ });
135
+
136
+ describe("rmWithStatus", () => {
137
+ function rmWithStatus(path: string, label: string): void {
138
+ if (existsSync(path)) {
139
+ rmSync(path);
140
+ logger.message(` Removed ${label}: ${path}`);
141
+ }
142
+ }
143
+
144
+ test("removes file and logs when it exists", () => {
145
+ const filePath = join(testDir, "todelete.txt");
146
+ writeFileSync(filePath, "content");
147
+
148
+ rmWithStatus(filePath, "test file");
149
+
150
+ expect(existsSync(filePath)).toBe(false);
151
+ expect(logger.logs[0].type).toBe("message");
152
+ expect(logger.logs[0].message).toContain("Removed test file");
153
+ });
154
+
155
+ test("does nothing when file doesn't exist", () => {
156
+ const filePath = join(testDir, "nonexistent.txt");
157
+
158
+ rmWithStatus(filePath, "test file");
159
+
160
+ expect(logger.logs.length).toBe(0);
161
+ });
162
+ });
163
+ });