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.
@@ -966,6 +966,11 @@
966
966
  {"id":"opencode-swarm-plugin-gpse","title":"Workflow test epic","description":"","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-08T07:49:11.489232-08:00","updated_at":"2025-12-08T07:49:11.696115-08:00","closed_at":"2025-12-08T07:49:11.696115-08:00"}
967
967
  {"id":"opencode-swarm-plugin-gpse.1","title":"Step 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T07:49:11.52435-08:00","updated_at":"2025-12-08T07:49:11.619347-08:00","closed_at":"2025-12-08T07:49:11.619347-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-gpse.1","depends_on_id":"opencode-swarm-plugin-gpse","type":"parent-child","created_at":"2025-12-08T07:49:11.524725-08:00","created_by":"daemon"}]}
968
968
  {"id":"opencode-swarm-plugin-gpse.2","title":"Step 2","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T07:49:11.56095-08:00","updated_at":"2025-12-08T07:49:11.671061-08:00","closed_at":"2025-12-08T07:49:11.671061-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-gpse.2","depends_on_id":"opencode-swarm-plugin-gpse","type":"parent-child","created_at":"2025-12-08T07:49:11.561312-08:00","created_by":"daemon"}]}
969
+ {"id":"opencode-swarm-plugin-gpusl","title":"DX Improvements: Actionable Errors \u0026 Troubleshooting","description":"Improve developer experience with actionable error messages that tell users HOW to fix problems, add troubleshooting docs, and enhance CLI doctor output.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-13T15:21:23.537986-08:00","updated_at":"2025-12-13T15:26:06.152115-08:00","closed_at":"2025-12-13T15:26:06.152115-08:00"}
970
+ {"id":"opencode-swarm-plugin-gpusl.1","title":"Add troubleshooting section to README","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-13T15:21:23.645841-08:00","updated_at":"2025-12-13T15:24:59.766004-08:00","closed_at":"2025-12-13T15:24:59.766004-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-gpusl.1","depends_on_id":"opencode-swarm-plugin-gpusl","type":"parent-child","created_at":"2025-12-13T15:21:23.64819-08:00","created_by":"daemon"}]}
971
+ {"id":"opencode-swarm-plugin-gpusl.2","title":"Make BeadError and SwarmError actionable","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-13T15:21:23.728838-08:00","updated_at":"2025-12-13T15:25:01.061305-08:00","closed_at":"2025-12-13T15:25:01.061305-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-gpusl.2","depends_on_id":"opencode-swarm-plugin-gpusl","type":"parent-child","created_at":"2025-12-13T15:21:23.730994-08:00","created_by":"daemon"}]}
972
+ {"id":"opencode-swarm-plugin-gpusl.3","title":"Make MandateError and storage errors actionable","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-13T15:21:23.806569-08:00","updated_at":"2025-12-13T15:25:02.21639-08:00","closed_at":"2025-12-13T15:25:02.21639-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-gpusl.3","depends_on_id":"opencode-swarm-plugin-gpusl","type":"parent-child","created_at":"2025-12-13T15:21:23.808361-08:00","created_by":"daemon"}]}
973
+ {"id":"opencode-swarm-plugin-gpusl.4","title":"Enhance CLI doctor with fix suggestions","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-13T15:21:23.868538-08:00","updated_at":"2025-12-13T15:25:03.179053-08:00","closed_at":"2025-12-13T15:25:03.179053-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-gpusl.4","depends_on_id":"opencode-swarm-plugin-gpusl","type":"parent-child","created_at":"2025-12-13T15:21:23.869987-08:00","created_by":"daemon"}]}
969
974
  {"id":"opencode-swarm-plugin-gq4y","title":"Update test bead","description":"Updated description","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T11:12:26.032848-08:00","updated_at":"2025-12-08T11:12:28.256366-08:00","closed_at":"2025-12-08T11:12:28.256366-08:00"}
970
975
  {"id":"opencode-swarm-plugin-gr8j","title":"Update test bead","description":"Original description","status":"closed","priority":0,"issue_type":"task","created_at":"2025-12-08T11:11:08.754659-08:00","updated_at":"2025-12-08T11:11:11.067841-08:00","closed_at":"2025-12-08T11:11:11.067841-08:00"}
971
976
  {"id":"opencode-swarm-plugin-gswv","title":"Bead to start","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T07:53:44.538704-08:00","updated_at":"2025-12-08T07:53:46.579794-08:00","closed_at":"2025-12-08T07:53:46.579794-08:00"}
package/README.md CHANGED
@@ -29,19 +29,15 @@ swarm setup
29
29
  The setup wizard handles everything:
30
30
 
31
31
  ```
32
- ┌ opencode-swarm-plugin v0.10.0
32
+ ┌ opencode-swarm-plugin v0.16.0
33
33
 
34
34
  ◇ Checking dependencies...
35
35
 
36
36
  ◆ OpenCode
37
37
  ◆ Beads
38
- Go
39
- Swarm Mail (optional)
40
- Redis (optional)
41
-
42
- ◆ Install optional dependencies?
43
- │ ◻ Swarm Mail - Multi-agent coordination
44
- │ ◻ Redis - Rate limiting
38
+ CASS (optional)
39
+ UBS (optional)
40
+ semantic-memory (optional)
45
41
 
46
42
  ◇ Setting up OpenCode integration...
47
43
 
@@ -271,16 +267,14 @@ What NOT to do...
271
267
 
272
268
  ## Dependencies
273
269
 
274
- | Dependency | Purpose | Required |
275
- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | -------- |
276
- | [OpenCode](https://opencode.ai) | Plugin host | Yes |
277
- | [Beads](https://github.com/steveyegge/beads) | Git-backed issue tracking | Yes |
278
- | [Go](https://go.dev) | Required for Swarm Mail | No |
279
- | [MCP Agent Mail](https://github.com/Dicklesworthstone/mcp_agent_mail)| **The original** - Multi-agent coordination, file reservations. Swarm Mail is built on these patterns. | No |
280
- | [CASS (Coding Agent Session Search)](https://github.com/Dicklesworthstone/coding_agent_session_search) | Historical context from past sessions | No |
281
- | [UBS (Ultimate Bug Scanner)](https://github.com/Dicklesworthstone/ultimate_bug_scanner) | Pre-completion bug scanning using AI-powered static analysis | No |
282
- | [semantic-memory](https://github.com/joelhooks/semantic-memory) | Learning persistence | No |
283
- | [Redis](https://redis.io) | Rate limiting (SQLite fallback available) | No |
270
+ | Dependency | Purpose | Required |
271
+ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------ | -------- |
272
+ | [OpenCode](https://opencode.ai) | Plugin host | Yes |
273
+ | [Beads](https://github.com/steveyegge/beads) | Git-backed issue tracking | Yes |
274
+ | [CASS (Coding Agent Session Search)](https://github.com/Dicklesworthstone/coding_agent_session_search) | Historical context from past sessions | No |
275
+ | [UBS (Ultimate Bug Scanner)](https://github.com/Dicklesworthstone/ultimate_bug_scanner) | Pre-completion bug scanning using AI-powered static analysis | No |
276
+ | [semantic-memory](https://github.com/joelhooks/semantic-memory) | Learning persistence | No |
277
+ | [Redis](https://redis.io) | Rate limiting (SQLite fallback available) | No |
284
278
 
285
279
  All dependencies are checked and can be installed via `swarm setup`.
286
280
 
@@ -298,13 +292,7 @@ curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/ultimate_bug_sca
298
292
  curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/coding_agent_session_search/main/install.sh | bash -s -- --easy-mode
299
293
  ```
300
294
 
301
- **MCP Agent Mail** - The original multi-agent coordination system. Swarm Mail's embedded implementation is inspired by and compatible with MCP Agent Mail's protocol:
302
-
303
- ```bash
304
- curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/mcp_agent_mail/main/scripts/install.sh" | bash -s -- --yes
305
- ```
306
-
307
- > **Note:** The embedded Swarm Mail (PGLite in-process) is now the primary option and works out of the box with no external dependencies. MCP Agent Mail (external Go server) is still supported for advanced use cases requiring a separate server process.
295
+ > **Note:** Swarm Mail is now embedded (PGLite in-process) and works out of the box with no external dependencies. No Go or external servers required.
308
296
 
309
297
  ## Tools Reference
310
298
 
@@ -584,6 +572,34 @@ bun test
584
572
  bun run build
585
573
  ```
586
574
 
575
+ ## Troubleshooting
576
+
577
+ ### 1. First Step: Run Doctor
578
+
579
+ ```bash
580
+ swarm doctor
581
+ ```
582
+
583
+ This checks all dependencies and shows their installation status.
584
+
585
+ ### 2. Common Issues
586
+
587
+ | Issue | Cause | Solution |
588
+ | --------------------------- | ---------------------------------- | ------------------------------------------------- |
589
+ | `beads: command not found` | Beads CLI not installed | `npm install -g @joelhooks/beads` |
590
+ | `bd: command not found` | Same as above | `npm install -g @joelhooks/beads` |
591
+ | Verification Gate fails | TypeScript errors or test failures | Fix errors shown, or use `skip_verification=true` |
592
+ | File reservation conflict | Another agent has the file | Wait for release, or check `swarmmail_inbox` |
593
+ | `Mandate not found` | ID doesn't exist | Use `mandate_list` to see available mandates |
594
+ | Swarm Mail connection error | Database not initialized | Run `swarm setup` again |
595
+ | `Agent not registered` | Session not initialized | Call `swarmmail_init` first |
596
+
597
+ ### 3. Getting Help
598
+
599
+ - Run `swarm doctor` for dependency status
600
+ - Check `swarmmail_health` for database status
601
+ - File issues at: https://github.com/joelhooks/opencode-swarm-plugin/issues
602
+
587
603
  ## License
588
604
 
589
605
  MIT
package/bin/swarm.ts CHANGED
@@ -670,6 +670,34 @@ If you discover a reusable pattern worth preserving:
670
670
  // Commands
671
671
  // ============================================================================
672
672
 
673
+ /**
674
+ * Get the fix command for a dependency
675
+ * Returns null for manual installs (those show a link instead)
676
+ */
677
+ function getFixCommand(dep: Dependency): string | null {
678
+ switch (dep.name) {
679
+ case "OpenCode":
680
+ return "brew install sst/tap/opencode";
681
+ case "Beads":
682
+ return "curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash";
683
+ case "Go":
684
+ return "brew install go (or visit https://go.dev/dl/)";
685
+ case "semantic-memory":
686
+ return "npm install -g semantic-memory";
687
+ case "Redis":
688
+ return "brew install redis && brew services start redis";
689
+ case "MCP Agent Mail":
690
+ return "See: https://github.com/Dicklesworthstone/mcp_agent_mail";
691
+ case "CASS (Coding Agent Session Search)":
692
+ return "See: https://github.com/Dicklesworthstone/coding_agent_session_search";
693
+ case "UBS (Ultimate Bug Scanner)":
694
+ return "See: https://github.com/Dicklesworthstone/ultimate_bug_scanner";
695
+ default:
696
+ // Fallback to generic install command if available
697
+ return dep.installType !== "manual" ? dep.install : null;
698
+ }
699
+ }
700
+
673
701
  async function doctor() {
674
702
  p.intro("swarm doctor v" + VERSION);
675
703
 
@@ -689,7 +717,10 @@ async function doctor() {
689
717
  p.log.success(dep.name + (version ? " v" + version : ""));
690
718
  } else {
691
719
  p.log.error(dep.name + " - not found");
692
- p.log.message(" Install: " + dep.install);
720
+ const fixCmd = getFixCommand(dep);
721
+ if (fixCmd) {
722
+ p.log.message(dim(" └─ Fix: " + fixCmd));
723
+ }
693
724
  }
694
725
  }
695
726
 
@@ -701,10 +732,9 @@ async function doctor() {
701
732
  );
702
733
  } else {
703
734
  p.log.warn(dep.name + " - not found (" + dep.description + ")");
704
- if (dep.installType !== "manual") {
705
- p.log.message(" Install: " + dep.install);
706
- } else {
707
- p.log.message(" See: " + dep.install);
735
+ const fixCmd = getFixCommand(dep);
736
+ if (fixCmd) {
737
+ p.log.message(dim(" └─ Fix: " + fixCmd));
708
738
  }
709
739
  }
710
740
  }
package/dist/index.js CHANGED
@@ -29841,7 +29841,7 @@ function parseBead(output) {
29841
29841
  const parsed = JSON.parse(output);
29842
29842
  const data = Array.isArray(parsed) ? parsed[0] : parsed;
29843
29843
  if (!data) {
29844
- throw new BeadError("No bead data in response", "parse");
29844
+ 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");
29845
29845
  }
29846
29846
  return BeadSchema.parse(data);
29847
29847
  } catch (error45) {
@@ -29851,7 +29851,7 @@ function parseBead(output) {
29851
29851
  if (error45 instanceof BeadError) {
29852
29852
  throw error45;
29853
29853
  }
29854
- throw new BeadError(`Failed to parse bead JSON: ${output}`, "parse");
29854
+ 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");
29855
29855
  }
29856
29856
  }
29857
29857
  function parseBeads(output) {
@@ -29862,7 +29862,7 @@ function parseBeads(output) {
29862
29862
  if (error45 instanceof exports_external.ZodError) {
29863
29863
  throw new BeadValidationError(`Invalid beads data: ${error45.message}`, error45);
29864
29864
  }
29865
- throw new BeadError(`Failed to parse beads JSON: ${output}`, "parse");
29865
+ 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");
29866
29866
  }
29867
29867
  }
29868
29868
  var beads_create = tool({
@@ -29879,14 +29879,14 @@ var beads_create = tool({
29879
29879
  const cmdParts = buildCreateCommand(validated);
29880
29880
  const result = await runBdCommand(cmdParts.slice(1));
29881
29881
  if (result.exitCode !== 0) {
29882
- throw new BeadError(`Failed to create bead: ${result.stderr}`, cmdParts.join(" "), result.exitCode, result.stderr);
29882
+ 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);
29883
29883
  }
29884
29884
  const stdout = result.stdout.trim();
29885
29885
  if (!stdout) {
29886
- throw new BeadError("bd create returned empty output", cmdParts.join(" "), 0, "Empty stdout");
29886
+ 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");
29887
29887
  }
29888
29888
  if (stdout.startsWith("error:") || stdout.startsWith("Error:")) {
29889
- throw new BeadError(`bd create failed: ${stdout}`, cmdParts.join(" "), 0, stdout);
29889
+ 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);
29890
29890
  }
29891
29891
  const bead = parseBead(stdout);
29892
29892
  return JSON.stringify(bead, null, 2);
@@ -29918,7 +29918,7 @@ var beads_create_epic = tool({
29918
29918
  });
29919
29919
  const epicResult = await runBdCommand(epicCmd.slice(1));
29920
29920
  if (epicResult.exitCode !== 0) {
29921
- throw new BeadError(`Failed to create epic: ${epicResult.stderr}`, epicCmd.join(" "), epicResult.exitCode);
29921
+ 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);
29922
29922
  }
29923
29923
  const epic = parseBead(epicResult.stdout);
29924
29924
  created.push(epic);
@@ -29936,7 +29936,7 @@ var beads_create_epic = tool({
29936
29936
  });
29937
29937
  const subtaskResult = await runBdCommand(subtaskCmd.slice(1));
29938
29938
  if (subtaskResult.exitCode !== 0) {
29939
- throw new BeadError(`Failed to create subtask: ${subtaskResult.stderr}`, subtaskCmd.join(" "), subtaskResult.exitCode);
29939
+ 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);
29940
29940
  }
29941
29941
  const subtaskBead = parseBead(subtaskResult.stdout);
29942
29942
  created.push(subtaskBead);
@@ -29992,7 +29992,7 @@ ${rollbackErrors.join(`
29992
29992
 
29993
29993
  No beads to rollback.`;
29994
29994
  }
29995
- throw new BeadError(`Epic creation failed: ${errorMsg}${rollbackInfo}`, "beads_create_epic", 1);
29995
+ 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);
29996
29996
  }
29997
29997
  }
29998
29998
  });
@@ -30020,7 +30020,7 @@ var beads_query = tool({
30020
30020
  }
30021
30021
  const result = await runBdCommand(cmd.slice(1));
30022
30022
  if (result.exitCode !== 0) {
30023
- throw new BeadError(`Failed to query beads: ${result.stderr}`, cmd.join(" "), result.exitCode);
30023
+ 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);
30024
30024
  }
30025
30025
  const beads = parseBeads(result.stdout);
30026
30026
  const limited = beads.slice(0, validated.limit);
@@ -30050,7 +30050,7 @@ var beads_update = tool({
30050
30050
  cmd.push("--json");
30051
30051
  const result = await runBdCommand(cmd.slice(1));
30052
30052
  if (result.exitCode !== 0) {
30053
- throw new BeadError(`Failed to update bead: ${result.stderr}`, cmd.join(" "), result.exitCode);
30053
+ 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);
30054
30054
  }
30055
30055
  const bead = parseBead(result.stdout);
30056
30056
  return JSON.stringify(bead, null, 2);
@@ -30074,7 +30074,7 @@ var beads_close = tool({
30074
30074
  ];
30075
30075
  const result = await runBdCommand(cmd.slice(1));
30076
30076
  if (result.exitCode !== 0) {
30077
- throw new BeadError(`Failed to close bead: ${result.stderr}`, cmd.join(" "), result.exitCode);
30077
+ 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);
30078
30078
  }
30079
30079
  const bead = parseBead(result.stdout);
30080
30080
  return `Closed ${bead.id}: ${validated.reason}`;
@@ -30094,7 +30094,7 @@ var beads_start = tool({
30094
30094
  "--json"
30095
30095
  ]);
30096
30096
  if (result.exitCode !== 0) {
30097
- throw new BeadError(`Failed to start bead: ${result.stderr}`, `bd update ${args.id} --status in_progress --json`, result.exitCode);
30097
+ 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);
30098
30098
  }
30099
30099
  const bead = parseBead(result.stdout);
30100
30100
  return `Started: ${bead.id}`;
@@ -30106,7 +30106,7 @@ var beads_ready = tool({
30106
30106
  async execute(args, ctx) {
30107
30107
  const result = await runBdCommand(["ready", "--json"]);
30108
30108
  if (result.exitCode !== 0) {
30109
- throw new BeadError(`Failed to get ready beads: ${result.stderr}`, "bd ready --json", result.exitCode);
30109
+ 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);
30110
30110
  }
30111
30111
  const beads = parseBeads(result.stdout);
30112
30112
  if (beads.length === 0) {
@@ -30139,7 +30139,7 @@ var beads_sync = tool({
30139
30139
  };
30140
30140
  const flushResult = await withTimeout(runBdCommand(["sync", "--flush-only"]), TIMEOUT_MS, "bd sync --flush-only");
30141
30141
  if (flushResult.exitCode !== 0) {
30142
- throw new BeadError(`Failed to flush beads: ${flushResult.stderr}`, "bd sync --flush-only", flushResult.exitCode);
30142
+ 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);
30143
30143
  }
30144
30144
  const beadsStatusResult = await runGitCommand([
30145
30145
  "status",
@@ -30150,11 +30150,11 @@ var beads_sync = tool({
30150
30150
  if (hasChanges) {
30151
30151
  const addResult = await runGitCommand(["add", ".beads/"]);
30152
30152
  if (addResult.exitCode !== 0) {
30153
- throw new BeadError(`Failed to stage beads: ${addResult.stderr}`, "git add .beads/", addResult.exitCode);
30153
+ 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);
30154
30154
  }
30155
30155
  const commitResult = await withTimeout(runGitCommand(["commit", "-m", "chore: sync beads"]), TIMEOUT_MS, "git commit");
30156
30156
  if (commitResult.exitCode !== 0 && !commitResult.stdout.includes("nothing to commit")) {
30157
- throw new BeadError(`Failed to commit beads: ${commitResult.stderr}`, "git commit", commitResult.exitCode);
30157
+ 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);
30158
30158
  }
30159
30159
  }
30160
30160
  if (autoPull) {
@@ -30193,7 +30193,7 @@ var beads_sync = tool({
30193
30193
  }
30194
30194
  }
30195
30195
  if (pullResult.exitCode !== 0) {
30196
- throw new BeadError(`Failed to pull: ${pullResult.stderr}`, "git pull --rebase", pullResult.exitCode);
30196
+ 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);
30197
30197
  }
30198
30198
  const importResult = await withTimeout(runBdCommand(["sync", "--import-only"]), TIMEOUT_MS, "bd sync --import-only");
30199
30199
  if (importResult.exitCode !== 0) {
@@ -30202,7 +30202,7 @@ var beads_sync = tool({
30202
30202
  }
30203
30203
  const pushResult = await withTimeout(runGitCommand(["push"]), TIMEOUT_MS, "git push");
30204
30204
  if (pushResult.exitCode !== 0) {
30205
- throw new BeadError(`Failed to push: ${pushResult.stderr}`, "git push", pushResult.exitCode);
30205
+ 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);
30206
30206
  }
30207
30207
  const statusResult = await runGitCommand(["status", "--porcelain"]);
30208
30208
  const status = statusResult.stdout.trim();
@@ -30222,7 +30222,7 @@ var beads_link_thread = tool({
30222
30222
  async execute(args, ctx) {
30223
30223
  const queryResult = await runBdCommand(["show", args.bead_id, "--json"]);
30224
30224
  if (queryResult.exitCode !== 0) {
30225
- throw new BeadError(`Failed to get bead: ${queryResult.stderr}`, `bd show ${args.bead_id} --json`, queryResult.exitCode);
30225
+ 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);
30226
30226
  }
30227
30227
  const bead = parseBead(queryResult.stdout);
30228
30228
  const existingDesc = bead.description || "";
@@ -30241,7 +30241,7 @@ ${threadMarker}` : threadMarker;
30241
30241
  "--json"
30242
30242
  ]);
30243
30243
  if (updateResult.exitCode !== 0) {
30244
- throw new BeadError(`Failed to update bead: ${updateResult.stderr}`, `bd update ${args.bead_id} -d ...`, updateResult.exitCode);
30244
+ 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);
30245
30245
  }
30246
30246
  return `Linked bead ${args.bead_id} to thread ${args.thread_id}`;
30247
30247
  }
@@ -34015,7 +34015,7 @@ async function runVerificationGate(filesTouched, skipUbs = false) {
34015
34015
  };
34016
34016
  if (!ubsStep.passed) {
34017
34017
  ubsStep.error = `Found ${ubsResult.summary.critical} critical bugs`;
34018
- blockers.push(`UBS: ${ubsResult.summary.critical} critical bugs found`);
34018
+ 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).`);
34019
34019
  }
34020
34020
  steps.push(ubsStep);
34021
34021
  } else {
@@ -34032,12 +34032,12 @@ async function runVerificationGate(filesTouched, skipUbs = false) {
34032
34032
  const typecheckStep = await runTypecheckVerification();
34033
34033
  steps.push(typecheckStep);
34034
34034
  if (!typecheckStep.passed && !typecheckStep.skipped) {
34035
- blockers.push(`Typecheck: ${typecheckStep.error?.slice(0, 100) || "failed"}`);
34035
+ 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.`);
34036
34036
  }
34037
34037
  const testStep = await runTestVerification(filesTouched);
34038
34038
  steps.push(testStep);
34039
34039
  if (!testStep.passed && !testStep.skipped) {
34040
- blockers.push(`Tests: ${testStep.error?.slice(0, 100) || "failed"}`);
34040
+ 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.`);
34041
34041
  }
34042
34042
  const passedCount = steps.filter((s) => s.passed).length;
34043
34043
  const skippedCount = steps.filter((s) => s.skipped).length;
@@ -34092,8 +34092,8 @@ async function runUbsScan(files) {
34092
34092
  }
34093
34093
  };
34094
34094
  } catch (error45) {
34095
- console.error(`[swarm] CRITICAL: UBS scan failed to parse JSON output:`, error45);
34096
- console.error(`[swarm] Raw output:`, output);
34095
+ console.error(`[swarm] CRITICAL: UBS scan failed to parse JSON output because output is malformed:`, error45);
34096
+ 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.`);
34097
34097
  return {
34098
34098
  exitCode: result.exitCode,
34099
34099
  bugs: [],
@@ -34183,7 +34183,7 @@ var swarm_complete = tool({
34183
34183
  error: s.error?.slice(0, 200)
34184
34184
  }))
34185
34185
  },
34186
- hint: "Fix the failing checks and try again. Use skip_verification=true only as last resort.",
34186
+ 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.",
34187
34187
  gate_function: "IDENTIFY → RUN → READ → VERIFY → CLAIM (you are at VERIFY, claim blocked)"
34188
34188
  }, null, 2);
34189
34189
  }
@@ -34194,12 +34194,12 @@ var swarm_complete = tool({
34194
34194
  if (ubsResult && ubsResult.summary.critical > 0) {
34195
34195
  return JSON.stringify({
34196
34196
  success: false,
34197
- error: "UBS found critical bugs - fix before completing",
34197
+ error: `UBS found ${ubsResult.summary.critical} critical bug(s) that must be fixed before completing`,
34198
34198
  ubs_scan: {
34199
34199
  critical_count: ubsResult.summary.critical,
34200
34200
  bugs: ubsResult.bugs.filter((b) => b.severity === "critical")
34201
34201
  },
34202
- hint: "Fix the critical bugs and try again, or use skip_ubs_scan=true to bypass"
34202
+ 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).`
34203
34203
  }, null, 2);
34204
34204
  }
34205
34205
  }
@@ -34225,7 +34225,7 @@ var swarm_complete = tool({
34225
34225
  }
34226
34226
  const closeResult = await Bun.$`bd close ${args.bead_id} --reason ${args.summary} --json`.quiet().nothrow();
34227
34227
  if (closeResult.exitCode !== 0) {
34228
- throw new SwarmError(`Failed to close bead: ${closeResult.stderr.toString()}`, "complete");
34228
+ 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");
34229
34229
  }
34230
34230
  try {
34231
34231
  await releaseSwarmFiles({
@@ -35403,7 +35403,7 @@ class SemanticMemoryMandateStorage {
35403
35403
  async update(id, updates) {
35404
35404
  const existing = await this.get(id);
35405
35405
  if (!existing) {
35406
- throw new Error(`Mandate ${id} not found`);
35406
+ throw new Error(`Mandate '${id}' not found. Use list() to see available mandates.`);
35407
35407
  }
35408
35408
  const updated = { ...existing, ...updates };
35409
35409
  await this.store(updated);
@@ -35411,7 +35411,7 @@ class SemanticMemoryMandateStorage {
35411
35411
  async vote(vote) {
35412
35412
  const existing = await this.hasVoted(vote.mandate_id, vote.agent_name);
35413
35413
  if (existing) {
35414
- throw new Error(`Agent ${vote.agent_name} has already voted on mandate ${vote.mandate_id}`);
35414
+ 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.`);
35415
35415
  }
35416
35416
  await this.storeInternal(this.config.collections.votes, vote, {
35417
35417
  id: vote.id,
@@ -35502,7 +35502,7 @@ class InMemoryMandateStorage {
35502
35502
  async update(id, updates) {
35503
35503
  const existing = await this.get(id);
35504
35504
  if (!existing) {
35505
- throw new Error(`Mandate ${id} not found`);
35505
+ throw new Error(`Mandate '${id}' not found. Use list() to see available mandates.`);
35506
35506
  }
35507
35507
  const updated = { ...existing, ...updates };
35508
35508
  this.entries.set(id, updated);
@@ -35510,7 +35510,7 @@ class InMemoryMandateStorage {
35510
35510
  async vote(vote) {
35511
35511
  const existing = await this.hasVoted(vote.mandate_id, vote.agent_name);
35512
35512
  if (existing) {
35513
- throw new Error(`Agent ${vote.agent_name} has already voted on mandate ${vote.mandate_id}`);
35513
+ 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.`);
35514
35514
  }
35515
35515
  this.votes.set(vote.id, vote);
35516
35516
  }
@@ -35565,13 +35565,13 @@ function createMandateStorage(config2 = {}) {
35565
35565
  case "memory":
35566
35566
  return new InMemoryMandateStorage(fullConfig);
35567
35567
  default:
35568
- throw new Error(`Unknown storage backend: ${fullConfig.backend}`);
35568
+ throw new Error(`Unknown storage backend: '${fullConfig.backend}'. Valid backends are 'semantic-memory' or 'memory'.`);
35569
35569
  }
35570
35570
  }
35571
35571
  async function updateMandateStatus(mandateId, storage) {
35572
35572
  const entry = await storage.get(mandateId);
35573
35573
  if (!entry) {
35574
- throw new Error(`Mandate ${mandateId} not found`);
35574
+ throw new Error(`Mandate '${mandateId}' not found when calculating score. Use storage.list() to verify the mandate exists.`);
35575
35575
  }
35576
35576
  const score = await storage.calculateScore(mandateId);
35577
35577
  const previousStatus = entry.status;
@@ -35781,11 +35781,11 @@ var mandate_vote = tool({
35781
35781
  const storage = getMandateStorage();
35782
35782
  const mandate = await storage.get(validated.mandate_id);
35783
35783
  if (!mandate) {
35784
- throw new MandateError(`Mandate ${validated.mandate_id} not found`, "mandate_vote");
35784
+ throw new MandateError(`Mandate '${validated.mandate_id}' not found. Use mandate_list() to see available mandates, or check the ID is correct.`, "mandate_vote");
35785
35785
  }
35786
35786
  const hasVoted = await storage.hasVoted(validated.mandate_id, args.agent_name);
35787
35787
  if (hasVoted) {
35788
- throw new MandateError(`Agent ${args.agent_name} has already voted on mandate ${validated.mandate_id}`, "mandate_vote");
35788
+ 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");
35789
35789
  }
35790
35790
  const vote = {
35791
35791
  id: generateVoteId(),
@@ -35928,7 +35928,7 @@ var mandate_stats = tool({
35928
35928
  if (args.mandate_id) {
35929
35929
  const mandate = await storage.get(args.mandate_id);
35930
35930
  if (!mandate) {
35931
- throw new MandateError(`Mandate ${args.mandate_id} not found`, "mandate_stats");
35931
+ throw new MandateError(`Mandate '${args.mandate_id}' not found. Use mandate_list() to see available mandates, or check the ID is correct.`, "mandate_stats");
35932
35932
  }
35933
35933
  const score = await storage.calculateScore(args.mandate_id);
35934
35934
  const votes = await storage.getVotes(args.mandate_id);