opencode-swarm-plugin 0.57.6 → 0.59.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.
@@ -17875,13 +17875,13 @@ Scripts run in the skill's directory with the project directory as an argument.`
17875
17875
  }
17876
17876
  const scriptPath = join3(skill.directory, "scripts", args.script);
17877
17877
  const scriptArgs = args.args || [];
17878
+ const TIMEOUT_MS = 60000;
17879
+ const proc = Bun.spawn([scriptPath, skillsProjectDirectory, ...scriptArgs], {
17880
+ cwd: skill.directory,
17881
+ stdout: "pipe",
17882
+ stderr: "pipe"
17883
+ });
17878
17884
  try {
17879
- const TIMEOUT_MS = 60000;
17880
- const proc = Bun.spawn([scriptPath, skillsProjectDirectory, ...scriptArgs], {
17881
- cwd: skill.directory,
17882
- stdout: "pipe",
17883
- stderr: "pipe"
17884
- });
17885
17885
  const timeoutPromise = new Promise((resolve2) => {
17886
17886
  setTimeout(() => resolve2({ timedOut: true }), TIMEOUT_MS);
17887
17887
  });
@@ -17895,7 +17895,6 @@ Scripts run in the skill's directory with the project directory as an argument.`
17895
17895
  })();
17896
17896
  const result = await Promise.race([resultPromise, timeoutPromise]);
17897
17897
  if (result.timedOut) {
17898
- proc.kill();
17899
17898
  return `Script timed out after ${TIMEOUT_MS / 1000} seconds.`;
17900
17899
  }
17901
17900
  const output = result.stdout + result.stderr;
@@ -17907,6 +17906,8 @@ ${output}`;
17907
17906
  }
17908
17907
  } catch (error45) {
17909
17908
  return `Failed to execute script: ${error45 instanceof Error ? error45.message : String(error45)}`;
17909
+ } finally {
17910
+ proc.kill();
17910
17911
  }
17911
17912
  }
17912
17913
  });
@@ -18284,6 +18285,237 @@ echo "Project directory: $1"
18284
18285
  };
18285
18286
  });
18286
18287
 
18288
+ // src/decision-trace-integration.ts
18289
+ var exports_decision_trace_integration = {};
18290
+ __export(exports_decision_trace_integration, {
18291
+ traceWorkerSpawn: () => traceWorkerSpawn,
18292
+ traceStrategySelection: () => traceStrategySelection,
18293
+ traceScopeChange: () => traceScopeChange,
18294
+ traceReviewDecision: () => traceReviewDecision,
18295
+ traceFileSelection: () => traceFileSelection,
18296
+ linkOutcomeToDecisionTrace: () => linkOutcomeToDecisionTrace,
18297
+ getEpicDecisionTraces: () => getEpicDecisionTraces,
18298
+ getDecisionTracesByType: () => getDecisionTracesByType,
18299
+ extractMemoryIds: () => extractMemoryIds
18300
+ });
18301
+ import {
18302
+ createDecisionTrace,
18303
+ createEntityLink
18304
+ } from "swarm-mail";
18305
+ import { createLibSQLAdapter } from "swarm-mail";
18306
+ import { getDatabasePath } from "swarm-mail";
18307
+ async function getTraceDb(projectPath) {
18308
+ const dbPath = getDatabasePath(projectPath);
18309
+ return createLibSQLAdapter({ url: `file:${dbPath}` });
18310
+ }
18311
+ function extractMemoryIds(precedentCited) {
18312
+ if (!precedentCited) {
18313
+ return [];
18314
+ }
18315
+ if (precedentCited.memoryIds && Array.isArray(precedentCited.memoryIds)) {
18316
+ return precedentCited.memoryIds;
18317
+ }
18318
+ if (precedentCited.memoryId) {
18319
+ return [precedentCited.memoryId];
18320
+ }
18321
+ return [];
18322
+ }
18323
+ async function traceStrategySelection(input) {
18324
+ try {
18325
+ const db = await getTraceDb(input.projectKey);
18326
+ const trace = await createDecisionTrace(db, {
18327
+ decision_type: "strategy_selection",
18328
+ epic_id: input.epicId,
18329
+ bead_id: input.beadId,
18330
+ agent_name: input.agentName,
18331
+ project_key: input.projectKey,
18332
+ decision: {
18333
+ strategy: input.strategy,
18334
+ confidence: input.confidence,
18335
+ task_preview: input.taskPreview
18336
+ },
18337
+ rationale: input.reasoning,
18338
+ inputs_gathered: input.inputsGathered,
18339
+ alternatives: input.alternatives,
18340
+ precedent_cited: input.precedentCited
18341
+ });
18342
+ const memoryIds = extractMemoryIds(input.precedentCited);
18343
+ for (const memoryId of memoryIds) {
18344
+ await createEntityLink(db, {
18345
+ source_decision_id: trace.id,
18346
+ target_entity_type: "memory",
18347
+ target_entity_id: memoryId,
18348
+ link_type: "cites_precedent",
18349
+ strength: input.precedentCited?.similarity ?? 1,
18350
+ context: "Cited as precedent for strategy selection"
18351
+ });
18352
+ }
18353
+ await db.close?.();
18354
+ return trace.id;
18355
+ } catch (error45) {
18356
+ console.warn("[decision-trace] Failed to trace strategy_selection:", error45);
18357
+ return "";
18358
+ }
18359
+ }
18360
+ async function traceWorkerSpawn(input) {
18361
+ try {
18362
+ const db = await getTraceDb(input.projectKey);
18363
+ const trace = await createDecisionTrace(db, {
18364
+ decision_type: "worker_spawn",
18365
+ epic_id: input.epicId,
18366
+ bead_id: input.beadId,
18367
+ agent_name: input.agentName,
18368
+ project_key: input.projectKey,
18369
+ decision: {
18370
+ worker: input.workerName || "worker",
18371
+ subtask_title: input.subtaskTitle,
18372
+ files: input.files,
18373
+ model: input.model,
18374
+ spawn_order: input.spawnOrder,
18375
+ is_parallel: input.isParallel
18376
+ },
18377
+ rationale: input.rationale || `Spawning worker for: ${input.subtaskTitle}`
18378
+ });
18379
+ for (const file2 of input.files) {
18380
+ await createEntityLink(db, {
18381
+ source_decision_id: trace.id,
18382
+ target_entity_type: "file",
18383
+ target_entity_id: file2,
18384
+ link_type: "assigns_file",
18385
+ strength: 1,
18386
+ context: `File assigned to worker ${input.workerName || "worker"}`
18387
+ });
18388
+ }
18389
+ await db.close?.();
18390
+ return trace.id;
18391
+ } catch (error45) {
18392
+ console.warn("[decision-trace] Failed to trace worker_spawn:", error45);
18393
+ return "";
18394
+ }
18395
+ }
18396
+ async function traceReviewDecision(input) {
18397
+ try {
18398
+ const db = await getTraceDb(input.projectKey);
18399
+ const trace = await createDecisionTrace(db, {
18400
+ decision_type: "review_decision",
18401
+ epic_id: input.epicId,
18402
+ bead_id: input.beadId,
18403
+ agent_name: input.agentName,
18404
+ project_key: input.projectKey,
18405
+ decision: {
18406
+ status: input.status,
18407
+ worker_id: input.workerId,
18408
+ issues_count: input.issues?.length || 0,
18409
+ attempt_number: input.attemptNumber,
18410
+ remaining_attempts: input.remainingAttempts
18411
+ },
18412
+ rationale: input.rationale || input.summary || `Review ${input.status}`,
18413
+ inputs_gathered: input.issues ? [{ source: "code_review", issues: input.issues }] : undefined
18414
+ });
18415
+ await createEntityLink(db, {
18416
+ source_decision_id: trace.id,
18417
+ target_entity_type: "agent",
18418
+ target_entity_id: input.workerId,
18419
+ link_type: "reviewed_work_by",
18420
+ strength: 1,
18421
+ context: `Review ${input.status} for ${input.workerId}`
18422
+ });
18423
+ await db.close?.();
18424
+ return trace.id;
18425
+ } catch (error45) {
18426
+ console.warn("[decision-trace] Failed to trace review_decision:", error45);
18427
+ return "";
18428
+ }
18429
+ }
18430
+ async function traceFileSelection(input) {
18431
+ try {
18432
+ const db = await getTraceDb(input.projectKey);
18433
+ const trace = await createDecisionTrace(db, {
18434
+ decision_type: "file_selection",
18435
+ epic_id: input.epicId,
18436
+ bead_id: input.beadId,
18437
+ agent_name: input.agentName,
18438
+ project_key: input.projectKey,
18439
+ decision: {
18440
+ files_selected: input.filesSelected,
18441
+ files_owned: input.filesOwned,
18442
+ scope_expanded: input.scopeExpanded
18443
+ },
18444
+ rationale: input.rationale || `Selected ${input.filesSelected.length} files`
18445
+ });
18446
+ await db.close?.();
18447
+ return trace.id;
18448
+ } catch (error45) {
18449
+ console.warn("[decision-trace] Failed to trace file_selection:", error45);
18450
+ return "";
18451
+ }
18452
+ }
18453
+ async function traceScopeChange(input) {
18454
+ try {
18455
+ const db = await getTraceDb(input.projectKey);
18456
+ const trace = await createDecisionTrace(db, {
18457
+ decision_type: "scope_change",
18458
+ epic_id: input.epicId,
18459
+ bead_id: input.beadId,
18460
+ agent_name: input.agentName,
18461
+ project_key: input.projectKey,
18462
+ decision: {
18463
+ files_added: input.filesAdded || [],
18464
+ files_removed: input.filesRemoved || [],
18465
+ coordinator_approved: input.coordinatorApproved
18466
+ },
18467
+ rationale: input.reason
18468
+ });
18469
+ await db.close?.();
18470
+ return trace.id;
18471
+ } catch (error45) {
18472
+ console.warn("[decision-trace] Failed to trace scope_change:", error45);
18473
+ return "";
18474
+ }
18475
+ }
18476
+ async function getEpicDecisionTraces(projectKey, epicId) {
18477
+ try {
18478
+ const { getDecisionTracesByEpic } = await import("swarm-mail");
18479
+ const db = await getTraceDb(projectKey);
18480
+ const traces = await getDecisionTracesByEpic(db, epicId);
18481
+ await db.close?.();
18482
+ return traces;
18483
+ } catch (error45) {
18484
+ console.warn("[decision-trace] Failed to query epic traces:", error45);
18485
+ return [];
18486
+ }
18487
+ }
18488
+ async function getDecisionTracesByType(projectKey, decisionType) {
18489
+ try {
18490
+ const { getDecisionTracesByType: queryByType } = await import("swarm-mail");
18491
+ const db = await getTraceDb(projectKey);
18492
+ const traces = await queryByType(db, decisionType);
18493
+ await db.close?.();
18494
+ return traces;
18495
+ } catch (error45) {
18496
+ console.warn("[decision-trace] Failed to query traces by type:", error45);
18497
+ return [];
18498
+ }
18499
+ }
18500
+ async function linkOutcomeToDecisionTrace(input) {
18501
+ try {
18502
+ const { findDecisionTraceByBead, linkOutcomeToTrace } = await import("swarm-mail");
18503
+ const db = await getTraceDb(input.projectKey);
18504
+ const trace = await findDecisionTraceByBead(db, input.beadId);
18505
+ if (!trace) {
18506
+ await db.close?.();
18507
+ return false;
18508
+ }
18509
+ await linkOutcomeToTrace(db, trace.id, input.outcomeEventId);
18510
+ await db.close?.();
18511
+ return true;
18512
+ } catch (error45) {
18513
+ console.warn("[decision-trace] Failed to link outcome to trace:", error45);
18514
+ return false;
18515
+ }
18516
+ }
18517
+ var init_decision_trace_integration = () => {};
18518
+
18287
18519
  // src/anti-patterns.ts
18288
18520
  var exports_anti_patterns = {};
18289
18521
  __export(exports_anti_patterns, {
@@ -18809,9 +19041,11 @@ async function execSemanticMemory(args) {
18809
19041
  stderr: "pipe"
18810
19042
  });
18811
19043
  try {
19044
+ const TIMEOUT_MS = 30000;
19045
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Process timed out after 30s")), TIMEOUT_MS));
18812
19046
  const stdout = Buffer.from(await new Response(proc.stdout).arrayBuffer());
18813
19047
  const stderr = Buffer.from(await new Response(proc.stderr).arrayBuffer());
18814
- const exitCode = await proc.exited;
19048
+ const exitCode = await Promise.race([proc.exited, timeoutPromise]);
18815
19049
  return { exitCode, stdout, stderr };
18816
19050
  } finally {
18817
19051
  proc.kill();
@@ -39785,13 +40019,17 @@ var toolCheckers = {
39785
40019
  stderr: "pipe"
39786
40020
  });
39787
40021
  const timeout = setTimeout(() => proc.kill(), BUNX_TIMEOUT_MS);
39788
- const exitCode = await proc.exited;
39789
- clearTimeout(timeout);
39790
- return {
39791
- available: exitCode === 0,
39792
- checkedAt: new Date().toISOString(),
39793
- version: "bunx"
39794
- };
40022
+ try {
40023
+ const exitCode = await proc.exited;
40024
+ return {
40025
+ available: exitCode === 0,
40026
+ checkedAt: new Date().toISOString(),
40027
+ version: "bunx"
40028
+ };
40029
+ } finally {
40030
+ clearTimeout(timeout);
40031
+ proc.kill();
40032
+ }
39795
40033
  } catch (e) {
39796
40034
  return {
39797
40035
  available: false,
@@ -39864,13 +40102,17 @@ var toolCheckers = {
39864
40102
  stderr: "pipe"
39865
40103
  });
39866
40104
  const timeout = setTimeout(() => proc.kill(), BUNX_TIMEOUT_MS);
39867
- const exitCode = await proc.exited;
39868
- clearTimeout(timeout);
39869
- return {
39870
- available: exitCode === 0,
39871
- checkedAt: new Date().toISOString(),
39872
- version: "bunx-semantic-memory"
39873
- };
40105
+ try {
40106
+ const exitCode = await proc.exited;
40107
+ return {
40108
+ available: exitCode === 0,
40109
+ checkedAt: new Date().toISOString(),
40110
+ version: "bunx-semantic-memory"
40111
+ };
40112
+ } finally {
40113
+ clearTimeout(timeout);
40114
+ proc.kill();
40115
+ }
39874
40116
  } catch (e) {
39875
40117
  return {
39876
40118
  available: false,
@@ -40034,12 +40276,16 @@ async function runGitCommand(args) {
40034
40276
  stdout: "pipe",
40035
40277
  stderr: "pipe"
40036
40278
  });
40037
- const [stdout, stderr] = await Promise.all([
40038
- new Response(proc.stdout).text(),
40039
- new Response(proc.stderr).text()
40040
- ]);
40041
- const exitCode = await proc.exited;
40042
- return { exitCode, stdout, stderr };
40279
+ try {
40280
+ const [stdout, stderr] = await Promise.all([
40281
+ new Response(proc.stdout).text(),
40282
+ new Response(proc.stderr).text()
40283
+ ]);
40284
+ const exitCode = await proc.exited;
40285
+ return { exitCode, stdout, stderr };
40286
+ } finally {
40287
+ proc.kill();
40288
+ }
40043
40289
  }
40044
40290
 
40045
40291
  class HiveError extends Error {
@@ -40196,9 +40442,9 @@ var hive_create = tool({
40196
40442
  }
40197
40443
  });
40198
40444
  var hive_create_epic = tool({
40199
- description: "Create epic with subtasks in one atomic operation",
40445
+ description: "Create epic with subtasks atomically. REQUIRED: epic_title, subtasks (array with {title, files?}). Use after swarm_validate_decomposition confirms your decomposition is valid. Each subtask should list files it will modify to enable parallel work without conflicts.",
40200
40446
  args: {
40201
- epic_title: tool.schema.string().describe("Epic title"),
40447
+ epic_title: tool.schema.string().describe("Epic title (e.g., 'Implement user auth')"),
40202
40448
  epic_description: tool.schema.string().optional().describe("Epic description"),
40203
40449
  epic_id: tool.schema.string().optional().describe("Custom ID for the epic (e.g., 'phase-0')"),
40204
40450
  subtasks: tool.schema.array(tool.schema.object({
@@ -40217,6 +40463,28 @@ var hive_create_epic = tool({
40217
40463
  }).optional().describe("Recovery context from checkpoint compaction")
40218
40464
  },
40219
40465
  async execute(args, ctx) {
40466
+ const missing = [];
40467
+ if (!args.epic_title)
40468
+ missing.push("epic_title");
40469
+ if (!args.subtasks || args.subtasks.length === 0)
40470
+ missing.push("subtasks (array of subtask objects)");
40471
+ if (missing.length > 0) {
40472
+ return JSON.stringify({
40473
+ success: false,
40474
+ error: `Missing required parameters: ${missing.join(", ")}`,
40475
+ hint: "hive_create_epic creates an epic with subtasks atomically.",
40476
+ example: {
40477
+ epic_title: "Implement user authentication",
40478
+ epic_description: "Add login, logout, and session management",
40479
+ subtasks: [
40480
+ { title: "Create auth service", files: ["src/auth/service.ts"] },
40481
+ { title: "Add login endpoint", files: ["src/api/login.ts"] },
40482
+ { title: "Add session middleware", files: ["src/middleware/session.ts"] }
40483
+ ]
40484
+ },
40485
+ tip: "Each subtask should have a title and optionally files it will modify. This helps with file reservation and parallel execution."
40486
+ }, null, 2);
40487
+ }
40220
40488
  const validated = EpicCreateArgsSchema.parse(args);
40221
40489
  const projectKey = getHiveWorkingDirectory();
40222
40490
  const adapter = await getHiveAdapter(projectKey);
@@ -41270,90 +41538,7 @@ init_dist();
41270
41538
  init_zod();
41271
41539
  import { sendSwarmMessage } from "swarm-mail";
41272
41540
  init_eval_capture();
41273
-
41274
- // src/decision-trace-integration.ts
41275
- import {
41276
- createDecisionTrace,
41277
- createEntityLink
41278
- } from "swarm-mail";
41279
- import { createLibSQLAdapter } from "swarm-mail";
41280
- import { getDatabasePath } from "swarm-mail";
41281
- async function getTraceDb(projectPath) {
41282
- const dbPath = getDatabasePath(projectPath);
41283
- return createLibSQLAdapter({ url: `file:${dbPath}` });
41284
- }
41285
- async function traceWorkerSpawn(input) {
41286
- try {
41287
- const db = await getTraceDb(input.projectKey);
41288
- const trace = await createDecisionTrace(db, {
41289
- decision_type: "worker_spawn",
41290
- epic_id: input.epicId,
41291
- bead_id: input.beadId,
41292
- agent_name: input.agentName,
41293
- project_key: input.projectKey,
41294
- decision: {
41295
- worker: input.workerName || "worker",
41296
- subtask_title: input.subtaskTitle,
41297
- files: input.files,
41298
- model: input.model,
41299
- spawn_order: input.spawnOrder,
41300
- is_parallel: input.isParallel
41301
- },
41302
- rationale: input.rationale || `Spawning worker for: ${input.subtaskTitle}`
41303
- });
41304
- for (const file2 of input.files) {
41305
- await createEntityLink(db, {
41306
- source_decision_id: trace.id,
41307
- target_entity_type: "file",
41308
- target_entity_id: file2,
41309
- link_type: "assigns_file",
41310
- strength: 1,
41311
- context: `File assigned to worker ${input.workerName || "worker"}`
41312
- });
41313
- }
41314
- await db.close?.();
41315
- return trace.id;
41316
- } catch (error45) {
41317
- console.warn("[decision-trace] Failed to trace worker_spawn:", error45);
41318
- return "";
41319
- }
41320
- }
41321
- async function traceReviewDecision(input) {
41322
- try {
41323
- const db = await getTraceDb(input.projectKey);
41324
- const trace = await createDecisionTrace(db, {
41325
- decision_type: "review_decision",
41326
- epic_id: input.epicId,
41327
- bead_id: input.beadId,
41328
- agent_name: input.agentName,
41329
- project_key: input.projectKey,
41330
- decision: {
41331
- status: input.status,
41332
- worker_id: input.workerId,
41333
- issues_count: input.issues?.length || 0,
41334
- attempt_number: input.attemptNumber,
41335
- remaining_attempts: input.remainingAttempts
41336
- },
41337
- rationale: input.rationale || input.summary || `Review ${input.status}`,
41338
- inputs_gathered: input.issues ? [{ source: "code_review", issues: input.issues }] : undefined
41339
- });
41340
- await createEntityLink(db, {
41341
- source_decision_id: trace.id,
41342
- target_entity_type: "agent",
41343
- target_entity_id: input.workerId,
41344
- link_type: "reviewed_work_by",
41345
- strength: 1,
41346
- context: `Review ${input.status} for ${input.workerId}`
41347
- });
41348
- await db.close?.();
41349
- return trace.id;
41350
- } catch (error45) {
41351
- console.warn("[decision-trace] Failed to trace review_decision:", error45);
41352
- return "";
41353
- }
41354
- }
41355
-
41356
- // src/swarm-review.ts
41541
+ init_decision_trace_integration();
41357
41542
  var ReviewIssueSchema = exports_external.object({
41358
41543
  file: exports_external.string(),
41359
41544
  line: exports_external.number().optional(),
@@ -42207,17 +42392,41 @@ var swarm_status = tool({
42207
42392
  }
42208
42393
  });
42209
42394
  var swarm_progress = tool({
42210
- description: "Report progress on a subtask to coordinator",
42395
+ description: "Report progress on a subtask to coordinator. REQUIRED: project_key, agent_name, bead_id, status. Call periodically (every 25% or when blocked) to keep coordinator informed. Use status='blocked' with message explaining the blocker if you're stuck.",
42211
42396
  args: {
42212
- project_key: tool.schema.string().describe("Project path"),
42213
- agent_name: tool.schema.string().describe("Your Agent Mail name"),
42214
- bead_id: tool.schema.string().describe("Subtask bead ID"),
42397
+ project_key: tool.schema.string().describe("Project path (e.g., '/Users/name/project')"),
42398
+ agent_name: tool.schema.string().describe("Your agent name from swarmmail_init"),
42399
+ bead_id: tool.schema.string().describe("Task ID from your spawn prompt or hive cell"),
42215
42400
  status: tool.schema.enum(["in_progress", "blocked", "completed", "failed"]).describe("Current status"),
42216
42401
  message: tool.schema.string().optional().describe("Progress message or blockers"),
42217
42402
  progress_percent: tool.schema.number().min(0).max(100).optional().describe("Completion percentage"),
42218
42403
  files_touched: tool.schema.array(tool.schema.string()).optional().describe("Files modified so far")
42219
42404
  },
42220
42405
  async execute(args) {
42406
+ const missing = [];
42407
+ if (!args.bead_id)
42408
+ missing.push("bead_id");
42409
+ if (!args.project_key)
42410
+ missing.push("project_key");
42411
+ if (!args.agent_name)
42412
+ missing.push("agent_name");
42413
+ if (!args.status)
42414
+ missing.push("status");
42415
+ if (missing.length > 0) {
42416
+ return JSON.stringify({
42417
+ success: false,
42418
+ error: `Missing required parameters: ${missing.join(", ")}`,
42419
+ hint: "swarm_progress reports task progress to the coordinator.",
42420
+ example: {
42421
+ project_key: "/path/to/project",
42422
+ agent_name: "your-agent-name",
42423
+ bead_id: "your-task-id from spawn",
42424
+ status: "in_progress",
42425
+ progress_percent: 50,
42426
+ message: "Completed X, working on Y"
42427
+ }
42428
+ }, null, 2);
42429
+ }
42221
42430
  const progress = {
42222
42431
  bead_id: args.bead_id,
42223
42432
  agent_name: args.agent_name,
@@ -42343,12 +42552,12 @@ ${args.files_affected.map((f) => `- \`${f}\``).join(`
42343
42552
  }
42344
42553
  });
42345
42554
  var swarm_complete = tool({
42346
- description: "Mark subtask complete with Verification Gate. Runs typecheck and tests before allowing completion.",
42555
+ description: "Mark subtask complete with Verification Gate. REQUIRED: project_key, agent_name, bead_id (from your task assignment), summary, start_time (Date.now() from when you started). Before calling: 1) hivemind_store your learnings, 2) list files_touched for verification. Runs typecheck/tests before finalizing.",
42347
42556
  args: {
42348
- project_key: tool.schema.string().describe("Project path"),
42349
- agent_name: tool.schema.string().describe("Your Agent Mail name"),
42350
- bead_id: tool.schema.string().describe("Subtask bead ID"),
42351
- summary: tool.schema.string().describe("Brief summary of work done"),
42557
+ project_key: tool.schema.string().describe("Project path (e.g., '/Users/name/project')"),
42558
+ agent_name: tool.schema.string().describe("Your agent name from swarmmail_init"),
42559
+ bead_id: tool.schema.string().describe("Task ID from your spawn prompt or hive cell"),
42560
+ summary: tool.schema.string().describe("What you accomplished (1-3 sentences)"),
42352
42561
  evaluation: tool.schema.string().optional().describe("Self-evaluation JSON (Evaluation schema)"),
42353
42562
  files_touched: tool.schema.array(tool.schema.string()).optional().describe("Files modified - will be verified (typecheck, tests)"),
42354
42563
  skip_verification: tool.schema.boolean().optional().describe("Skip ALL verification (typecheck, tests). Use sparingly! (default: false)"),
@@ -42359,6 +42568,33 @@ var swarm_complete = tool({
42359
42568
  skip_review: tool.schema.boolean().optional().describe("Skip review gate check (default: false). Use only for tasks that don't require coordinator review.")
42360
42569
  },
42361
42570
  async execute(args, _ctx) {
42571
+ const missing = [];
42572
+ if (!args.bead_id)
42573
+ missing.push("bead_id");
42574
+ if (!args.project_key)
42575
+ missing.push("project_key");
42576
+ if (!args.agent_name)
42577
+ missing.push("agent_name");
42578
+ if (!args.summary)
42579
+ missing.push("summary");
42580
+ if (args.start_time === undefined)
42581
+ missing.push("start_time");
42582
+ if (missing.length > 0) {
42583
+ return JSON.stringify({
42584
+ success: false,
42585
+ error: `Missing required parameters: ${missing.join(", ")}`,
42586
+ hint: "swarm_complete marks a subtask as done. All parameters are required.",
42587
+ example: {
42588
+ project_key: "/path/to/project",
42589
+ agent_name: "your-agent-name",
42590
+ bead_id: "epic-id.subtask-num OR cell-id from hive",
42591
+ summary: "Brief description of what you completed",
42592
+ start_time: Date.now(),
42593
+ files_touched: ["src/file1.ts", "src/file2.ts"]
42594
+ },
42595
+ tip: "The bead_id comes from swarm_spawn_subtask or hive_create. Check your task assignment for the correct ID."
42596
+ }, null, 2);
42597
+ }
42362
42598
  const epicId = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
42363
42599
  if (!args.skip_review) {
42364
42600
  const reviewStatusResult = getReviewStatus(args.bead_id);
@@ -42559,6 +42795,7 @@ This will be recorded as a negative learning signal.`;
42559
42795
  }
42560
42796
  const completionDurationMs = Date.now() - args.start_time;
42561
42797
  const eventEpicId = cell.parent_id || (args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id);
42798
+ let outcomeEventId;
42562
42799
  try {
42563
42800
  const event = createEvent3("subtask_outcome", {
42564
42801
  project_key: args.project_key,
@@ -42573,10 +42810,23 @@ This will be recorded as a negative learning signal.`;
42573
42810
  scope_violation: contractValidation ? !contractValidation.valid : undefined,
42574
42811
  violation_files: contractValidation?.violations
42575
42812
  });
42576
- await appendEvent2(event, args.project_key);
42813
+ const savedEvent = await appendEvent2(event, args.project_key);
42814
+ outcomeEventId = savedEvent.id;
42577
42815
  } catch (error45) {
42578
42816
  console.warn("[swarm_complete] Failed to emit SubtaskOutcomeEvent:", error45);
42579
42817
  }
42818
+ if (outcomeEventId) {
42819
+ try {
42820
+ const { linkOutcomeToDecisionTrace: linkOutcomeToDecisionTrace2 } = await Promise.resolve().then(() => (init_decision_trace_integration(), exports_decision_trace_integration));
42821
+ await linkOutcomeToDecisionTrace2({
42822
+ projectKey: args.project_key,
42823
+ beadId: args.bead_id,
42824
+ outcomeEventId
42825
+ });
42826
+ } catch (error45) {
42827
+ console.warn("[swarm_complete] Failed to link outcome to decision trace:", error45);
42828
+ }
42829
+ }
42580
42830
  try {
42581
42831
  const workerCompletedEvent = createEvent3("worker_completed", {
42582
42832
  project_key: args.project_key,
@@ -43538,6 +43788,7 @@ ${skillBody}`, "utf-8");
43538
43788
  // src/swarm-prompts.ts
43539
43789
  init_eval_capture();
43540
43790
  init_memory_tools();
43791
+ init_decision_trace_integration();
43541
43792
  var DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
43542
43793
 
43543
43794
  ## Task
@@ -43746,6 +43997,26 @@ Before writing code:
43746
43997
  Begin work on your subtask now.`;
43747
43998
  var SUBTASK_PROMPT_V2 = `You are a swarm agent working on: **{subtask_title}**
43748
43999
 
44000
+ ╔═══════════════════════════════════════════════════════════════════════════════╗
44001
+ ║ ║
44002
+ ║ \uD83D\uDED1 STOP - READ THIS FIRST - BEFORE ANY EDIT OR WRITE \uD83D\uDED1 ║
44003
+ ║ ║
44004
+ ║ You MUST do these 3 things BEFORE your first Edit/Write call: ║
44005
+ ║ ║
44006
+ ║ 1️⃣ hivemind_find(query="<your task keywords>", limit=5, expand=true) ║
44007
+ ║ → Check if past agents already solved this ║
44008
+ ║ → Find gotchas, patterns, warnings ║
44009
+ ║ ║
44010
+ ║ 2️⃣ skills_list() then skills_use(name="<relevant>") ║
44011
+ ║ → testing-patterns, swarm-coordination, system-design ║
44012
+ ║ ║
44013
+ ║ 3️⃣ swarmmail_send(to=["coordinator"], ...) when blocked ║
44014
+ ║ → Don't spin >5min - ASK FOR HELP ║
44015
+ ║ ║
44016
+ ║ SKIPPING THESE = wasted time repeating solved problems ║
44017
+ ║ ║
44018
+ ╚═══════════════════════════════════════════════════════════════════════════════╝
44019
+
43749
44020
  ## [IDENTITY]
43750
44021
  Agent: (assigned at spawn)
43751
44022
  Cell: {bead_id}
@@ -1 +1 @@
1
- {"version":3,"file":"tool-availability.d.ts","sourceRoot":"","sources":["../src/tool-availability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,MAAM,MAAM,QAAQ,GAChB,iBAAiB,GACjB,MAAM,GACN,UAAU,GACV,MAAM,GACN,OAAO,GACP,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAuRD;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAWnE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,gBAAgB,CAAC,CAO3B;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAC5C,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAChC,CA0BA;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAQpD;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/D;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACxB,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CASZ;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CASxB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,GAC5C,MAAM,CAWR"}
1
+ {"version":3,"file":"tool-availability.d.ts","sourceRoot":"","sources":["../src/tool-availability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,MAAM,MAAM,QAAQ,GAChB,iBAAiB,GACjB,MAAM,GACN,UAAU,GACV,MAAM,GACN,OAAO,GACP,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AA6RD;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAWnE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,gBAAgB,CAAC,CAO3B;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAC5C,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAChC,CA0BA;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAQpD;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/D;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACxB,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CASZ;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CASxB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,GAC5C,MAAM,CAWR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm-plugin",
3
- "version": "0.57.6",
3
+ "version": "0.59.0",
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",
@@ -70,7 +70,7 @@
70
70
  "minimatch": "^10.1.1",
71
71
  "pino": "^9.6.0",
72
72
  "pino-roll": "^1.3.0",
73
- "swarm-mail": "1.10.2",
73
+ "swarm-mail": "1.10.3",
74
74
  "yaml": "^2.8.2",
75
75
  "zod": "4.1.8"
76
76
  },