opencode-swarm-plugin 0.30.5 → 0.30.7
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/.turbo/turbo-build.log +2 -2
- package/.turbo/turbo-test.log +317 -317
- package/CHANGELOG.md +13 -0
- package/dist/hive.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +134 -29
- package/dist/memory-tools.d.ts +4 -0
- package/dist/memory-tools.d.ts.map +1 -1
- package/dist/memory.d.ts +2 -0
- package/dist/memory.d.ts.map +1 -1
- package/dist/model-selection.d.ts +37 -0
- package/dist/model-selection.d.ts.map +1 -0
- package/dist/plugin.js +134 -29
- package/dist/schemas/task.d.ts +2 -0
- package/dist/schemas/task.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +5 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm.d.ts +2 -0
- package/dist/swarm.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/hive.ts +16 -2
- package/src/memory-tools.ts +5 -1
- package/src/memory.ts +9 -0
- package/src/swarm-prompts.test.ts +176 -0
- package/src/swarm-prompts.ts +64 -20
- package/src/swarm.integration.test.ts +4 -4
|
@@ -0,0 +1,176 @@
|
|
|
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
|
+
if (!lastStepMatch) return;
|
|
117
|
+
|
|
118
|
+
const lastStepContent = lastStepMatch[0];
|
|
119
|
+
expect(lastStepContent).toContain("swarm_complete");
|
|
120
|
+
expect(lastStepContent).toMatch(/NOT.*hive_close|DO NOT.*hive_close/i);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe("critical requirements section", () => {
|
|
125
|
+
test("lists memory query as non-negotiable", () => {
|
|
126
|
+
const criticalSection = SUBTASK_PROMPT_V2.match(/\[CRITICAL REQUIREMENTS\][\s\S]*?Begin now/);
|
|
127
|
+
expect(criticalSection).not.toBeNull();
|
|
128
|
+
if (!criticalSection) return;
|
|
129
|
+
|
|
130
|
+
expect(criticalSection[0]).toMatch(/semantic-memory_find|memory.*MUST|Step 2.*MUST/i);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test("lists consequences of skipping memory steps", () => {
|
|
134
|
+
const criticalSection = SUBTASK_PROMPT_V2.match(/\[CRITICAL REQUIREMENTS\][\s\S]*?Begin now/);
|
|
135
|
+
expect(criticalSection).not.toBeNull();
|
|
136
|
+
if (!criticalSection) return;
|
|
137
|
+
|
|
138
|
+
// Should mention consequences for skipping memory
|
|
139
|
+
expect(criticalSection[0]).toMatch(/repeat|waste|already.solved|mistakes/i);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe("formatSubtaskPromptV2", () => {
|
|
145
|
+
test("substitutes all placeholders correctly", () => {
|
|
146
|
+
const result = formatSubtaskPromptV2({
|
|
147
|
+
bead_id: "test-project-abc123-bead456",
|
|
148
|
+
epic_id: "test-project-abc123-epic789",
|
|
149
|
+
subtask_title: "Test Subtask",
|
|
150
|
+
subtask_description: "Do the test thing",
|
|
151
|
+
files: ["src/test.ts", "src/test.test.ts"],
|
|
152
|
+
shared_context: "This is shared context",
|
|
153
|
+
project_path: "/path/to/project",
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
expect(result).toContain("test-project-abc123-bead456");
|
|
157
|
+
expect(result).toContain("test-project-abc123-epic789");
|
|
158
|
+
expect(result).toContain("Test Subtask");
|
|
159
|
+
expect(result).toContain("Do the test thing");
|
|
160
|
+
expect(result).toContain("src/test.ts");
|
|
161
|
+
expect(result).toContain("/path/to/project");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("includes memory query step with MANDATORY emphasis", () => {
|
|
165
|
+
const result = formatSubtaskPromptV2({
|
|
166
|
+
bead_id: "test-project-abc123-def456",
|
|
167
|
+
epic_id: "test-project-abc123-ghi789",
|
|
168
|
+
subtask_title: "Test",
|
|
169
|
+
subtask_description: "",
|
|
170
|
+
files: [],
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
expect(result).toMatch(/Step 2:.*MANDATORY/i);
|
|
174
|
+
expect(result).toContain("semantic-memory_find");
|
|
175
|
+
});
|
|
176
|
+
});
|
package/src/swarm-prompts.ts
CHANGED
|
@@ -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
|
-
**
|
|
300
|
-
-
|
|
301
|
-
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
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"
|
|
304
316
|
|
|
305
|
-
**
|
|
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
|
|
322
|
+
|
|
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
|
\`\`\`
|
|
@@ -388,21 +406,44 @@ swarm_checkpoint(
|
|
|
388
406
|
|
|
389
407
|
**Checkpoints preserve context so you can recover if things go wrong.**
|
|
390
408
|
|
|
391
|
-
### Step 8:
|
|
409
|
+
### Step 8: 💾 STORE YOUR LEARNINGS (if you discovered something)
|
|
410
|
+
|
|
411
|
+
**If you learned it the hard way, STORE IT so the next agent doesn't have to.**
|
|
412
|
+
|
|
392
413
|
\`\`\`
|
|
393
414
|
semantic-memory_store(
|
|
394
415
|
information="<what you learned, WHY it matters, how to apply it>",
|
|
395
|
-
|
|
416
|
+
tags="<domain, tech-stack, pattern-type>"
|
|
396
417
|
)
|
|
397
418
|
\`\`\`
|
|
398
419
|
|
|
399
|
-
**Store:**
|
|
400
|
-
-
|
|
401
|
-
-
|
|
402
|
-
-
|
|
403
|
-
-
|
|
420
|
+
**MANDATORY Storage Triggers - Store when you:**
|
|
421
|
+
- 🐛 **Solved a tricky bug** (>15min debugging) - include root cause + solution
|
|
422
|
+
- 💡 **Discovered a project-specific pattern** - domain rules, business logic quirks
|
|
423
|
+
- ⚠️ **Found a tool/library gotcha** - API quirks, version-specific bugs, workarounds
|
|
424
|
+
- 🚫 **Tried an approach that failed** - anti-patterns to avoid, why it didn't work
|
|
425
|
+
- 🏗️ **Made an architectural decision** - reasoning, alternatives considered, tradeoffs
|
|
426
|
+
|
|
427
|
+
**What Makes a GOOD Memory:**
|
|
428
|
+
|
|
429
|
+
✅ **GOOD** (actionable, explains WHY):
|
|
430
|
+
\`\`\`
|
|
431
|
+
"OAuth refresh tokens need 5min buffer before expiry to avoid race conditions.
|
|
432
|
+
Without buffer, token refresh can fail mid-request if expiry happens between
|
|
433
|
+
check and use. Implemented with: if (expiresAt - Date.now() < 300000) refresh()"
|
|
434
|
+
\`\`\`
|
|
435
|
+
|
|
436
|
+
❌ **BAD** (generic, no context):
|
|
437
|
+
\`\`\`
|
|
438
|
+
"Fixed the auth bug by adding a null check"
|
|
439
|
+
\`\`\`
|
|
404
440
|
|
|
405
|
-
**
|
|
441
|
+
**What NOT to Store:**
|
|
442
|
+
- Generic knowledge that's in official documentation
|
|
443
|
+
- Implementation details that change frequently
|
|
444
|
+
- Vague descriptions without context ("fixed the thing")
|
|
445
|
+
|
|
446
|
+
**The WHY matters more than the WHAT.** Future agents need context to apply your learning.
|
|
406
447
|
|
|
407
448
|
### Step 9: Complete (REQUIRED - releases reservations)
|
|
408
449
|
\`\`\`
|
|
@@ -493,17 +534,20 @@ Other cell operations:
|
|
|
493
534
|
|
|
494
535
|
**NON-NEGOTIABLE:**
|
|
495
536
|
1. Step 1 (swarmmail_init) MUST be first - do it before anything else
|
|
496
|
-
2. Step 2 (semantic-memory_find) MUST happen
|
|
537
|
+
2. 🧠 Step 2 (semantic-memory_find) MUST happen BEFORE starting work - query first, code second
|
|
497
538
|
3. Step 4 (swarmmail_reserve) - YOU reserve files, not coordinator
|
|
498
539
|
4. Step 6 (swarm_progress) - Report at milestones, don't work silently
|
|
499
|
-
5. Step
|
|
540
|
+
5. 💾 Step 8 (semantic-memory_store) - If you learned something hard, STORE IT
|
|
541
|
+
6. Step 9 (swarm_complete) - Use this to close, NOT hive_close
|
|
500
542
|
|
|
501
543
|
**If you skip these steps:**
|
|
502
544
|
- Your work won't be tracked (swarm_complete will fail)
|
|
503
|
-
- You'll waste time repeating solved problems (no semantic memory query)
|
|
545
|
+
- 🔄 You'll waste time repeating already-solved problems (no semantic memory query)
|
|
504
546
|
- Edit conflicts with other agents (no file reservation)
|
|
505
547
|
- Lost work if you crash (no checkpoints)
|
|
506
|
-
- Future agents repeat
|
|
548
|
+
- 🔄 Future agents repeat YOUR mistakes (no learnings stored)
|
|
549
|
+
|
|
550
|
+
**Memory is the swarm's collective intelligence. Query it. Feed it.**
|
|
507
551
|
|
|
508
552
|
Begin now.`;
|
|
509
553
|
|
|
@@ -1426,7 +1426,7 @@ describe("Swarm Prompt V2 (with Swarm Mail/Beads)", () => {
|
|
|
1426
1426
|
expect(SUBTASK_PROMPT_V2).toContain("semantic-memory_find");
|
|
1427
1427
|
expect(SUBTASK_PROMPT_V2).toContain("Query Past Learnings");
|
|
1428
1428
|
expect(SUBTASK_PROMPT_V2).toContain("BEFORE starting work");
|
|
1429
|
-
expect(SUBTASK_PROMPT_V2).toContain("
|
|
1429
|
+
expect(SUBTASK_PROMPT_V2).toContain("If you skip this step, you WILL waste time solving already-solved problems");
|
|
1430
1430
|
});
|
|
1431
1431
|
|
|
1432
1432
|
it("contains survival checklist: skills discovery and loading", () => {
|
|
@@ -1465,9 +1465,9 @@ describe("Swarm Prompt V2 (with Swarm Mail/Beads)", () => {
|
|
|
1465
1465
|
it("contains survival checklist: semantic-memory_store for learnings", () => {
|
|
1466
1466
|
// Step 8: Store discoveries and learnings
|
|
1467
1467
|
expect(SUBTASK_PROMPT_V2).toContain("semantic-memory_store");
|
|
1468
|
-
expect(SUBTASK_PROMPT_V2).toContain("
|
|
1469
|
-
expect(SUBTASK_PROMPT_V2).toContain("
|
|
1470
|
-
expect(SUBTASK_PROMPT_V2).toContain("
|
|
1468
|
+
expect(SUBTASK_PROMPT_V2).toContain("STORE YOUR LEARNINGS");
|
|
1469
|
+
expect(SUBTASK_PROMPT_V2).toContain("Solved a tricky bug");
|
|
1470
|
+
expect(SUBTASK_PROMPT_V2).toContain("The WHY matters more than the WHAT");
|
|
1471
1471
|
});
|
|
1472
1472
|
|
|
1473
1473
|
it("does NOT mention coordinator reserving files", () => {
|