opencode-swarm-plugin 0.30.5 → 0.30.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # opencode-swarm-plugin
2
2
 
3
+ ## 0.30.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [`32a2885`](https://github.com/joelhooks/swarm-tools/commit/32a2885115cc3e574e86d8e492f60ee189627488) Thanks [@joelhooks](https://github.com/joelhooks)! - chore: verify CI publish flow works
8
+
3
9
  ## 0.30.5
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm-plugin",
3
- "version": "0.30.5",
3
+ "version": "0.30.6",
4
4
  "description": "Multi-agent swarm coordination for OpenCode with learning capabilities, beads integration, and Agent Mail",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Tests for swarm-prompts.ts
3
+ *
4
+ * Validates that prompt templates contain required sections and emphasis
5
+ * for memory usage, coordination, and TDD workflow.
6
+ */
7
+
8
+ import { describe, expect, test } from "bun:test";
9
+ import {
10
+ formatSubtaskPromptV2,
11
+ SUBTASK_PROMPT_V2,
12
+ } from "./swarm-prompts";
13
+
14
+ describe("SUBTASK_PROMPT_V2", () => {
15
+ describe("memory query emphasis", () => {
16
+ test("Step 2 is semantic-memory_find and marked MANDATORY", () => {
17
+ expect(SUBTASK_PROMPT_V2).toContain("### Step 2:");
18
+ expect(SUBTASK_PROMPT_V2).toContain("semantic-memory_find");
19
+ // Must have MANDATORY in the step header
20
+ expect(SUBTASK_PROMPT_V2).toMatch(/### Step 2:.*MANDATORY/i);
21
+ });
22
+
23
+ test("memory query step has visual emphasis (emoji or caps)", () => {
24
+ // Should have emoji or CRITICAL/ALWAYS in caps
25
+ const step2Match = SUBTASK_PROMPT_V2.match(/### Step 2:[\s\S]*?### Step 3:/);
26
+ expect(step2Match).not.toBeNull();
27
+ if (!step2Match) return;
28
+ const step2Content = step2Match[0];
29
+
30
+ // Must have at least one of: emoji, CRITICAL, ALWAYS, MANDATORY
31
+ const hasEmphasis =
32
+ /🧠|⚠️|CRITICAL|ALWAYS|MANDATORY/.test(step2Content);
33
+ expect(hasEmphasis).toBe(true);
34
+ });
35
+
36
+ test("memory query step includes query examples by task type", () => {
37
+ const step2Match = SUBTASK_PROMPT_V2.match(/### Step 2:[\s\S]*?### Step 3:/);
38
+ expect(step2Match).not.toBeNull();
39
+ if (!step2Match) return;
40
+ const step2Content = step2Match[0];
41
+
42
+ // Should have examples for different task types
43
+ expect(step2Content).toContain("Bug fix");
44
+ expect(step2Content).toContain("New feature");
45
+ expect(step2Content).toContain("Refactor");
46
+ });
47
+
48
+ test("memory query step explains WHY it's mandatory", () => {
49
+ const step2Match = SUBTASK_PROMPT_V2.match(/### Step 2:[\s\S]*?### Step 3:/);
50
+ expect(step2Match).not.toBeNull();
51
+ if (!step2Match) return;
52
+ const step2Content = step2Match[0];
53
+
54
+ // Should explain consequences of skipping
55
+ expect(step2Content).toMatch(/skip|waste|repeat|already.solved/i);
56
+ });
57
+ });
58
+
59
+ describe("memory storage emphasis", () => {
60
+ test("has a dedicated section for storing learnings", () => {
61
+ // Should have a prominent section about storing memories
62
+ expect(SUBTASK_PROMPT_V2).toMatch(/##.*STORE.*LEARNING|### Step.*Store.*Learning/i);
63
+ });
64
+
65
+ test("storage section lists triggers for when to store", () => {
66
+ // Should mention triggers: bugs, gotchas, patterns, failed approaches
67
+ expect(SUBTASK_PROMPT_V2).toContain("bug");
68
+ expect(SUBTASK_PROMPT_V2).toMatch(/gotcha|quirk|workaround/i);
69
+ expect(SUBTASK_PROMPT_V2).toMatch(/pattern|domain/i);
70
+ });
71
+
72
+ test("storage section emphasizes WHY not just WHAT", () => {
73
+ expect(SUBTASK_PROMPT_V2).toMatch(/WHY.*not.*WHAT|why.*matters/i);
74
+ });
75
+
76
+ test("storage section warns against generic knowledge", () => {
77
+ expect(SUBTASK_PROMPT_V2).toMatch(/don't store.*generic|generic knowledge/i);
78
+ });
79
+ });
80
+
81
+ describe("checklist order", () => {
82
+ test("Step 1 is swarmmail_init", () => {
83
+ expect(SUBTASK_PROMPT_V2).toMatch(/### Step 1:[\s\S]*?swarmmail_init/);
84
+ });
85
+
86
+ test("Step 2 is semantic-memory_find (before skills)", () => {
87
+ const step2Pos = SUBTASK_PROMPT_V2.indexOf("### Step 2:");
88
+ const step3Pos = SUBTASK_PROMPT_V2.indexOf("### Step 3:");
89
+ const memoryFindPos = SUBTASK_PROMPT_V2.indexOf("semantic-memory_find");
90
+ const skillsPos = SUBTASK_PROMPT_V2.indexOf("skills_list");
91
+
92
+ // Memory find should be in Step 2, before skills in Step 3
93
+ expect(memoryFindPos).toBeGreaterThan(step2Pos);
94
+ expect(memoryFindPos).toBeLessThan(step3Pos);
95
+ expect(skillsPos).toBeGreaterThan(step3Pos);
96
+ });
97
+
98
+ test("semantic-memory_store comes before swarm_complete", () => {
99
+ const storePos = SUBTASK_PROMPT_V2.indexOf("semantic-memory_store");
100
+ const completePos = SUBTASK_PROMPT_V2.lastIndexOf("swarm_complete");
101
+
102
+ expect(storePos).toBeGreaterThan(0);
103
+ expect(storePos).toBeLessThan(completePos);
104
+ });
105
+
106
+ test("final step is swarm_complete (not hive_close)", () => {
107
+ // Find the last "### Step N:" pattern
108
+ const stepMatches = [...SUBTASK_PROMPT_V2.matchAll(/### Step (\d+):/g)];
109
+ expect(stepMatches.length).toBeGreaterThan(0);
110
+
111
+ const lastStepNum = Math.max(...stepMatches.map(m => parseInt(m[1])));
112
+ const lastStepMatch = SUBTASK_PROMPT_V2.match(
113
+ new RegExp(`### Step ${lastStepNum}:[\\s\\S]*?(?=## \\[|$)`)
114
+ );
115
+ expect(lastStepMatch).not.toBeNull();
116
+
117
+ const lastStepContent = lastStepMatch![0];
118
+ expect(lastStepContent).toContain("swarm_complete");
119
+ expect(lastStepContent).toMatch(/NOT.*hive_close|DO NOT.*hive_close/i);
120
+ });
121
+ });
122
+
123
+ describe("critical requirements section", () => {
124
+ test("lists memory query as non-negotiable", () => {
125
+ const criticalSection = SUBTASK_PROMPT_V2.match(/\[CRITICAL REQUIREMENTS\][\s\S]*?Begin now/);
126
+ expect(criticalSection).not.toBeNull();
127
+
128
+ expect(criticalSection![0]).toMatch(/semantic-memory_find|memory.*MUST|Step 2.*MUST/i);
129
+ });
130
+
131
+ test("lists consequences of skipping memory steps", () => {
132
+ const criticalSection = SUBTASK_PROMPT_V2.match(/\[CRITICAL REQUIREMENTS\][\s\S]*?Begin now/);
133
+ expect(criticalSection).not.toBeNull();
134
+
135
+ // Should mention consequences for skipping memory
136
+ expect(criticalSection![0]).toMatch(/repeat|waste|already.solved|mistakes/i);
137
+ });
138
+ });
139
+ });
140
+
141
+ describe("formatSubtaskPromptV2", () => {
142
+ test("substitutes all placeholders correctly", () => {
143
+ const result = formatSubtaskPromptV2({
144
+ bead_id: "test-bead-123",
145
+ epic_id: "test-epic-456",
146
+ subtask_title: "Test Subtask",
147
+ subtask_description: "Do the test thing",
148
+ files: ["src/test.ts", "src/test.test.ts"],
149
+ shared_context: "This is shared context",
150
+ project_path: "/path/to/project",
151
+ });
152
+
153
+ expect(result).toContain("test-bead-123");
154
+ expect(result).toContain("test-epic-456");
155
+ expect(result).toContain("Test Subtask");
156
+ expect(result).toContain("Do the test thing");
157
+ expect(result).toContain("src/test.ts");
158
+ expect(result).toContain("/path/to/project");
159
+ });
160
+
161
+ test("includes memory query step with MANDATORY emphasis", () => {
162
+ const result = formatSubtaskPromptV2({
163
+ bead_id: "test-bead",
164
+ epic_id: "test-epic",
165
+ subtask_title: "Test",
166
+ subtask_description: "",
167
+ files: [],
168
+ });
169
+
170
+ expect(result).toMatch(/Step 2:.*MANDATORY/i);
171
+ expect(result).toContain("semantic-memory_find");
172
+ });
173
+ });
@@ -291,18 +291,36 @@ swarmmail_init(project_path="{project_path}", task_description="{bead_id}: {subt
291
291
 
292
292
  **If you skip this step, your work will not be tracked and swarm_complete will fail.**
293
293
 
294
- ### Step 2: Query Past Learnings (BEFORE starting work)
294
+ ### Step 2: 🧠 Query Past Learnings (MANDATORY - BEFORE starting work)
295
+
296
+ **⚠️ CRITICAL: ALWAYS query semantic memory BEFORE writing ANY code.**
297
+
295
298
  \`\`\`
296
- semantic-memory_find(query="<keywords from your task>", limit=5)
299
+ semantic-memory_find(query="<keywords from your task>", limit=5, expand=true)
297
300
  \`\`\`
298
301
 
299
- **Check if past agents solved similar problems.** Search for:
300
- - Error messages if debugging
301
- - Domain concepts (e.g., "authentication", "caching")
302
- - Technology stack (e.g., "Next.js", "React")
303
- - Patterns (e.g., "event sourcing", "validation")
302
+ **Why this is MANDATORY:**
303
+ - Past agents may have already solved your exact problem
304
+ - Avoids repeating mistakes that wasted 30+ minutes before
305
+ - Discovers project-specific patterns and gotchas
306
+ - Finds known workarounds for tool/library quirks
307
+
308
+ **Search Query Examples by Task Type:**
309
+
310
+ - **Bug fix**: Use exact error message or "<symptom> <component>"
311
+ - **New feature**: Search "<domain concept> implementation pattern"
312
+ - **Refactor**: Query "<pattern name> migration approach"
313
+ - **Integration**: Look for "<library name> gotchas configuration"
314
+ - **Testing**: Find "testing <component type> characterization tests"
315
+ - **Performance**: Search "<technology> performance optimization"
316
+
317
+ **BEFORE you start coding:**
318
+ 1. Run semantic-memory_find with keywords from your task
319
+ 2. Read the results with expand=true for full content
320
+ 3. Check if any memory solves your problem or warns of pitfalls
321
+ 4. Adjust your approach based on past learnings
304
322
 
305
- **Past learnings save time and prevent repeating mistakes.**
323
+ **If you skip this step, you WILL waste time solving already-solved problems.**
306
324
 
307
325
  ### Step 3: Load Relevant Skills (if available)
308
326
  \`\`\`