opencode-swarm-plugin 0.21.0 → 0.23.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 (131) hide show
  1. package/.turbo/turbo-build.log +9 -0
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +111 -166
  4. package/dist/agent-mail.d.ts +480 -0
  5. package/dist/agent-mail.d.ts.map +1 -0
  6. package/dist/anti-patterns.d.ts +257 -0
  7. package/dist/anti-patterns.d.ts.map +1 -0
  8. package/dist/beads.d.ts +377 -0
  9. package/dist/beads.d.ts.map +1 -0
  10. package/dist/eval-capture.d.ts +206 -0
  11. package/dist/eval-capture.d.ts.map +1 -0
  12. package/dist/index.d.ts +1299 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +776 -4387
  15. package/dist/learning.d.ts +670 -0
  16. package/dist/learning.d.ts.map +1 -0
  17. package/dist/mandate-promotion.d.ts +93 -0
  18. package/dist/mandate-promotion.d.ts.map +1 -0
  19. package/dist/mandate-storage.d.ts +209 -0
  20. package/dist/mandate-storage.d.ts.map +1 -0
  21. package/dist/mandates.d.ts +230 -0
  22. package/dist/mandates.d.ts.map +1 -0
  23. package/dist/output-guardrails.d.ts +125 -0
  24. package/dist/output-guardrails.d.ts.map +1 -0
  25. package/dist/pattern-maturity.d.ts +246 -0
  26. package/dist/pattern-maturity.d.ts.map +1 -0
  27. package/dist/plugin.d.ts +22 -0
  28. package/dist/plugin.d.ts.map +1 -0
  29. package/dist/plugin.js +755 -4375
  30. package/dist/rate-limiter.d.ts +218 -0
  31. package/dist/rate-limiter.d.ts.map +1 -0
  32. package/dist/repo-crawl.d.ts +146 -0
  33. package/dist/repo-crawl.d.ts.map +1 -0
  34. package/dist/schemas/bead.d.ts +255 -0
  35. package/dist/schemas/bead.d.ts.map +1 -0
  36. package/dist/schemas/evaluation.d.ts +161 -0
  37. package/dist/schemas/evaluation.d.ts.map +1 -0
  38. package/dist/schemas/index.d.ts +34 -0
  39. package/dist/schemas/index.d.ts.map +1 -0
  40. package/dist/schemas/mandate.d.ts +336 -0
  41. package/dist/schemas/mandate.d.ts.map +1 -0
  42. package/dist/schemas/swarm-context.d.ts +131 -0
  43. package/dist/schemas/swarm-context.d.ts.map +1 -0
  44. package/dist/schemas/task.d.ts +188 -0
  45. package/dist/schemas/task.d.ts.map +1 -0
  46. package/dist/skills.d.ts +471 -0
  47. package/dist/skills.d.ts.map +1 -0
  48. package/dist/storage.d.ts +260 -0
  49. package/dist/storage.d.ts.map +1 -0
  50. package/dist/structured.d.ts +196 -0
  51. package/dist/structured.d.ts.map +1 -0
  52. package/dist/swarm-decompose.d.ts +201 -0
  53. package/dist/swarm-decompose.d.ts.map +1 -0
  54. package/dist/swarm-mail.d.ts +240 -0
  55. package/dist/swarm-mail.d.ts.map +1 -0
  56. package/dist/swarm-orchestrate.d.ts +708 -0
  57. package/dist/swarm-orchestrate.d.ts.map +1 -0
  58. package/dist/swarm-prompts.d.ts +292 -0
  59. package/dist/swarm-prompts.d.ts.map +1 -0
  60. package/dist/swarm-strategies.d.ts +100 -0
  61. package/dist/swarm-strategies.d.ts.map +1 -0
  62. package/dist/swarm.d.ts +455 -0
  63. package/dist/swarm.d.ts.map +1 -0
  64. package/dist/tool-availability.d.ts +91 -0
  65. package/dist/tool-availability.d.ts.map +1 -0
  66. package/docs/planning/ADR-001-monorepo-structure.md +171 -0
  67. package/docs/planning/ADR-002-package-extraction.md +393 -0
  68. package/docs/planning/ADR-003-performance-improvements.md +451 -0
  69. package/docs/planning/ADR-004-message-queue-features.md +187 -0
  70. package/docs/planning/ADR-005-devtools-observability.md +202 -0
  71. package/docs/planning/ROADMAP.md +368 -0
  72. package/docs/semantic-memory-cli-syntax.md +123 -0
  73. package/docs/swarm-mail-architecture.md +1147 -0
  74. package/package.json +13 -24
  75. package/scripts/cleanup-test-memories.ts +346 -0
  76. package/src/agent-mail.ts +1 -1
  77. package/src/beads.ts +1 -2
  78. package/src/index.ts +2 -2
  79. package/src/learning.integration.test.ts +80 -10
  80. package/src/mandate-storage.test.ts +3 -3
  81. package/src/storage.ts +189 -9
  82. package/src/swarm-mail.ts +3 -3
  83. package/src/swarm-orchestrate.ts +399 -246
  84. package/src/swarm.integration.test.ts +124 -0
  85. package/src/tool-availability.ts +1 -1
  86. package/tsconfig.json +1 -1
  87. package/.beads/.local_version +0 -1
  88. package/.beads/README.md +0 -81
  89. package/.beads/analysis/skill-architecture-meta-skills.md +0 -1562
  90. package/.beads/config.yaml +0 -62
  91. package/.beads/issues.jsonl +0 -2186
  92. package/.beads/metadata.json +0 -4
  93. package/.gitattributes +0 -3
  94. package/.github/workflows/ci.yml +0 -30
  95. package/.github/workflows/opencode.yml +0 -31
  96. package/.opencode/skills/tdd/SKILL.md +0 -182
  97. package/INTEGRATION_EXAMPLE.md +0 -66
  98. package/VERIFICATION_QUALITY_PATTERNS.md +0 -565
  99. package/bun.lock +0 -286
  100. package/dist/pglite.data +0 -0
  101. package/dist/pglite.wasm +0 -0
  102. package/src/streams/agent-mail.test.ts +0 -777
  103. package/src/streams/agent-mail.ts +0 -535
  104. package/src/streams/debug.test.ts +0 -500
  105. package/src/streams/debug.ts +0 -727
  106. package/src/streams/effect/ask.integration.test.ts +0 -314
  107. package/src/streams/effect/ask.ts +0 -202
  108. package/src/streams/effect/cursor.integration.test.ts +0 -418
  109. package/src/streams/effect/cursor.ts +0 -288
  110. package/src/streams/effect/deferred.test.ts +0 -357
  111. package/src/streams/effect/deferred.ts +0 -445
  112. package/src/streams/effect/index.ts +0 -17
  113. package/src/streams/effect/layers.ts +0 -73
  114. package/src/streams/effect/lock.test.ts +0 -385
  115. package/src/streams/effect/lock.ts +0 -399
  116. package/src/streams/effect/mailbox.test.ts +0 -260
  117. package/src/streams/effect/mailbox.ts +0 -318
  118. package/src/streams/events.test.ts +0 -924
  119. package/src/streams/events.ts +0 -329
  120. package/src/streams/index.test.ts +0 -229
  121. package/src/streams/index.ts +0 -578
  122. package/src/streams/migrations.test.ts +0 -359
  123. package/src/streams/migrations.ts +0 -362
  124. package/src/streams/projections.test.ts +0 -611
  125. package/src/streams/projections.ts +0 -504
  126. package/src/streams/store.integration.test.ts +0 -658
  127. package/src/streams/store.ts +0 -1075
  128. package/src/streams/swarm-mail.ts +0 -552
  129. package/test-bug-fixes.ts +0 -86
  130. package/vitest.integration.config.ts +0 -13
  131. package/workflow-integration-analysis.md +0 -876
package/src/storage.ts CHANGED
@@ -141,15 +141,102 @@ export interface StorageConfig {
141
141
  useSemanticSearch: boolean;
142
142
  }
143
143
 
144
- export const DEFAULT_STORAGE_CONFIG: StorageConfig = {
145
- backend: "semantic-memory",
146
- collections: {
144
+ /**
145
+ * Generate unique test collection name
146
+ *
147
+ * Creates a timestamp-based suffix for test collections to ensure complete isolation.
148
+ * Each test run gets its own collections that don't pollute production semantic-memory.
149
+ *
150
+ * @returns Unique suffix like "test-1734567890123"
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * // In test setup:
155
+ * process.env.TEST_SEMANTIC_MEMORY_COLLECTION = getTestCollectionName();
156
+ * // Results in collections like: swarm-feedback-test-1734567890123
157
+ * ```
158
+ */
159
+ export function getTestCollectionName(): string {
160
+ return `test-${Date.now()}`;
161
+ }
162
+
163
+ /**
164
+ * Get collection names with optional test suffix
165
+ *
166
+ * Supports two test isolation modes:
167
+ * 1. TEST_MEMORY_COLLECTIONS=true - appends "-test" (shared across test run)
168
+ * 2. TEST_SEMANTIC_MEMORY_COLLECTION=<suffix> - appends custom suffix (unique per test run)
169
+ *
170
+ * Mode 2 is preferred for full isolation - prevents test pollution of production
171
+ * semantic-memory collections.
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Production
176
+ * getCollectionNames()
177
+ * // => { feedback: "swarm-feedback", patterns: "swarm-patterns", maturity: "swarm-maturity" }
178
+ *
179
+ * // Test mode 1 (legacy)
180
+ * process.env.TEST_MEMORY_COLLECTIONS = "true"
181
+ * getCollectionNames()
182
+ * // => { feedback: "swarm-feedback-test", patterns: "swarm-patterns-test", ... }
183
+ *
184
+ * // Test mode 2 (preferred - full isolation)
185
+ * process.env.TEST_SEMANTIC_MEMORY_COLLECTION = "test-1734567890123"
186
+ * getCollectionNames()
187
+ * // => { feedback: "swarm-feedback-test-1734567890123", patterns: "swarm-patterns-test-1734567890123", ... }
188
+ * ```
189
+ */
190
+ function getCollectionNames(): StorageCollections {
191
+ const base = {
147
192
  feedback: "swarm-feedback",
148
193
  patterns: "swarm-patterns",
149
194
  maturity: "swarm-maturity",
150
- },
151
- useSemanticSearch: true,
152
- };
195
+ };
196
+
197
+ // Test isolation mode 2 (preferred): unique suffix per test run
198
+ const testSuffix = process.env.TEST_SEMANTIC_MEMORY_COLLECTION;
199
+ if (testSuffix) {
200
+ return {
201
+ feedback: `${base.feedback}-${testSuffix}`,
202
+ patterns: `${base.patterns}-${testSuffix}`,
203
+ maturity: `${base.maturity}-${testSuffix}`,
204
+ };
205
+ }
206
+
207
+ // Test isolation mode 1 (legacy): shared "-test" suffix
208
+ if (process.env.TEST_MEMORY_COLLECTIONS === "true") {
209
+ return {
210
+ feedback: `${base.feedback}-test`,
211
+ patterns: `${base.patterns}-test`,
212
+ maturity: `${base.maturity}-test`,
213
+ };
214
+ }
215
+
216
+ return base;
217
+ }
218
+
219
+ /**
220
+ * Get default storage configuration
221
+ *
222
+ * Returns a fresh config object on each call to ensure env vars (like
223
+ * TEST_SEMANTIC_MEMORY_COLLECTION) are read at runtime, not module load time.
224
+ *
225
+ * @returns Default storage configuration
226
+ */
227
+ export function getDefaultStorageConfig(): StorageConfig {
228
+ return {
229
+ backend: "semantic-memory",
230
+ collections: getCollectionNames(),
231
+ useSemanticSearch: true,
232
+ };
233
+ }
234
+
235
+ /**
236
+ * @deprecated Use getDefaultStorageConfig() instead. This static export
237
+ * captures collections at module load time, breaking test isolation.
238
+ */
239
+ export const DEFAULT_STORAGE_CONFIG: StorageConfig = getDefaultStorageConfig();
153
240
 
154
241
  // ============================================================================
155
242
  // Unified Storage Interface
@@ -189,6 +276,43 @@ export interface LearningStorage {
189
276
  close(): Promise<void>;
190
277
  }
191
278
 
279
+ // ============================================================================
280
+ // Session Stats Tracking
281
+ // ============================================================================
282
+
283
+ interface SessionStats {
284
+ storesCount: number;
285
+ queriesCount: number;
286
+ sessionStart: number;
287
+ lastAlertCheck: number;
288
+ }
289
+
290
+ let sessionStats: SessionStats = {
291
+ storesCount: 0,
292
+ queriesCount: 0,
293
+ sessionStart: Date.now(),
294
+ lastAlertCheck: Date.now(),
295
+ };
296
+
297
+ /**
298
+ * Reset session stats (for testing)
299
+ */
300
+ export function resetSessionStats(): void {
301
+ sessionStats = {
302
+ storesCount: 0,
303
+ queriesCount: 0,
304
+ sessionStart: Date.now(),
305
+ lastAlertCheck: Date.now(),
306
+ };
307
+ }
308
+
309
+ /**
310
+ * Get current session stats
311
+ */
312
+ export function getSessionStats(): Readonly<SessionStats> {
313
+ return { ...sessionStats };
314
+ }
315
+
192
316
  // ============================================================================
193
317
  // Semantic Memory Storage Implementation
194
318
  // ============================================================================
@@ -203,13 +327,48 @@ export class SemanticMemoryStorage implements LearningStorage {
203
327
  private config: StorageConfig;
204
328
 
205
329
  constructor(config: Partial<StorageConfig> = {}) {
206
- this.config = { ...DEFAULT_STORAGE_CONFIG, ...config };
330
+ // Use getDefaultStorageConfig() to ensure env vars are read at runtime
331
+ this.config = { ...getDefaultStorageConfig(), ...config };
332
+ console.log(
333
+ `[storage] SemanticMemoryStorage initialized with collections:`,
334
+ this.config.collections,
335
+ );
207
336
  }
208
337
 
209
338
  // -------------------------------------------------------------------------
210
339
  // Helpers
211
340
  // -------------------------------------------------------------------------
212
341
 
342
+ /**
343
+ * Check if low usage alert should be sent
344
+ *
345
+ * Sends alert via agentmail if:
346
+ * - More than 10 minutes have elapsed since session start
347
+ * - Less than 1 store operation has occurred
348
+ * - Alert hasn't been sent in the last 10 minutes
349
+ */
350
+ private async checkLowUsageAlert(): Promise<void> {
351
+ const TEN_MINUTES = 10 * 60 * 1000;
352
+ const now = Date.now();
353
+ const sessionDuration = now - sessionStats.sessionStart;
354
+ const timeSinceLastAlert = now - sessionStats.lastAlertCheck;
355
+
356
+ if (
357
+ sessionDuration >= TEN_MINUTES &&
358
+ sessionStats.storesCount < 1 &&
359
+ timeSinceLastAlert >= TEN_MINUTES
360
+ ) {
361
+ console.warn(
362
+ `[storage] LOW USAGE ALERT: ${sessionStats.storesCount} stores after ${Math.floor(sessionDuration / 60000)} minutes`,
363
+ );
364
+ sessionStats.lastAlertCheck = now;
365
+
366
+ // Send alert via Agent Mail if available
367
+ // Note: This requires agentmail to be initialized, which may not always be the case
368
+ // We'll log the alert and let the coordinator detect it in logs
369
+ }
370
+ }
371
+
213
372
  private async store(
214
373
  collection: string,
215
374
  data: unknown,
@@ -222,7 +381,19 @@ export class SemanticMemoryStorage implements LearningStorage {
222
381
  args.push("--metadata", JSON.stringify(metadata));
223
382
  }
224
383
 
225
- await execSemanticMemory(args);
384
+ console.log(`[storage] store() -> collection="${collection}"`);
385
+ sessionStats.storesCount++;
386
+
387
+ const result = await execSemanticMemory(args);
388
+
389
+ if (result.exitCode !== 0) {
390
+ console.warn(
391
+ `[storage] semantic-memory store() failed with exit code ${result.exitCode}: ${result.stderr.toString().trim()}`,
392
+ );
393
+ }
394
+
395
+ // Alert check: if 10+ minutes elapsed with < 1 store, send alert
396
+ await this.checkLowUsageAlert();
226
397
  }
227
398
 
228
399
  private async find<T>(
@@ -245,6 +416,11 @@ export class SemanticMemoryStorage implements LearningStorage {
245
416
  args.push("--fts");
246
417
  }
247
418
 
419
+ console.log(
420
+ `[storage] find() -> collection="${collection}", query="${query.slice(0, 50)}${query.length > 50 ? "..." : ""}", limit=${limit}, fts=${useFts}`,
421
+ );
422
+ sessionStats.queriesCount++;
423
+
248
424
  const result = await execSemanticMemory(args);
249
425
 
250
426
  if (result.exitCode !== 0) {
@@ -280,6 +456,9 @@ export class SemanticMemoryStorage implements LearningStorage {
280
456
  }
281
457
 
282
458
  private async list<T>(collection: string): Promise<T[]> {
459
+ console.log(`[storage] list() -> collection="${collection}"`);
460
+ sessionStats.queriesCount++;
461
+
283
462
  const result = await execSemanticMemory([
284
463
  "list",
285
464
  "--collection",
@@ -611,7 +790,8 @@ export class InMemoryStorage implements LearningStorage {
611
790
  export function createStorage(
612
791
  config: Partial<StorageConfig> = {},
613
792
  ): LearningStorage {
614
- const fullConfig = { ...DEFAULT_STORAGE_CONFIG, ...config };
793
+ // Use getDefaultStorageConfig() to ensure env vars are read at runtime
794
+ const fullConfig = { ...getDefaultStorageConfig(), ...config };
615
795
 
616
796
  switch (fullConfig.backend) {
617
797
  case "semantic-memory":
package/src/swarm-mail.ts CHANGED
@@ -26,9 +26,9 @@ import {
26
26
  releaseSwarmFiles,
27
27
  acknowledgeSwarmMessage,
28
28
  checkSwarmHealth,
29
- } from "./streams/swarm-mail";
30
- import { getActiveReservations } from "./streams/projections";
31
- import type { MailSessionState } from "./streams/events";
29
+ getActiveReservations,
30
+ type MailSessionState,
31
+ } from "swarm-mail";
32
32
  import {
33
33
  existsSync,
34
34
  mkdirSync,