opencode-swarm-plugin 0.16.0 → 0.17.1

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/dist/plugin.js CHANGED
@@ -29829,7 +29829,7 @@ function parseBead(output) {
29829
29829
  const parsed = JSON.parse(output);
29830
29830
  const data = Array.isArray(parsed) ? parsed[0] : parsed;
29831
29831
  if (!data) {
29832
- throw new BeadError("No bead data in response", "parse");
29832
+ throw new BeadError("No bead data in response. The bd CLI may not be installed or returned unexpected output. Try: Run 'bd --version' to verify installation, or check if .beads/ directory exists in project.", "parse");
29833
29833
  }
29834
29834
  return BeadSchema.parse(data);
29835
29835
  } catch (error45) {
@@ -29839,7 +29839,7 @@ function parseBead(output) {
29839
29839
  if (error45 instanceof BeadError) {
29840
29840
  throw error45;
29841
29841
  }
29842
- throw new BeadError(`Failed to parse bead JSON: ${output}`, "parse");
29842
+ throw new BeadError(`Failed to parse bead JSON because output is malformed. Try: Check if bd CLI is up to date with 'bd --version' (need v1.0.0+), or inspect output: ${output.slice(0, 100)}`, "parse");
29843
29843
  }
29844
29844
  }
29845
29845
  function parseBeads(output) {
@@ -29850,7 +29850,7 @@ function parseBeads(output) {
29850
29850
  if (error45 instanceof exports_external.ZodError) {
29851
29851
  throw new BeadValidationError(`Invalid beads data: ${error45.message}`, error45);
29852
29852
  }
29853
- throw new BeadError(`Failed to parse beads JSON: ${output}`, "parse");
29853
+ throw new BeadError(`Failed to parse beads JSON because output is malformed. Try: Check if bd CLI is up to date with 'bd --version' (need v1.0.0+), or inspect output: ${output.slice(0, 100)}`, "parse");
29854
29854
  }
29855
29855
  }
29856
29856
  var beads_create = tool({
@@ -29867,14 +29867,14 @@ var beads_create = tool({
29867
29867
  const cmdParts = buildCreateCommand(validated);
29868
29868
  const result = await runBdCommand(cmdParts.slice(1));
29869
29869
  if (result.exitCode !== 0) {
29870
- throw new BeadError(`Failed to create bead: ${result.stderr}`, cmdParts.join(" "), result.exitCode, result.stderr);
29870
+ throw new BeadError(`Failed to create bead because bd command exited with code ${result.exitCode}. Error: ${result.stderr}. Try: Check if beads initialized with 'bd init' in project root, or verify .beads/ directory exists.`, cmdParts.join(" "), result.exitCode, result.stderr);
29871
29871
  }
29872
29872
  const stdout = result.stdout.trim();
29873
29873
  if (!stdout) {
29874
- throw new BeadError("bd create returned empty output", cmdParts.join(" "), 0, "Empty stdout");
29874
+ throw new BeadError("bd create returned empty output because command produced no response. Try: Check if bd is properly installed with 'bd --version', or run 'bd list' to test basic functionality.", cmdParts.join(" "), 0, "Empty stdout");
29875
29875
  }
29876
29876
  if (stdout.startsWith("error:") || stdout.startsWith("Error:")) {
29877
- throw new BeadError(`bd create failed: ${stdout}`, cmdParts.join(" "), 0, stdout);
29877
+ throw new BeadError(`bd create failed because command returned error in stdout: ${stdout}. Try: Check error message above, verify beads initialized with 'bd init', or check .beads/issues.jsonl for corruption.`, cmdParts.join(" "), 0, stdout);
29878
29878
  }
29879
29879
  const bead = parseBead(stdout);
29880
29880
  return JSON.stringify(bead, null, 2);
@@ -29906,7 +29906,7 @@ var beads_create_epic = tool({
29906
29906
  });
29907
29907
  const epicResult = await runBdCommand(epicCmd.slice(1));
29908
29908
  if (epicResult.exitCode !== 0) {
29909
- throw new BeadError(`Failed to create epic: ${epicResult.stderr}`, epicCmd.join(" "), epicResult.exitCode);
29909
+ throw new BeadError(`Failed to create epic because bd command failed: ${epicResult.stderr}. Try: Verify beads initialized with 'bd init', check if .beads/ directory is writable, or run 'bd list' to test basic functionality.`, epicCmd.join(" "), epicResult.exitCode);
29910
29910
  }
29911
29911
  const epic = parseBead(epicResult.stdout);
29912
29912
  created.push(epic);
@@ -29924,7 +29924,7 @@ var beads_create_epic = tool({
29924
29924
  });
29925
29925
  const subtaskResult = await runBdCommand(subtaskCmd.slice(1));
29926
29926
  if (subtaskResult.exitCode !== 0) {
29927
- throw new BeadError(`Failed to create subtask: ${subtaskResult.stderr}`, subtaskCmd.join(" "), subtaskResult.exitCode);
29927
+ throw new BeadError(`Failed to create subtask because bd command failed: ${subtaskResult.stderr}. Try: Check if parent epic exists with 'bd show ${epic.id}', verify .beads/issues.jsonl is not corrupted, or check for invalid characters in title.`, subtaskCmd.join(" "), subtaskResult.exitCode);
29928
29928
  }
29929
29929
  const subtaskBead = parseBead(subtaskResult.stdout);
29930
29930
  created.push(subtaskBead);
@@ -29980,7 +29980,7 @@ ${rollbackErrors.join(`
29980
29980
 
29981
29981
  No beads to rollback.`;
29982
29982
  }
29983
- throw new BeadError(`Epic creation failed: ${errorMsg}${rollbackInfo}`, "beads_create_epic", 1);
29983
+ throw new BeadError(`Epic creation failed: ${errorMsg}${rollbackInfo}. Try: If rollback failed, manually close beads with 'bd close <id> --reason "Rollback"', check .beads/issues.jsonl for partial state, or re-run beads_create_epic with corrected parameters.`, "beads_create_epic", 1);
29984
29984
  }
29985
29985
  }
29986
29986
  });
@@ -30008,7 +30008,7 @@ var beads_query = tool({
30008
30008
  }
30009
30009
  const result = await runBdCommand(cmd.slice(1));
30010
30010
  if (result.exitCode !== 0) {
30011
- throw new BeadError(`Failed to query beads: ${result.stderr}`, cmd.join(" "), result.exitCode);
30011
+ throw new BeadError(`Failed to query beads because bd command failed: ${result.stderr}. Try: Check if beads initialized with 'bd init', verify .beads/ directory exists, or run 'bd --version' to check CLI version.`, cmd.join(" "), result.exitCode);
30012
30012
  }
30013
30013
  const beads = parseBeads(result.stdout);
30014
30014
  const limited = beads.slice(0, validated.limit);
@@ -30038,7 +30038,7 @@ var beads_update = tool({
30038
30038
  cmd.push("--json");
30039
30039
  const result = await runBdCommand(cmd.slice(1));
30040
30040
  if (result.exitCode !== 0) {
30041
- throw new BeadError(`Failed to update bead: ${result.stderr}`, cmd.join(" "), result.exitCode);
30041
+ throw new BeadError(`Failed to update bead because bd command failed: ${result.stderr}. Try: Verify bead exists with 'bd show ${validated.id}', check for invalid status values, or inspect .beads/issues.jsonl for corruption.`, cmd.join(" "), result.exitCode);
30042
30042
  }
30043
30043
  const bead = parseBead(result.stdout);
30044
30044
  return JSON.stringify(bead, null, 2);
@@ -30062,7 +30062,7 @@ var beads_close = tool({
30062
30062
  ];
30063
30063
  const result = await runBdCommand(cmd.slice(1));
30064
30064
  if (result.exitCode !== 0) {
30065
- throw new BeadError(`Failed to close bead: ${result.stderr}`, cmd.join(" "), result.exitCode);
30065
+ throw new BeadError(`Failed to close bead because bd command failed: ${result.stderr}. Try: Verify bead exists and is not already closed with 'beads_query(status="closed")' or 'bd show ${validated.id}', check if bead ID is correct.`, cmd.join(" "), result.exitCode);
30066
30066
  }
30067
30067
  const bead = parseBead(result.stdout);
30068
30068
  return `Closed ${bead.id}: ${validated.reason}`;
@@ -30082,7 +30082,7 @@ var beads_start = tool({
30082
30082
  "--json"
30083
30083
  ]);
30084
30084
  if (result.exitCode !== 0) {
30085
- throw new BeadError(`Failed to start bead: ${result.stderr}`, `bd update ${args.id} --status in_progress --json`, result.exitCode);
30085
+ throw new BeadError(`Failed to start bead because bd update command failed: ${result.stderr}. Try: Verify bead exists with 'bd show ${args.id}', check if already in_progress with 'beads_query(status="in_progress")', or use beads_update directly.`, `bd update ${args.id} --status in_progress --json`, result.exitCode);
30086
30086
  }
30087
30087
  const bead = parseBead(result.stdout);
30088
30088
  return `Started: ${bead.id}`;
@@ -30094,7 +30094,7 @@ var beads_ready = tool({
30094
30094
  async execute(args, ctx) {
30095
30095
  const result = await runBdCommand(["ready", "--json"]);
30096
30096
  if (result.exitCode !== 0) {
30097
- throw new BeadError(`Failed to get ready beads: ${result.stderr}`, "bd ready --json", result.exitCode);
30097
+ throw new BeadError(`Failed to get ready beads because bd ready command failed: ${result.stderr}. Try: Check if beads initialized with 'bd init', verify .beads/ directory is readable, or run 'bd list --json' to test basic query.`, "bd ready --json", result.exitCode);
30098
30098
  }
30099
30099
  const beads = parseBeads(result.stdout);
30100
30100
  if (beads.length === 0) {
@@ -30127,7 +30127,7 @@ var beads_sync = tool({
30127
30127
  };
30128
30128
  const flushResult = await withTimeout(runBdCommand(["sync", "--flush-only"]), TIMEOUT_MS, "bd sync --flush-only");
30129
30129
  if (flushResult.exitCode !== 0) {
30130
- throw new BeadError(`Failed to flush beads: ${flushResult.stderr}`, "bd sync --flush-only", flushResult.exitCode);
30130
+ throw new BeadError(`Failed to flush beads because bd sync failed: ${flushResult.stderr}. Try: Check if .beads/ directory is writable, verify no corrupted JSONL files, or run 'bd list' to test basic beads functionality.`, "bd sync --flush-only", flushResult.exitCode);
30131
30131
  }
30132
30132
  const beadsStatusResult = await runGitCommand([
30133
30133
  "status",
@@ -30138,11 +30138,11 @@ var beads_sync = tool({
30138
30138
  if (hasChanges) {
30139
30139
  const addResult = await runGitCommand(["add", ".beads/"]);
30140
30140
  if (addResult.exitCode !== 0) {
30141
- throw new BeadError(`Failed to stage beads: ${addResult.stderr}`, "git add .beads/", addResult.exitCode);
30141
+ throw new BeadError(`Failed to stage beads because git add failed: ${addResult.stderr}. Try: Check if .beads/ directory exists, verify git is initialized with 'git status', or check for .gitignore patterns blocking .beads/.`, "git add .beads/", addResult.exitCode);
30142
30142
  }
30143
30143
  const commitResult = await withTimeout(runGitCommand(["commit", "-m", "chore: sync beads"]), TIMEOUT_MS, "git commit");
30144
30144
  if (commitResult.exitCode !== 0 && !commitResult.stdout.includes("nothing to commit")) {
30145
- throw new BeadError(`Failed to commit beads: ${commitResult.stderr}`, "git commit", commitResult.exitCode);
30145
+ throw new BeadError(`Failed to commit beads because git commit failed: ${commitResult.stderr}. Try: Check git config (user.name, user.email) with 'git config --list', verify working tree is clean, or check for pre-commit hooks blocking commit.`, "git commit", commitResult.exitCode);
30146
30146
  }
30147
30147
  }
30148
30148
  if (autoPull) {
@@ -30181,7 +30181,7 @@ var beads_sync = tool({
30181
30181
  }
30182
30182
  }
30183
30183
  if (pullResult.exitCode !== 0) {
30184
- throw new BeadError(`Failed to pull: ${pullResult.stderr}`, "git pull --rebase", pullResult.exitCode);
30184
+ throw new BeadError(`Failed to pull because git pull --rebase failed: ${pullResult.stderr}. Try: Resolve merge conflicts manually with 'git status', check if remote is accessible with 'git remote -v', or use skip_verification to bypass automatic pull.`, "git pull --rebase", pullResult.exitCode);
30185
30185
  }
30186
30186
  const importResult = await withTimeout(runBdCommand(["sync", "--import-only"]), TIMEOUT_MS, "bd sync --import-only");
30187
30187
  if (importResult.exitCode !== 0) {
@@ -30190,7 +30190,7 @@ var beads_sync = tool({
30190
30190
  }
30191
30191
  const pushResult = await withTimeout(runGitCommand(["push"]), TIMEOUT_MS, "git push");
30192
30192
  if (pushResult.exitCode !== 0) {
30193
- throw new BeadError(`Failed to push: ${pushResult.stderr}`, "git push", pushResult.exitCode);
30193
+ throw new BeadError(`Failed to push because git push failed: ${pushResult.stderr}. Try: Check if remote branch is up to date with 'git pull --rebase', verify push permissions, check remote URL with 'git remote -v', or force push with 'git push --force-with-lease' if safe.`, "git push", pushResult.exitCode);
30194
30194
  }
30195
30195
  const statusResult = await runGitCommand(["status", "--porcelain"]);
30196
30196
  const status = statusResult.stdout.trim();
@@ -30210,7 +30210,7 @@ var beads_link_thread = tool({
30210
30210
  async execute(args, ctx) {
30211
30211
  const queryResult = await runBdCommand(["show", args.bead_id, "--json"]);
30212
30212
  if (queryResult.exitCode !== 0) {
30213
- throw new BeadError(`Failed to get bead: ${queryResult.stderr}`, `bd show ${args.bead_id} --json`, queryResult.exitCode);
30213
+ throw new BeadError(`Failed to get bead because bd show command failed: ${queryResult.stderr}. Try: Verify bead ID is correct with 'beads_query()', check if bead exists with 'bd list --json', or check .beads/issues.jsonl for valid entries.`, `bd show ${args.bead_id} --json`, queryResult.exitCode);
30214
30214
  }
30215
30215
  const bead = parseBead(queryResult.stdout);
30216
30216
  const existingDesc = bead.description || "";
@@ -30229,7 +30229,7 @@ ${threadMarker}` : threadMarker;
30229
30229
  "--json"
30230
30230
  ]);
30231
30231
  if (updateResult.exitCode !== 0) {
30232
- throw new BeadError(`Failed to update bead: ${updateResult.stderr}`, `bd update ${args.bead_id} -d ...`, updateResult.exitCode);
30232
+ throw new BeadError(`Failed to update bead because bd update command failed: ${updateResult.stderr}. Try: Verify bead exists with 'bd show ${args.bead_id}', check for invalid characters in description, or inspect .beads/issues.jsonl for corruption.`, `bd update ${args.bead_id} -d ...`, updateResult.exitCode);
30233
30233
  }
30234
30234
  return `Linked bead ${args.bead_id} to thread ${args.thread_id}`;
30235
30235
  }
@@ -33846,7 +33846,7 @@ async function runVerificationGate(filesTouched, skipUbs = false) {
33846
33846
  };
33847
33847
  if (!ubsStep.passed) {
33848
33848
  ubsStep.error = `Found ${ubsResult.summary.critical} critical bugs`;
33849
- blockers.push(`UBS: ${ubsResult.summary.critical} critical bugs found`);
33849
+ blockers.push(`UBS found ${ubsResult.summary.critical} critical bug(s). Try: Run 'ubs scan ${filesTouched.join(" ")}' to see details, fix critical bugs in reported files, or use skip_ubs_scan=true to bypass (not recommended).`);
33850
33850
  }
33851
33851
  steps.push(ubsStep);
33852
33852
  } else {
@@ -33863,12 +33863,12 @@ async function runVerificationGate(filesTouched, skipUbs = false) {
33863
33863
  const typecheckStep = await runTypecheckVerification();
33864
33864
  steps.push(typecheckStep);
33865
33865
  if (!typecheckStep.passed && !typecheckStep.skipped) {
33866
- blockers.push(`Typecheck: ${typecheckStep.error?.slice(0, 100) || "failed"}`);
33866
+ blockers.push(`Typecheck failed: ${typecheckStep.error?.slice(0, 100) || "type errors found"}. Try: Run 'tsc --noEmit' to see full errors, check tsconfig.json configuration, or fix reported type errors in modified files.`);
33867
33867
  }
33868
33868
  const testStep = await runTestVerification(filesTouched);
33869
33869
  steps.push(testStep);
33870
33870
  if (!testStep.passed && !testStep.skipped) {
33871
- blockers.push(`Tests: ${testStep.error?.slice(0, 100) || "failed"}`);
33871
+ blockers.push(`Tests failed: ${testStep.error?.slice(0, 100) || "test failures"}. Try: Run 'bun test ${testStep.command.split(" ").slice(2).join(" ")}' to see full output, check test assertions, or fix failing tests in modified files.`);
33872
33872
  }
33873
33873
  const passedCount = steps.filter((s) => s.passed).length;
33874
33874
  const skippedCount = steps.filter((s) => s.skipped).length;
@@ -33923,8 +33923,8 @@ async function runUbsScan(files) {
33923
33923
  }
33924
33924
  };
33925
33925
  } catch (error45) {
33926
- console.error(`[swarm] CRITICAL: UBS scan failed to parse JSON output:`, error45);
33927
- console.error(`[swarm] Raw output:`, output);
33926
+ console.error(`[swarm] CRITICAL: UBS scan failed to parse JSON output because output is malformed:`, error45);
33927
+ console.error(`[swarm] Raw output: ${output}. Try: Run 'ubs doctor' to check installation, verify UBS version with 'ubs --version' (need v1.0.0+), or check if UBS supports --json flag.`);
33928
33928
  return {
33929
33929
  exitCode: result.exitCode,
33930
33930
  bugs: [],
@@ -34014,7 +34014,7 @@ var swarm_complete = tool({
34014
34014
  error: s.error?.slice(0, 200)
34015
34015
  }))
34016
34016
  },
34017
- hint: "Fix the failing checks and try again. Use skip_verification=true only as last resort.",
34017
+ hint: verificationResult.blockers.length > 0 ? `Fix these issues: ${verificationResult.blockers.map((b, i) => `${i + 1}. ${b}`).join(", ")}. Use skip_verification=true only as last resort.` : "Fix the failing checks and try again. Use skip_verification=true only as last resort.",
34018
34018
  gate_function: "IDENTIFY → RUN → READ → VERIFY → CLAIM (you are at VERIFY, claim blocked)"
34019
34019
  }, null, 2);
34020
34020
  }
@@ -34025,12 +34025,12 @@ var swarm_complete = tool({
34025
34025
  if (ubsResult && ubsResult.summary.critical > 0) {
34026
34026
  return JSON.stringify({
34027
34027
  success: false,
34028
- error: "UBS found critical bugs - fix before completing",
34028
+ error: `UBS found ${ubsResult.summary.critical} critical bug(s) that must be fixed before completing`,
34029
34029
  ubs_scan: {
34030
34030
  critical_count: ubsResult.summary.critical,
34031
34031
  bugs: ubsResult.bugs.filter((b) => b.severity === "critical")
34032
34032
  },
34033
- hint: "Fix the critical bugs and try again, or use skip_ubs_scan=true to bypass"
34033
+ hint: `Fix these critical bugs: ${ubsResult.bugs.filter((b) => b.severity === "critical").map((b) => `${b.file}:${b.line} - ${b.message}`).slice(0, 3).join("; ")}. Try: Run 'ubs scan ${args.files_touched?.join(" ") || "."} --json' for full report, fix reported issues, or use skip_ubs_scan=true to bypass (not recommended).`
34034
34034
  }, null, 2);
34035
34035
  }
34036
34036
  }
@@ -34056,7 +34056,7 @@ var swarm_complete = tool({
34056
34056
  }
34057
34057
  const closeResult = await Bun.$`bd close ${args.bead_id} --reason ${args.summary} --json`.quiet().nothrow();
34058
34058
  if (closeResult.exitCode !== 0) {
34059
- throw new SwarmError(`Failed to close bead: ${closeResult.stderr.toString()}`, "complete");
34059
+ throw new SwarmError(`Failed to close bead because bd close command failed: ${closeResult.stderr.toString()}. Try: Verify bead exists and is not already closed with 'bd show ${args.bead_id}', check if bead ID is correct with 'beads_query()', or use beads_close tool directly.`, "complete");
34060
34060
  }
34061
34061
  try {
34062
34062
  await releaseSwarmFiles({
@@ -35234,7 +35234,7 @@ class SemanticMemoryMandateStorage {
35234
35234
  async update(id, updates) {
35235
35235
  const existing = await this.get(id);
35236
35236
  if (!existing) {
35237
- throw new Error(`Mandate ${id} not found`);
35237
+ throw new Error(`Mandate '${id}' not found. Use list() to see available mandates.`);
35238
35238
  }
35239
35239
  const updated = { ...existing, ...updates };
35240
35240
  await this.store(updated);
@@ -35242,7 +35242,7 @@ class SemanticMemoryMandateStorage {
35242
35242
  async vote(vote) {
35243
35243
  const existing = await this.hasVoted(vote.mandate_id, vote.agent_name);
35244
35244
  if (existing) {
35245
- throw new Error(`Agent ${vote.agent_name} has already voted on mandate ${vote.mandate_id}`);
35245
+ throw new Error(`Agent '${vote.agent_name}' has already voted on mandate '${vote.mandate_id}'. Each agent can vote once per mandate to ensure fair consensus.`);
35246
35246
  }
35247
35247
  await this.storeInternal(this.config.collections.votes, vote, {
35248
35248
  id: vote.id,
@@ -35333,7 +35333,7 @@ class InMemoryMandateStorage {
35333
35333
  async update(id, updates) {
35334
35334
  const existing = await this.get(id);
35335
35335
  if (!existing) {
35336
- throw new Error(`Mandate ${id} not found`);
35336
+ throw new Error(`Mandate '${id}' not found. Use list() to see available mandates.`);
35337
35337
  }
35338
35338
  const updated = { ...existing, ...updates };
35339
35339
  this.entries.set(id, updated);
@@ -35341,7 +35341,7 @@ class InMemoryMandateStorage {
35341
35341
  async vote(vote) {
35342
35342
  const existing = await this.hasVoted(vote.mandate_id, vote.agent_name);
35343
35343
  if (existing) {
35344
- throw new Error(`Agent ${vote.agent_name} has already voted on mandate ${vote.mandate_id}`);
35344
+ throw new Error(`Agent '${vote.agent_name}' has already voted on mandate '${vote.mandate_id}'. Each agent can vote once per mandate to ensure fair consensus.`);
35345
35345
  }
35346
35346
  this.votes.set(vote.id, vote);
35347
35347
  }
@@ -35396,13 +35396,13 @@ function createMandateStorage(config2 = {}) {
35396
35396
  case "memory":
35397
35397
  return new InMemoryMandateStorage(fullConfig);
35398
35398
  default:
35399
- throw new Error(`Unknown storage backend: ${fullConfig.backend}`);
35399
+ throw new Error(`Unknown storage backend: '${fullConfig.backend}'. Valid backends are 'semantic-memory' or 'memory'.`);
35400
35400
  }
35401
35401
  }
35402
35402
  async function updateMandateStatus(mandateId, storage) {
35403
35403
  const entry = await storage.get(mandateId);
35404
35404
  if (!entry) {
35405
- throw new Error(`Mandate ${mandateId} not found`);
35405
+ throw new Error(`Mandate '${mandateId}' not found when calculating score. Use storage.list() to verify the mandate exists.`);
35406
35406
  }
35407
35407
  const score = await storage.calculateScore(mandateId);
35408
35408
  const previousStatus = entry.status;
@@ -35566,11 +35566,11 @@ var mandate_vote = tool({
35566
35566
  const storage = getMandateStorage();
35567
35567
  const mandate = await storage.get(validated.mandate_id);
35568
35568
  if (!mandate) {
35569
- throw new MandateError(`Mandate ${validated.mandate_id} not found`, "mandate_vote");
35569
+ throw new MandateError(`Mandate '${validated.mandate_id}' not found. Use mandate_list() to see available mandates, or check the ID is correct.`, "mandate_vote");
35570
35570
  }
35571
35571
  const hasVoted = await storage.hasVoted(validated.mandate_id, args.agent_name);
35572
35572
  if (hasVoted) {
35573
- throw new MandateError(`Agent ${args.agent_name} has already voted on mandate ${validated.mandate_id}`, "mandate_vote");
35573
+ throw new MandateError(`Agent '${args.agent_name}' has already voted on mandate '${validated.mandate_id}'. Each agent can vote once per mandate. This is expected behavior to prevent vote manipulation.`, "mandate_vote");
35574
35574
  }
35575
35575
  const vote = {
35576
35576
  id: generateVoteId(),
@@ -35713,7 +35713,7 @@ var mandate_stats = tool({
35713
35713
  if (args.mandate_id) {
35714
35714
  const mandate = await storage.get(args.mandate_id);
35715
35715
  if (!mandate) {
35716
- throw new MandateError(`Mandate ${args.mandate_id} not found`, "mandate_stats");
35716
+ throw new MandateError(`Mandate '${args.mandate_id}' not found. Use mandate_list() to see available mandates, or check the ID is correct.`, "mandate_stats");
35717
35717
  }
35718
35718
  const score = await storage.calculateScore(args.mandate_id);
35719
35719
  const votes = await storage.getVotes(args.mandate_id);
@@ -342,5 +342,64 @@ Not: Do Everything Inline → Run Out of Context → Fail
342
342
  - [ ] Workers spawned in parallel
343
343
  - [ ] Progress monitored via **swarmmail_inbox** (limit=5, no bodies)
344
344
  - [ ] PR created (or pushed to main)
345
+ - [ ] **ASCII art session summary** (MANDATORY - see below)
346
+
347
+ ## ASCII Art & Visual Flair (MANDATORY)
348
+
349
+ **We fucking LOVE visual output.** Every swarm completion MUST include:
350
+
351
+ ### Required Elements
352
+
353
+ 1. **ASCII banner** - Big text for the epic title or "SWARM COMPLETE"
354
+ 2. **Architecture diagram** - Show what was built with box-drawing chars
355
+ 3. **Stats summary** - Files, subtasks, releases in a nice box
356
+ 4. **Ship-it flourish** - Cow, bee, or memorable closer
357
+
358
+ ### Box-Drawing Reference
359
+
360
+ ```
361
+ ─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ (light)
362
+ ━ ┃ ┏ ┓ ┗ ┛ ┣ ┫ ┳ ┻ ╋ (heavy)
363
+ ═ ║ ╔ ╗ ╚ ╝ ╠ ╣ ╦ ╩ ╬ (double)
364
+ ```
365
+
366
+ ### Example Session Summary
367
+
368
+ ```
369
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
370
+ ┃ 🐝 SWARM COMPLETE 🐝 ┃
371
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
372
+
373
+ EPIC: Add User Authentication
374
+ ══════════════════════════════
375
+
376
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
377
+ │ OAuth │────▶│ Session │────▶│ Protected │
378
+ │ Provider │ │ Manager │ │ Routes │
379
+ └─────────────┘ └─────────────┘ └─────────────┘
380
+
381
+ SUBTASKS
382
+ ────────
383
+ ├── auth-123.1 ✓ OAuth provider setup
384
+ ├── auth-123.2 ✓ Session management
385
+ ├── auth-123.3 ✓ Protected route middleware
386
+ └── auth-123.4 ✓ Integration tests
387
+
388
+ STATS
389
+ ─────
390
+ Files Modified: 12
391
+ Tests Added: 24
392
+ Time: ~45 min
393
+
394
+ \ ^__^
395
+ \ (oo)\_______
396
+ (__)\ )\/\
397
+ ||----w |
398
+ || ||
399
+
400
+ moo. ship it.
401
+ ```
402
+
403
+ **This is not optional.** Make it beautiful. Make it memorable. PRs get shared.
345
404
 
346
405
  Begin with swarmmail_init and knowledge gathering now.
@@ -443,3 +443,73 @@ beads_sync();
443
443
  ```
444
444
 
445
445
  See `references/coordinator-patterns.md` for detailed patterns.
446
+
447
+ ## ASCII Art, Whimsy & Diagrams (MANDATORY)
448
+
449
+ **We fucking LOVE visual flair.** Every swarm session should include:
450
+
451
+ ### Session Summaries
452
+
453
+ When completing a swarm, output a beautiful summary with:
454
+
455
+ - ASCII art banner (figlet-style or custom)
456
+ - Box-drawing characters for structure
457
+ - Architecture diagrams showing what was built
458
+ - Stats (files modified, subtasks completed, etc.)
459
+ - A memorable quote or cow saying "ship it"
460
+
461
+ ### During Coordination
462
+
463
+ - Use tables for status updates
464
+ - Draw dependency trees with box characters
465
+ - Show progress with visual indicators
466
+
467
+ ### Examples
468
+
469
+ **Session Complete Banner:**
470
+
471
+ ```
472
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
473
+ ┃ 🐝 SWARM COMPLETE 🐝 ┃
474
+ ┃ ┃
475
+ ┃ Epic: Add Authentication ┃
476
+ ┃ Subtasks: 4/4 ✓ ┃
477
+ ┃ Files: 12 modified ┃
478
+ ┃ ┃
479
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
480
+ ```
481
+
482
+ **Architecture Diagram:**
483
+
484
+ ```
485
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
486
+ │ INPUT │────▶│ PROCESS │────▶│ OUTPUT │
487
+ └─────────────┘ └─────────────┘ └─────────────┘
488
+ ```
489
+
490
+ **Dependency Tree:**
491
+
492
+ ```
493
+ epic-123
494
+ ├── epic-123.1 ✓ Auth service
495
+ ├── epic-123.2 ✓ Database schema
496
+ ├── epic-123.3 ◐ API routes (in progress)
497
+ └── epic-123.4 ○ Tests (pending)
498
+ ```
499
+
500
+ **Ship It:**
501
+
502
+ ```
503
+ \ ^__^
504
+ \ (oo)\_______
505
+ (__)\ )\/\
506
+ ||----w |
507
+ || ||
508
+
509
+ moo. ship it.
510
+ ```
511
+
512
+ **This is not optional.** PRs get shared on Twitter. Session summaries get screenshot. Make them memorable. Make them beautiful. Make them fun.
513
+
514
+ Box-drawing characters: `─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ ━ ┃ ┏ ┓ ┗ ┛`
515
+ Progress indicators: `✓ ✗ ◐ ○ ● ▶ ▷ ★ ☆ 🐝`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm-plugin",
3
- "version": "0.16.0",
3
+ "version": "0.17.1",
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",
package/src/beads.ts CHANGED
@@ -178,7 +178,10 @@ function parseBead(output: string): Bead {
178
178
  // CLI commands like `bd close`, `bd update` return arrays even for single items
179
179
  const data = Array.isArray(parsed) ? parsed[0] : parsed;
180
180
  if (!data) {
181
- throw new BeadError("No bead data in response", "parse");
181
+ throw new BeadError(
182
+ "No bead data in response. The bd CLI may not be installed or returned unexpected output. Try: Run 'bd --version' to verify installation, or check if .beads/ directory exists in project.",
183
+ "parse",
184
+ );
182
185
  }
183
186
  return BeadSchema.parse(data);
184
187
  } catch (error) {
@@ -191,7 +194,10 @@ function parseBead(output: string): Bead {
191
194
  if (error instanceof BeadError) {
192
195
  throw error;
193
196
  }
194
- throw new BeadError(`Failed to parse bead JSON: ${output}`, "parse");
197
+ throw new BeadError(
198
+ `Failed to parse bead JSON because output is malformed. Try: Check if bd CLI is up to date with 'bd --version' (need v1.0.0+), or inspect output: ${output.slice(0, 100)}`,
199
+ "parse",
200
+ );
195
201
  }
196
202
  }
197
203
 
@@ -209,7 +215,10 @@ function parseBeads(output: string): Bead[] {
209
215
  error,
210
216
  );
211
217
  }
212
- throw new BeadError(`Failed to parse beads JSON: ${output}`, "parse");
218
+ throw new BeadError(
219
+ `Failed to parse beads JSON because output is malformed. Try: Check if bd CLI is up to date with 'bd --version' (need v1.0.0+), or inspect output: ${output.slice(0, 100)}`,
220
+ "parse",
221
+ );
213
222
  }
214
223
  }
215
224
 
@@ -249,7 +258,7 @@ export const beads_create = tool({
249
258
 
250
259
  if (result.exitCode !== 0) {
251
260
  throw new BeadError(
252
- `Failed to create bead: ${result.stderr}`,
261
+ `Failed to create bead because bd command exited with code ${result.exitCode}. Error: ${result.stderr}. Try: Check if beads initialized with 'bd init' in project root, or verify .beads/ directory exists.`,
253
262
  cmdParts.join(" "),
254
263
  result.exitCode,
255
264
  result.stderr,
@@ -260,7 +269,7 @@ export const beads_create = tool({
260
269
  const stdout = result.stdout.trim();
261
270
  if (!stdout) {
262
271
  throw new BeadError(
263
- "bd create returned empty output",
272
+ "bd create returned empty output because command produced no response. Try: Check if bd is properly installed with 'bd --version', or run 'bd list' to test basic functionality.",
264
273
  cmdParts.join(" "),
265
274
  0,
266
275
  "Empty stdout",
@@ -270,7 +279,7 @@ export const beads_create = tool({
270
279
  // Check for error messages in stdout (bd sometimes outputs errors to stdout)
271
280
  if (stdout.startsWith("error:") || stdout.startsWith("Error:")) {
272
281
  throw new BeadError(
273
- `bd create failed: ${stdout}`,
282
+ `bd create failed because command returned error in stdout: ${stdout}. Try: Check error message above, verify beads initialized with 'bd init', or check .beads/issues.jsonl for corruption.`,
274
283
  cmdParts.join(" "),
275
284
  0,
276
285
  stdout,
@@ -331,7 +340,7 @@ export const beads_create_epic = tool({
331
340
 
332
341
  if (epicResult.exitCode !== 0) {
333
342
  throw new BeadError(
334
- `Failed to create epic: ${epicResult.stderr}`,
343
+ `Failed to create epic because bd command failed: ${epicResult.stderr}. Try: Verify beads initialized with 'bd init', check if .beads/ directory is writable, or run 'bd list' to test basic functionality.`,
335
344
  epicCmd.join(" "),
336
345
  epicResult.exitCode,
337
346
  );
@@ -361,7 +370,7 @@ export const beads_create_epic = tool({
361
370
 
362
371
  if (subtaskResult.exitCode !== 0) {
363
372
  throw new BeadError(
364
- `Failed to create subtask: ${subtaskResult.stderr}`,
373
+ `Failed to create subtask because bd command failed: ${subtaskResult.stderr}. Try: Check if parent epic exists with 'bd show ${epic.id}', verify .beads/issues.jsonl is not corrupted, or check for invalid characters in title.`,
365
374
  subtaskCmd.join(" "),
366
375
  subtaskResult.exitCode,
367
376
  );
@@ -430,7 +439,7 @@ export const beads_create_epic = tool({
430
439
  }
431
440
 
432
441
  throw new BeadError(
433
- `Epic creation failed: ${errorMsg}${rollbackInfo}`,
442
+ `Epic creation failed: ${errorMsg}${rollbackInfo}. Try: If rollback failed, manually close beads with 'bd close <id> --reason "Rollback"', check .beads/issues.jsonl for partial state, or re-run beads_create_epic with corrected parameters.`,
434
443
  "beads_create_epic",
435
444
  1,
436
445
  );
@@ -482,7 +491,7 @@ export const beads_query = tool({
482
491
 
483
492
  if (result.exitCode !== 0) {
484
493
  throw new BeadError(
485
- `Failed to query beads: ${result.stderr}`,
494
+ `Failed to query beads because bd command failed: ${result.stderr}. Try: Check if beads initialized with 'bd init', verify .beads/ directory exists, or run 'bd --version' to check CLI version.`,
486
495
  cmd.join(" "),
487
496
  result.exitCode,
488
497
  );
@@ -534,7 +543,7 @@ export const beads_update = tool({
534
543
 
535
544
  if (result.exitCode !== 0) {
536
545
  throw new BeadError(
537
- `Failed to update bead: ${result.stderr}`,
546
+ `Failed to update bead because bd command failed: ${result.stderr}. Try: Verify bead exists with 'bd show ${validated.id}', check for invalid status values, or inspect .beads/issues.jsonl for corruption.`,
538
547
  cmd.join(" "),
539
548
  result.exitCode,
540
549
  );
@@ -570,7 +579,7 @@ export const beads_close = tool({
570
579
 
571
580
  if (result.exitCode !== 0) {
572
581
  throw new BeadError(
573
- `Failed to close bead: ${result.stderr}`,
582
+ `Failed to close bead because bd command failed: ${result.stderr}. Try: Verify bead exists and is not already closed with 'beads_query(status="closed")' or 'bd show ${validated.id}', check if bead ID is correct.`,
574
583
  cmd.join(" "),
575
584
  result.exitCode,
576
585
  );
@@ -601,7 +610,7 @@ export const beads_start = tool({
601
610
 
602
611
  if (result.exitCode !== 0) {
603
612
  throw new BeadError(
604
- `Failed to start bead: ${result.stderr}`,
613
+ `Failed to start bead because bd update command failed: ${result.stderr}. Try: Verify bead exists with 'bd show ${args.id}', check if already in_progress with 'beads_query(status="in_progress")', or use beads_update directly.`,
605
614
  `bd update ${args.id} --status in_progress --json`,
606
615
  result.exitCode,
607
616
  );
@@ -623,7 +632,7 @@ export const beads_ready = tool({
623
632
 
624
633
  if (result.exitCode !== 0) {
625
634
  throw new BeadError(
626
- `Failed to get ready beads: ${result.stderr}`,
635
+ `Failed to get ready beads because bd ready command failed: ${result.stderr}. Try: Check if beads initialized with 'bd init', verify .beads/ directory is readable, or run 'bd list --json' to test basic query.`,
627
636
  "bd ready --json",
628
637
  result.exitCode,
629
638
  );
@@ -696,7 +705,7 @@ export const beads_sync = tool({
696
705
  );
697
706
  if (flushResult.exitCode !== 0) {
698
707
  throw new BeadError(
699
- `Failed to flush beads: ${flushResult.stderr}`,
708
+ `Failed to flush beads because bd sync failed: ${flushResult.stderr}. Try: Check if .beads/ directory is writable, verify no corrupted JSONL files, or run 'bd list' to test basic beads functionality.`,
700
709
  "bd sync --flush-only",
701
710
  flushResult.exitCode,
702
711
  );
@@ -715,7 +724,7 @@ export const beads_sync = tool({
715
724
  const addResult = await runGitCommand(["add", ".beads/"]);
716
725
  if (addResult.exitCode !== 0) {
717
726
  throw new BeadError(
718
- `Failed to stage beads: ${addResult.stderr}`,
727
+ `Failed to stage beads because git add failed: ${addResult.stderr}. Try: Check if .beads/ directory exists, verify git is initialized with 'git status', or check for .gitignore patterns blocking .beads/.`,
719
728
  "git add .beads/",
720
729
  addResult.exitCode,
721
730
  );
@@ -732,7 +741,7 @@ export const beads_sync = tool({
732
741
  !commitResult.stdout.includes("nothing to commit")
733
742
  ) {
734
743
  throw new BeadError(
735
- `Failed to commit beads: ${commitResult.stderr}`,
744
+ `Failed to commit beads because git commit failed: ${commitResult.stderr}. Try: Check git config (user.name, user.email) with 'git config --list', verify working tree is clean, or check for pre-commit hooks blocking commit.`,
736
745
  "git commit",
737
746
  commitResult.exitCode,
738
747
  );
@@ -798,7 +807,7 @@ export const beads_sync = tool({
798
807
 
799
808
  if (pullResult.exitCode !== 0) {
800
809
  throw new BeadError(
801
- `Failed to pull: ${pullResult.stderr}`,
810
+ `Failed to pull because git pull --rebase failed: ${pullResult.stderr}. Try: Resolve merge conflicts manually with 'git status', check if remote is accessible with 'git remote -v', or use skip_verification to bypass automatic pull.`,
802
811
  "git pull --rebase",
803
812
  pullResult.exitCode,
804
813
  );
@@ -824,7 +833,7 @@ export const beads_sync = tool({
824
833
  );
825
834
  if (pushResult.exitCode !== 0) {
826
835
  throw new BeadError(
827
- `Failed to push: ${pushResult.stderr}`,
836
+ `Failed to push because git push failed: ${pushResult.stderr}. Try: Check if remote branch is up to date with 'git pull --rebase', verify push permissions, check remote URL with 'git remote -v', or force push with 'git push --force-with-lease' if safe.`,
828
837
  "git push",
829
838
  pushResult.exitCode,
830
839
  );
@@ -858,7 +867,7 @@ export const beads_link_thread = tool({
858
867
 
859
868
  if (queryResult.exitCode !== 0) {
860
869
  throw new BeadError(
861
- `Failed to get bead: ${queryResult.stderr}`,
870
+ `Failed to get bead because bd show command failed: ${queryResult.stderr}. Try: Verify bead ID is correct with 'beads_query()', check if bead exists with 'bd list --json', or check .beads/issues.jsonl for valid entries.`,
862
871
  `bd show ${args.bead_id} --json`,
863
872
  queryResult.exitCode,
864
873
  );
@@ -887,7 +896,7 @@ export const beads_link_thread = tool({
887
896
 
888
897
  if (updateResult.exitCode !== 0) {
889
898
  throw new BeadError(
890
- `Failed to update bead: ${updateResult.stderr}`,
899
+ `Failed to update bead because bd update command failed: ${updateResult.stderr}. Try: Verify bead exists with 'bd show ${args.bead_id}', check for invalid characters in description, or inspect .beads/issues.jsonl for corruption.`,
891
900
  `bd update ${args.bead_id} -d ...`,
892
901
  updateResult.exitCode,
893
902
  );