opencode-swarm-plugin 0.26.1 → 0.27.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +38 -0
  3. package/README.md +43 -46
  4. package/bin/swarm.ts +10 -54
  5. package/dist/compaction-hook.d.ts +57 -0
  6. package/dist/compaction-hook.d.ts.map +1 -0
  7. package/dist/hive.d.ts +741 -0
  8. package/dist/hive.d.ts.map +1 -0
  9. package/dist/index.d.ts +139 -23
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1353 -350
  12. package/dist/learning.d.ts +9 -9
  13. package/dist/plugin.js +1176 -350
  14. package/dist/schemas/cell-events.d.ts +1352 -0
  15. package/dist/schemas/{bead-events.d.ts.map → cell-events.d.ts.map} +1 -1
  16. package/dist/schemas/{bead.d.ts → cell.d.ts} +173 -29
  17. package/dist/schemas/cell.d.ts.map +1 -0
  18. package/dist/schemas/index.d.ts +11 -7
  19. package/dist/schemas/index.d.ts.map +1 -1
  20. package/dist/structured.d.ts +17 -7
  21. package/dist/structured.d.ts.map +1 -1
  22. package/dist/swarm-decompose.d.ts +5 -5
  23. package/dist/swarm-orchestrate.d.ts +16 -2
  24. package/dist/swarm-orchestrate.d.ts.map +1 -1
  25. package/dist/swarm-prompts.d.ts +9 -9
  26. package/dist/swarm-prompts.d.ts.map +1 -1
  27. package/dist/swarm-review.d.ts +210 -0
  28. package/dist/swarm-review.d.ts.map +1 -0
  29. package/dist/swarm-worktree.d.ts +185 -0
  30. package/dist/swarm-worktree.d.ts.map +1 -0
  31. package/dist/swarm.d.ts +7 -0
  32. package/dist/swarm.d.ts.map +1 -1
  33. package/dist/tool-availability.d.ts +3 -2
  34. package/dist/tool-availability.d.ts.map +1 -1
  35. package/docs/analysis-socratic-planner-pattern.md +1 -1
  36. package/docs/planning/ADR-007-swarm-enhancements-worktree-review.md +168 -0
  37. package/docs/testing/context-recovery-test.md +2 -2
  38. package/evals/README.md +2 -2
  39. package/evals/scorers/index.ts +7 -7
  40. package/examples/commands/swarm.md +21 -23
  41. package/examples/plugin-wrapper-template.ts +310 -44
  42. package/examples/skills/{beads-workflow → hive-workflow}/SKILL.md +40 -40
  43. package/examples/skills/swarm-coordination/SKILL.md +1 -1
  44. package/global-skills/swarm-coordination/SKILL.md +14 -14
  45. package/global-skills/swarm-coordination/references/coordinator-patterns.md +3 -3
  46. package/package.json +2 -2
  47. package/src/compaction-hook.ts +161 -0
  48. package/src/{beads.integration.test.ts → hive.integration.test.ts} +92 -80
  49. package/src/{beads.ts → hive.ts} +378 -219
  50. package/src/index.ts +57 -20
  51. package/src/learning.ts +9 -9
  52. package/src/output-guardrails.test.ts +4 -4
  53. package/src/output-guardrails.ts +9 -9
  54. package/src/planning-guardrails.test.ts +1 -1
  55. package/src/planning-guardrails.ts +1 -1
  56. package/src/schemas/{bead-events.test.ts → cell-events.test.ts} +83 -77
  57. package/src/schemas/cell-events.ts +807 -0
  58. package/src/schemas/{bead.ts → cell.ts} +95 -41
  59. package/src/schemas/evaluation.ts +1 -1
  60. package/src/schemas/index.ts +90 -18
  61. package/src/schemas/swarm-context.ts +2 -2
  62. package/src/structured.test.ts +15 -15
  63. package/src/structured.ts +18 -11
  64. package/src/swarm-decompose.ts +23 -23
  65. package/src/swarm-orchestrate.ts +135 -21
  66. package/src/swarm-prompts.ts +43 -43
  67. package/src/swarm-review.test.ts +702 -0
  68. package/src/swarm-review.ts +696 -0
  69. package/src/swarm-worktree.test.ts +501 -0
  70. package/src/swarm-worktree.ts +575 -0
  71. package/src/swarm.integration.test.ts +12 -12
  72. package/src/tool-availability.ts +36 -3
  73. package/dist/beads.d.ts +0 -386
  74. package/dist/beads.d.ts.map +0 -1
  75. package/dist/schemas/bead-events.d.ts +0 -698
  76. package/dist/schemas/bead.d.ts.map +0 -1
  77. package/src/schemas/bead-events.ts +0 -583
@@ -1,26 +1,26 @@
1
1
  /**
2
- * Beads Module - Type-safe wrappers using BeadsAdapter
2
+ * Hive Module - Type-safe wrappers using HiveAdapter
3
3
  *
4
- * This module provides validated, type-safe operations for the beads
5
- * issue tracker using the BeadsAdapter from swarm-mail.
4
+ * This module provides validated, type-safe operations for the Hive
5
+ * issue tracker using the HiveAdapter from swarm-mail.
6
6
  *
7
7
  * Key principles:
8
- * - Use BeadsAdapter for all operations (no CLI commands)
8
+ * - Use HiveAdapter for all operations (no CLI commands)
9
9
  * - Validate all inputs with Zod schemas
10
10
  * - Throw typed errors on failure
11
11
  * - Support atomic epic creation with rollback
12
12
  *
13
- * IMPORTANT: Call setBeadsWorkingDirectory() before using tools to ensure
13
+ * IMPORTANT: Call setHiveWorkingDirectory() before using tools to ensure
14
14
  * operations run in the correct project directory.
15
15
  */
16
16
  import { tool } from "@opencode-ai/plugin";
17
17
  import { z } from "zod";
18
18
  import {
19
- createBeadsAdapter,
19
+ createHiveAdapter,
20
20
  FlushManager,
21
21
  importFromJSONL,
22
- type BeadsAdapter,
23
- type Bead as AdapterBead,
22
+ type HiveAdapter,
23
+ type Cell as AdapterCell,
24
24
  getSwarmMail,
25
25
  } from "swarm-mail";
26
26
  import { existsSync, readFileSync } from "node:fs";
@@ -31,37 +31,41 @@ import { join } from "node:path";
31
31
  // ============================================================================
32
32
 
33
33
  /**
34
- * Module-level working directory for beads commands.
35
- * Set this via setBeadsWorkingDirectory() before using tools.
34
+ * Module-level working directory for hive commands.
35
+ * Set this via setHiveWorkingDirectory() before using tools.
36
36
  * If not set, commands run in process.cwd() which may be wrong for plugins.
37
37
  */
38
- let beadsWorkingDirectory: string | null = null;
38
+ let hiveWorkingDirectory: string | null = null;
39
39
 
40
40
  /**
41
- * Set the working directory for all beads commands.
41
+ * Set the working directory for all hive commands.
42
42
  * Call this from the plugin initialization with the project directory.
43
43
  *
44
44
  * @param directory - Absolute path to the project directory
45
45
  */
46
- export function setBeadsWorkingDirectory(directory: string): void {
47
- beadsWorkingDirectory = directory;
46
+ export function setHiveWorkingDirectory(directory: string): void {
47
+ hiveWorkingDirectory = directory;
48
48
  }
49
49
 
50
50
  /**
51
- * Get the current working directory for beads commands.
51
+ * Get the current working directory for hive commands.
52
52
  * Returns the configured directory or process.cwd() as fallback.
53
53
  */
54
- export function getBeadsWorkingDirectory(): string {
55
- return beadsWorkingDirectory || process.cwd();
54
+ export function getHiveWorkingDirectory(): string {
55
+ return hiveWorkingDirectory || process.cwd();
56
56
  }
57
57
 
58
+ // Legacy aliases for backward compatibility
59
+ export const setBeadsWorkingDirectory = setHiveWorkingDirectory;
60
+ export const getBeadsWorkingDirectory = getHiveWorkingDirectory;
61
+
58
62
  /**
59
63
  * Run a git command in the correct working directory.
60
64
  */
61
65
  async function runGitCommand(
62
66
  args: string[],
63
67
  ): Promise<{ exitCode: number; stdout: string; stderr: string }> {
64
- const cwd = getBeadsWorkingDirectory();
68
+ const cwd = getHiveWorkingDirectory();
65
69
  const proc = Bun.spawn(["git", ...args], {
66
70
  cwd,
67
71
  stdout: "pipe",
@@ -79,23 +83,23 @@ async function runGitCommand(
79
83
  }
80
84
 
81
85
  import {
82
- BeadSchema,
83
- BeadCreateArgsSchema,
84
- BeadUpdateArgsSchema,
85
- BeadCloseArgsSchema,
86
- BeadQueryArgsSchema,
86
+ CellSchema,
87
+ CellCreateArgsSchema,
88
+ CellUpdateArgsSchema,
89
+ CellCloseArgsSchema,
90
+ CellQueryArgsSchema,
87
91
  EpicCreateArgsSchema,
88
92
  EpicCreateResultSchema,
89
- type Bead,
90
- type BeadCreateArgs,
93
+ type Cell,
94
+ type CellCreateArgs,
91
95
  type EpicCreateResult,
92
96
  } from "./schemas";
93
97
  import { createEvent, appendEvent } from "swarm-mail";
94
98
 
95
99
  /**
96
- * Custom error for bead operations
100
+ * Custom error for hive operations
97
101
  */
98
- export class BeadError extends Error {
102
+ export class HiveError extends Error {
99
103
  constructor(
100
104
  message: string,
101
105
  public readonly command: string,
@@ -103,48 +107,54 @@ export class BeadError extends Error {
103
107
  public readonly stderr?: string,
104
108
  ) {
105
109
  super(message);
106
- this.name = "BeadError";
110
+ this.name = "HiveError";
107
111
  }
108
112
  }
109
113
 
114
+ // Legacy alias for backward compatibility
115
+ export const BeadError = HiveError;
116
+
110
117
  /**
111
118
  * Custom error for validation failures
112
119
  */
113
- export class BeadValidationError extends Error {
120
+ export class HiveValidationError extends Error {
114
121
  constructor(
115
122
  message: string,
116
123
  public readonly zodError: z.ZodError,
117
124
  ) {
118
125
  super(message);
119
- this.name = "BeadValidationError";
126
+ this.name = "HiveValidationError";
120
127
  }
121
128
  }
122
129
 
130
+ // Legacy alias for backward compatibility
131
+ export const BeadValidationError = HiveValidationError;
132
+
123
133
  // ============================================================================
124
134
  // Adapter Singleton
125
135
  // ============================================================================
126
136
 
127
137
  /**
128
- * Lazy singleton for BeadsAdapter instances
129
- * Maps projectKey -> BeadsAdapter
138
+ * Lazy singleton for HiveAdapter instances
139
+ * Maps projectKey -> HiveAdapter
130
140
  */
131
- const adapterCache = new Map<string, BeadsAdapter>();
141
+ const adapterCache = new Map<string, HiveAdapter>();
132
142
 
133
143
  /**
134
- * Get or create a BeadsAdapter instance for a project
144
+ * Get or create a HiveAdapter instance for a project
135
145
  * Exported for testing - allows tests to verify state directly
136
146
  *
137
147
  * On first initialization, checks for .beads/issues.jsonl and imports
138
148
  * historical beads if the database is empty.
139
149
  */
140
- export async function getBeadsAdapter(projectKey: string): Promise<BeadsAdapter> {
150
+ export async function getHiveAdapter(projectKey: string): Promise<HiveAdapter> {
141
151
  if (adapterCache.has(projectKey)) {
142
152
  return adapterCache.get(projectKey)!;
143
153
  }
144
154
 
145
155
  const swarmMail = await getSwarmMail(projectKey);
146
156
  const db = await swarmMail.getDatabase();
147
- const adapter = createBeadsAdapter(db, projectKey);
157
+ const adapter = createHiveAdapter(db, projectKey);
148
158
 
149
159
  // Run migrations to ensure schema exists
150
160
  await adapter.runMigrations();
@@ -156,74 +166,77 @@ export async function getBeadsAdapter(projectKey: string): Promise<BeadsAdapter>
156
166
  return adapter;
157
167
  }
158
168
 
169
+ // Legacy alias for backward compatibility
170
+ export const getBeadsAdapter = getHiveAdapter;
171
+
159
172
  /**
160
- * Auto-migrate beads from .beads/issues.jsonl if:
173
+ * Auto-migrate cells from .hive/issues.jsonl if:
161
174
  * 1. The JSONL file exists
162
- * 2. The database has no beads for this project
175
+ * 2. The database has no cells for this project
163
176
  *
164
177
  * This enables seamless migration from the old bd CLI to the new PGLite-based system.
165
178
  */
166
- async function autoMigrateFromJSONL(adapter: BeadsAdapter, projectKey: string): Promise<void> {
167
- const jsonlPath = join(projectKey, ".beads", "issues.jsonl");
179
+ async function autoMigrateFromJSONL(adapter: HiveAdapter, projectKey: string): Promise<void> {
180
+ const jsonlPath = join(projectKey, ".hive", "issues.jsonl");
168
181
 
169
182
  // Check if JSONL file exists
170
183
  if (!existsSync(jsonlPath)) {
171
184
  return;
172
185
  }
173
186
 
174
- // Check if database already has beads
175
- const existingBeads = await adapter.queryBeads(projectKey, { limit: 1 });
176
- if (existingBeads.length > 0) {
177
- return; // Already have beads, skip migration
187
+ // Check if database already has cells
188
+ const existingCells = await adapter.queryCells(projectKey, { limit: 1 });
189
+ if (existingCells.length > 0) {
190
+ return; // Already have cells, skip migration
178
191
  }
179
192
 
180
193
  // Read and import JSONL
181
194
  try {
182
195
  const jsonlContent = readFileSync(jsonlPath, "utf-8");
183
196
  const result = await importFromJSONL(adapter, projectKey, jsonlContent, {
184
- skipExisting: true, // Safety: don't overwrite if somehow beads exist
197
+ skipExisting: true, // Safety: don't overwrite if somehow cells exist
185
198
  });
186
199
 
187
200
  if (result.created > 0 || result.updated > 0) {
188
201
  console.log(
189
- `[beads] Auto-migrated ${result.created} beads from ${jsonlPath} (${result.skipped} skipped, ${result.errors.length} errors)`
202
+ `[hive] Auto-migrated ${result.created} cells from ${jsonlPath} (${result.skipped} skipped, ${result.errors.length} errors)`
190
203
  );
191
204
  }
192
205
 
193
206
  if (result.errors.length > 0) {
194
207
  console.warn(
195
- `[beads] Migration errors:`,
196
- result.errors.slice(0, 5).map((e) => `${e.beadId}: ${e.error}`)
208
+ `[hive] Migration errors:`,
209
+ result.errors.slice(0, 5).map((e) => `${e.cellId}: ${e.error}`)
197
210
  );
198
211
  }
199
212
  } catch (error) {
200
213
  // Non-fatal - log and continue
201
214
  console.warn(
202
- `[beads] Failed to auto-migrate from ${jsonlPath}:`,
215
+ `[hive] Failed to auto-migrate from ${jsonlPath}:`,
203
216
  error instanceof Error ? error.message : String(error)
204
217
  );
205
218
  }
206
219
  }
207
220
 
208
221
  /**
209
- * Format adapter bead for output (map field names)
222
+ * Format adapter cell for output (map field names)
210
223
  * Adapter uses: type, created_at/updated_at (timestamps)
211
224
  * Schema expects: issue_type, created_at/updated_at (ISO strings)
212
225
  */
213
- function formatBeadForOutput(adapterBead: AdapterBead): Record<string, unknown> {
226
+ function formatCellForOutput(adapterCell: AdapterCell): Record<string, unknown> {
214
227
  return {
215
- id: adapterBead.id,
216
- title: adapterBead.title,
217
- description: adapterBead.description || "",
218
- status: adapterBead.status,
219
- priority: adapterBead.priority,
220
- issue_type: adapterBead.type, // Adapter: type → Schema: issue_type
221
- created_at: new Date(adapterBead.created_at).toISOString(),
222
- updated_at: new Date(adapterBead.updated_at).toISOString(),
223
- closed_at: adapterBead.closed_at
224
- ? new Date(adapterBead.closed_at).toISOString()
228
+ id: adapterCell.id,
229
+ title: adapterCell.title,
230
+ description: adapterCell.description || "",
231
+ status: adapterCell.status,
232
+ priority: adapterCell.priority,
233
+ issue_type: adapterCell.type, // Adapter: type → Schema: issue_type
234
+ created_at: new Date(adapterCell.created_at).toISOString(),
235
+ updated_at: new Date(adapterCell.updated_at).toISOString(),
236
+ closed_at: adapterCell.closed_at
237
+ ? new Date(adapterCell.closed_at).toISOString()
225
238
  : undefined,
226
- parent_id: adapterBead.parent_id || undefined,
239
+ parent_id: adapterCell.parent_id || undefined,
227
240
  dependencies: [], // TODO: fetch from adapter if needed
228
241
  metadata: {},
229
242
  };
@@ -234,12 +247,12 @@ function formatBeadForOutput(adapterBead: AdapterBead): Record<string, unknown>
234
247
  // ============================================================================
235
248
 
236
249
  /**
237
- * Create a new bead with type-safe validation
250
+ * Create a new cell with type-safe validation
238
251
  */
239
- export const beads_create = tool({
240
- description: "Create a new bead with type-safe validation",
252
+ export const hive_create = tool({
253
+ description: "Create a new cell in the hive with type-safe validation",
241
254
  args: {
242
- title: tool.schema.string().describe("Bead title"),
255
+ title: tool.schema.string().describe("Cell title"),
243
256
  type: tool.schema
244
257
  .enum(["bug", "feature", "task", "epic", "chore"])
245
258
  .optional()
@@ -250,19 +263,19 @@ export const beads_create = tool({
250
263
  .max(3)
251
264
  .optional()
252
265
  .describe("Priority 0-3 (default: 2)"),
253
- description: tool.schema.string().optional().describe("Bead description"),
266
+ description: tool.schema.string().optional().describe("Cell description"),
254
267
  parent_id: tool.schema
255
268
  .string()
256
269
  .optional()
257
- .describe("Parent bead ID for epic children"),
270
+ .describe("Parent cell ID for epic children"),
258
271
  },
259
272
  async execute(args, ctx) {
260
- const validated = BeadCreateArgsSchema.parse(args);
261
- const projectKey = getBeadsWorkingDirectory();
262
- const adapter = await getBeadsAdapter(projectKey);
273
+ const validated = CellCreateArgsSchema.parse(args);
274
+ const projectKey = getHiveWorkingDirectory();
275
+ const adapter = await getHiveAdapter(projectKey);
263
276
 
264
277
  try {
265
- const bead = await adapter.createBead(projectKey, {
278
+ const cell = await adapter.createCell(projectKey, {
266
279
  title: validated.title,
267
280
  type: validated.type || "task",
268
281
  priority: validated.priority ?? 2,
@@ -271,15 +284,15 @@ export const beads_create = tool({
271
284
  });
272
285
 
273
286
  // Mark dirty for export
274
- await adapter.markDirty(projectKey, bead.id);
287
+ await adapter.markDirty(projectKey, cell.id);
275
288
 
276
- const formatted = formatBeadForOutput(bead);
289
+ const formatted = formatCellForOutput(cell);
277
290
  return JSON.stringify(formatted, null, 2);
278
291
  } catch (error) {
279
292
  const message = error instanceof Error ? error.message : String(error);
280
- throw new BeadError(
281
- `Failed to create bead: ${message}`,
282
- "beads_create",
293
+ throw new HiveError(
294
+ `Failed to create cell: ${message}`,
295
+ "hive_create",
283
296
  );
284
297
  }
285
298
  },
@@ -288,7 +301,7 @@ export const beads_create = tool({
288
301
  /**
289
302
  * Create an epic with subtasks in one atomic operation
290
303
  */
291
- export const beads_create_epic = tool({
304
+ export const hive_create_epic = tool({
292
305
  description: "Create epic with subtasks in one atomic operation",
293
306
  args: {
294
307
  epic_title: tool.schema.string().describe("Epic title"),
@@ -338,13 +351,13 @@ export const beads_create_epic = tool({
338
351
  },
339
352
  async execute(args, ctx) {
340
353
  const validated = EpicCreateArgsSchema.parse(args);
341
- const projectKey = getBeadsWorkingDirectory();
342
- const adapter = await getBeadsAdapter(projectKey);
343
- const created: AdapterBead[] = [];
354
+ const projectKey = getHiveWorkingDirectory();
355
+ const adapter = await getHiveAdapter(projectKey);
356
+ const created: AdapterCell[] = [];
344
357
 
345
358
  try {
346
359
  // 1. Create epic
347
- const epic = await adapter.createBead(projectKey, {
360
+ const epic = await adapter.createCell(projectKey, {
348
361
  title: validated.epic_title,
349
362
  type: "epic",
350
363
  priority: 1,
@@ -355,20 +368,20 @@ export const beads_create_epic = tool({
355
368
 
356
369
  // 2. Create subtasks
357
370
  for (const subtask of validated.subtasks) {
358
- const subtaskBead = await adapter.createBead(projectKey, {
371
+ const subtaskCell = await adapter.createCell(projectKey, {
359
372
  title: subtask.title,
360
373
  type: "task",
361
374
  priority: subtask.priority ?? 2,
362
375
  parent_id: epic.id,
363
376
  });
364
- await adapter.markDirty(projectKey, subtaskBead.id);
365
- created.push(subtaskBead);
377
+ await adapter.markDirty(projectKey, subtaskCell.id);
378
+ created.push(subtaskCell);
366
379
  }
367
380
 
368
381
  const result: EpicCreateResult = {
369
382
  success: true,
370
- epic: formatBeadForOutput(epic) as Bead,
371
- subtasks: created.slice(1).map((b) => formatBeadForOutput(b) as Bead),
383
+ epic: formatCellForOutput(epic) as Cell,
384
+ subtasks: created.slice(1).map((c) => formatCellForOutput(c) as Cell),
372
385
  };
373
386
 
374
387
  // Emit DecompositionGeneratedEvent for learning system
@@ -392,7 +405,7 @@ export const beads_create_epic = tool({
392
405
  } catch (error) {
393
406
  // Non-fatal - log and continue
394
407
  console.warn(
395
- "[beads_create_epic] Failed to emit DecompositionGeneratedEvent:",
408
+ "[hive_create_epic] Failed to emit DecompositionGeneratedEvent:",
396
409
  error,
397
410
  );
398
411
  }
@@ -400,12 +413,12 @@ export const beads_create_epic = tool({
400
413
 
401
414
  return JSON.stringify(result, null, 2);
402
415
  } catch (error) {
403
- // Partial failure - rollback via deleteBead
416
+ // Partial failure - rollback via deleteCell
404
417
  const rollbackErrors: string[] = [];
405
418
 
406
- for (const bead of created) {
419
+ for (const cell of created) {
407
420
  try {
408
- await adapter.deleteBead(projectKey, bead.id, {
421
+ await adapter.deleteCell(projectKey, cell.id, {
409
422
  reason: "Rollback partial epic",
410
423
  });
411
424
  } catch (rollbackError) {
@@ -413,21 +426,21 @@ export const beads_create_epic = tool({
413
426
  rollbackError instanceof Error
414
427
  ? rollbackError.message
415
428
  : String(rollbackError);
416
- console.error(`Failed to rollback bead ${bead.id}:`, rollbackError);
417
- rollbackErrors.push(`${bead.id}: ${errMsg}`);
429
+ console.error(`Failed to rollback cell ${cell.id}:`, rollbackError);
430
+ rollbackErrors.push(`${cell.id}: ${errMsg}`);
418
431
  }
419
432
  }
420
433
 
421
434
  const errorMsg = error instanceof Error ? error.message : String(error);
422
- let rollbackInfo = `\n\nRolled back ${created.length - rollbackErrors.length} bead(s)`;
435
+ let rollbackInfo = `\n\nRolled back ${created.length - rollbackErrors.length} cell(s)`;
423
436
 
424
437
  if (rollbackErrors.length > 0) {
425
438
  rollbackInfo += `\n\nRollback failures (${rollbackErrors.length}):\n${rollbackErrors.join("\n")}`;
426
439
  }
427
440
 
428
- throw new BeadError(
441
+ throw new HiveError(
429
442
  `Epic creation failed: ${errorMsg}${rollbackInfo}`,
430
- "beads_create_epic",
443
+ "hive_create_epic",
431
444
  1,
432
445
  );
433
446
  }
@@ -435,10 +448,10 @@ export const beads_create_epic = tool({
435
448
  });
436
449
 
437
450
  /**
438
- * Query beads with filters
451
+ * Query cells with filters
439
452
  */
440
- export const beads_query = tool({
441
- description: "Query beads with filters (replaces bd list, bd ready, bd wip)",
453
+ export const hive_query = tool({
454
+ description: "Query hive cells with filters (replaces bd list, bd ready, bd wip)",
442
455
  args: {
443
456
  status: tool.schema
444
457
  .enum(["open", "in_progress", "blocked", "closed"])
@@ -451,50 +464,50 @@ export const beads_query = tool({
451
464
  ready: tool.schema
452
465
  .boolean()
453
466
  .optional()
454
- .describe("Only show unblocked beads (uses bd ready)"),
467
+ .describe("Only show unblocked cells"),
455
468
  limit: tool.schema
456
469
  .number()
457
470
  .optional()
458
471
  .describe("Max results to return (default: 20)"),
459
472
  },
460
473
  async execute(args, ctx) {
461
- const validated = BeadQueryArgsSchema.parse(args);
462
- const projectKey = getBeadsWorkingDirectory();
463
- const adapter = await getBeadsAdapter(projectKey);
474
+ const validated = CellQueryArgsSchema.parse(args);
475
+ const projectKey = getHiveWorkingDirectory();
476
+ const adapter = await getHiveAdapter(projectKey);
464
477
 
465
478
  try {
466
- let beads: AdapterBead[];
479
+ let cells: AdapterCell[];
467
480
 
468
481
  if (validated.ready) {
469
- const readyBead = await adapter.getNextReadyBead(projectKey);
470
- beads = readyBead ? [readyBead] : [];
482
+ const readyCell = await adapter.getNextReadyCell(projectKey);
483
+ cells = readyCell ? [readyCell] : [];
471
484
  } else {
472
- beads = await adapter.queryBeads(projectKey, {
485
+ cells = await adapter.queryCells(projectKey, {
473
486
  status: validated.status,
474
487
  type: validated.type,
475
488
  limit: validated.limit || 20,
476
489
  });
477
490
  }
478
491
 
479
- const formatted = beads.map((b) => formatBeadForOutput(b));
492
+ const formatted = cells.map((c) => formatCellForOutput(c));
480
493
  return JSON.stringify(formatted, null, 2);
481
494
  } catch (error) {
482
495
  const message = error instanceof Error ? error.message : String(error);
483
- throw new BeadError(
484
- `Failed to query beads: ${message}`,
485
- "beads_query",
496
+ throw new HiveError(
497
+ `Failed to query cells: ${message}`,
498
+ "hive_query",
486
499
  );
487
500
  }
488
501
  },
489
502
  });
490
503
 
491
504
  /**
492
- * Update a bead's status or description
505
+ * Update a cell's status or description
493
506
  */
494
- export const beads_update = tool({
495
- description: "Update bead status/description",
507
+ export const hive_update = tool({
508
+ description: "Update cell status/description",
496
509
  args: {
497
- id: tool.schema.string().describe("Bead ID"),
510
+ id: tool.schema.string().describe("Cell ID"),
498
511
  status: tool.schema
499
512
  .enum(["open", "in_progress", "blocked", "closed"])
500
513
  .optional()
@@ -508,16 +521,16 @@ export const beads_update = tool({
508
521
  .describe("New priority"),
509
522
  },
510
523
  async execute(args, ctx) {
511
- const validated = BeadUpdateArgsSchema.parse(args);
512
- const projectKey = getBeadsWorkingDirectory();
513
- const adapter = await getBeadsAdapter(projectKey);
524
+ const validated = CellUpdateArgsSchema.parse(args);
525
+ const projectKey = getHiveWorkingDirectory();
526
+ const adapter = await getHiveAdapter(projectKey);
514
527
 
515
528
  try {
516
- let bead: AdapterBead;
529
+ let cell: AdapterCell;
517
530
 
518
- // Status changes use changeBeadStatus, other fields use updateBead
531
+ // Status changes use changeCellStatus, other fields use updateCell
519
532
  if (validated.status) {
520
- bead = await adapter.changeBeadStatus(
533
+ cell = await adapter.changeCellStatus(
521
534
  projectKey,
522
535
  validated.id,
523
536
  validated.status,
@@ -526,52 +539,52 @@ export const beads_update = tool({
526
539
 
527
540
  // Update other fields if provided
528
541
  if (validated.description !== undefined || validated.priority !== undefined) {
529
- bead = await adapter.updateBead(projectKey, validated.id, {
542
+ cell = await adapter.updateCell(projectKey, validated.id, {
530
543
  description: validated.description,
531
544
  priority: validated.priority,
532
545
  });
533
546
  } else if (!validated.status) {
534
547
  // No changes requested
535
- const existingBead = await adapter.getBead(projectKey, validated.id);
536
- if (!existingBead) {
537
- throw new BeadError(
538
- `Bead not found: ${validated.id}`,
539
- "beads_update",
548
+ const existingCell = await adapter.getCell(projectKey, validated.id);
549
+ if (!existingCell) {
550
+ throw new HiveError(
551
+ `Cell not found: ${validated.id}`,
552
+ "hive_update",
540
553
  );
541
554
  }
542
- bead = existingBead;
555
+ cell = existingCell;
543
556
  }
544
557
 
545
558
  await adapter.markDirty(projectKey, validated.id);
546
559
 
547
- const formatted = formatBeadForOutput(bead!);
560
+ const formatted = formatCellForOutput(cell!);
548
561
  return JSON.stringify(formatted, null, 2);
549
562
  } catch (error) {
550
563
  const message = error instanceof Error ? error.message : String(error);
551
- throw new BeadError(
552
- `Failed to update bead: ${message}`,
553
- "beads_update",
564
+ throw new HiveError(
565
+ `Failed to update cell: ${message}`,
566
+ "hive_update",
554
567
  );
555
568
  }
556
569
  },
557
570
  });
558
571
 
559
572
  /**
560
- * Close a bead with reason
573
+ * Close a cell with reason
561
574
  */
562
- export const beads_close = tool({
563
- description: "Close a bead with reason",
575
+ export const hive_close = tool({
576
+ description: "Close a cell with reason",
564
577
  args: {
565
- id: tool.schema.string().describe("Bead ID"),
578
+ id: tool.schema.string().describe("Cell ID"),
566
579
  reason: tool.schema.string().describe("Completion reason"),
567
580
  },
568
581
  async execute(args, ctx) {
569
- const validated = BeadCloseArgsSchema.parse(args);
570
- const projectKey = getBeadsWorkingDirectory();
571
- const adapter = await getBeadsAdapter(projectKey);
582
+ const validated = CellCloseArgsSchema.parse(args);
583
+ const projectKey = getHiveWorkingDirectory();
584
+ const adapter = await getHiveAdapter(projectKey);
572
585
 
573
586
  try {
574
- const bead = await adapter.closeBead(
587
+ const cell = await adapter.closeCell(
575
588
  projectKey,
576
589
  validated.id,
577
590
  validated.reason,
@@ -579,32 +592,32 @@ export const beads_close = tool({
579
592
 
580
593
  await adapter.markDirty(projectKey, validated.id);
581
594
 
582
- return `Closed ${bead.id}: ${validated.reason}`;
595
+ return `Closed ${cell.id}: ${validated.reason}`;
583
596
  } catch (error) {
584
597
  const message = error instanceof Error ? error.message : String(error);
585
- throw new BeadError(
586
- `Failed to close bead: ${message}`,
587
- "beads_close",
598
+ throw new HiveError(
599
+ `Failed to close cell: ${message}`,
600
+ "hive_close",
588
601
  );
589
602
  }
590
603
  },
591
604
  });
592
605
 
593
606
  /**
594
- * Mark a bead as in-progress
607
+ * Mark a cell as in-progress
595
608
  */
596
- export const beads_start = tool({
609
+ export const hive_start = tool({
597
610
  description:
598
- "Mark a bead as in-progress (shortcut for update --status in_progress)",
611
+ "Mark a cell as in-progress (shortcut for update --status in_progress)",
599
612
  args: {
600
- id: tool.schema.string().describe("Bead ID"),
613
+ id: tool.schema.string().describe("Cell ID"),
601
614
  },
602
615
  async execute(args, ctx) {
603
- const projectKey = getBeadsWorkingDirectory();
604
- const adapter = await getBeadsAdapter(projectKey);
616
+ const projectKey = getHiveWorkingDirectory();
617
+ const adapter = await getHiveAdapter(projectKey);
605
618
 
606
619
  try {
607
- const bead = await adapter.changeBeadStatus(
620
+ const cell = await adapter.changeCellStatus(
608
621
  projectKey,
609
622
  args.id,
610
623
  "in_progress",
@@ -612,51 +625,51 @@ export const beads_start = tool({
612
625
 
613
626
  await adapter.markDirty(projectKey, args.id);
614
627
 
615
- return `Started: ${bead.id}`;
628
+ return `Started: ${cell.id}`;
616
629
  } catch (error) {
617
630
  const message = error instanceof Error ? error.message : String(error);
618
- throw new BeadError(
619
- `Failed to start bead: ${message}`,
620
- "beads_start",
631
+ throw new HiveError(
632
+ `Failed to start cell: ${message}`,
633
+ "hive_start",
621
634
  );
622
635
  }
623
636
  },
624
637
  });
625
638
 
626
639
  /**
627
- * Get the next ready bead
640
+ * Get the next ready cell
628
641
  */
629
- export const beads_ready = tool({
630
- description: "Get the next ready bead (unblocked, highest priority)",
642
+ export const hive_ready = tool({
643
+ description: "Get the next ready cell (unblocked, highest priority)",
631
644
  args: {},
632
645
  async execute(args, ctx) {
633
- const projectKey = getBeadsWorkingDirectory();
634
- const adapter = await getBeadsAdapter(projectKey);
646
+ const projectKey = getHiveWorkingDirectory();
647
+ const adapter = await getHiveAdapter(projectKey);
635
648
 
636
649
  try {
637
- const bead = await adapter.getNextReadyBead(projectKey);
650
+ const cell = await adapter.getNextReadyCell(projectKey);
638
651
 
639
- if (!bead) {
640
- return "No ready beads";
652
+ if (!cell) {
653
+ return "No ready cells";
641
654
  }
642
655
 
643
- const formatted = formatBeadForOutput(bead);
656
+ const formatted = formatCellForOutput(cell);
644
657
  return JSON.stringify(formatted, null, 2);
645
658
  } catch (error) {
646
659
  const message = error instanceof Error ? error.message : String(error);
647
- throw new BeadError(
648
- `Failed to get ready beads: ${message}`,
649
- "beads_ready",
660
+ throw new HiveError(
661
+ `Failed to get ready cells: ${message}`,
662
+ "hive_ready",
650
663
  );
651
664
  }
652
665
  },
653
666
  });
654
667
 
655
668
  /**
656
- * Sync beads to git and push
669
+ * Sync hive to git and push
657
670
  */
658
- export const beads_sync = tool({
659
- description: "Sync beads to git and push (MANDATORY at session end)",
671
+ export const hive_sync = tool({
672
+ description: "Sync hive to git and push (MANDATORY at session end)",
660
673
  args: {
661
674
  auto_pull: tool.schema
662
675
  .boolean()
@@ -665,8 +678,8 @@ export const beads_sync = tool({
665
678
  },
666
679
  async execute(args, ctx) {
667
680
  const autoPull = args.auto_pull ?? true;
668
- const projectKey = getBeadsWorkingDirectory();
669
- const adapter = await getBeadsAdapter(projectKey);
681
+ const projectKey = getHiveWorkingDirectory();
682
+ const adapter = await getHiveAdapter(projectKey);
670
683
  const TIMEOUT_MS = 30000; // 30 seconds
671
684
 
672
685
  /**
@@ -683,7 +696,7 @@ export const beads_sync = tool({
683
696
  timeoutId = setTimeout(
684
697
  () =>
685
698
  reject(
686
- new BeadError(
699
+ new HiveError(
687
700
  `Operation timed out after ${timeoutMs}ms`,
688
701
  operation,
689
702
  ),
@@ -701,45 +714,45 @@ export const beads_sync = tool({
701
714
  }
702
715
  };
703
716
 
704
- // 1. Flush beads to JSONL using FlushManager
717
+ // 1. Flush cells to JSONL using FlushManager
705
718
  const flushManager = new FlushManager({
706
719
  adapter,
707
720
  projectKey,
708
- outputPath: `${projectKey}/.beads/issues.jsonl`,
721
+ outputPath: `${projectKey}/.hive/issues.jsonl`,
709
722
  });
710
723
 
711
724
  const flushResult = await withTimeout(
712
725
  flushManager.flush(),
713
726
  TIMEOUT_MS,
714
- "flush beads",
727
+ "flush hive",
715
728
  );
716
729
 
717
- if (flushResult.beadsExported === 0) {
718
- return "No beads to sync";
730
+ if (flushResult.cellsExported === 0) {
731
+ return "No cells to sync";
719
732
  }
720
733
 
721
734
  // 2. Check if there are changes to commit
722
- const beadsStatusResult = await runGitCommand([
735
+ const hiveStatusResult = await runGitCommand([
723
736
  "status",
724
737
  "--porcelain",
725
- ".beads/",
738
+ ".hive/",
726
739
  ]);
727
- const hasChanges = beadsStatusResult.stdout.trim() !== "";
740
+ const hasChanges = hiveStatusResult.stdout.trim() !== "";
728
741
 
729
742
  if (hasChanges) {
730
- // 3. Stage .beads changes
731
- const addResult = await runGitCommand(["add", ".beads/"]);
743
+ // 3. Stage .hive changes
744
+ const addResult = await runGitCommand(["add", ".hive/"]);
732
745
  if (addResult.exitCode !== 0) {
733
- throw new BeadError(
734
- `Failed to stage beads: ${addResult.stderr}`,
735
- "git add .beads/",
746
+ throw new HiveError(
747
+ `Failed to stage hive: ${addResult.stderr}`,
748
+ "git add .hive/",
736
749
  addResult.exitCode,
737
750
  );
738
751
  }
739
752
 
740
753
  // 4. Commit
741
754
  const commitResult = await withTimeout(
742
- runGitCommand(["commit", "-m", "chore: sync beads"]),
755
+ runGitCommand(["commit", "-m", "chore: sync hive"]),
743
756
  TIMEOUT_MS,
744
757
  "git commit",
745
758
  );
@@ -747,8 +760,8 @@ export const beads_sync = tool({
747
760
  commitResult.exitCode !== 0 &&
748
761
  !commitResult.stdout.includes("nothing to commit")
749
762
  ) {
750
- throw new BeadError(
751
- `Failed to commit beads: ${commitResult.stderr}`,
763
+ throw new HiveError(
764
+ `Failed to commit hive: ${commitResult.stderr}`,
752
765
  "git commit",
753
766
  commitResult.exitCode,
754
767
  );
@@ -764,7 +777,7 @@ export const beads_sync = tool({
764
777
  );
765
778
 
766
779
  if (pullResult.exitCode !== 0) {
767
- throw new BeadError(
780
+ throw new HiveError(
768
781
  `Failed to pull: ${pullResult.stderr}`,
769
782
  "git pull --rebase",
770
783
  pullResult.exitCode,
@@ -779,63 +792,63 @@ export const beads_sync = tool({
779
792
  "git push",
780
793
  );
781
794
  if (pushResult.exitCode !== 0) {
782
- throw new BeadError(
795
+ throw new HiveError(
783
796
  `Failed to push: ${pushResult.stderr}`,
784
797
  "git push",
785
798
  pushResult.exitCode,
786
799
  );
787
800
  }
788
801
 
789
- return "Beads synced and pushed successfully";
802
+ return "Hive synced and pushed successfully";
790
803
  },
791
804
  });
792
805
 
793
806
  /**
794
- * Link a bead to an Agent Mail thread
807
+ * Link a cell to an Agent Mail thread
795
808
  */
796
- export const beads_link_thread = tool({
797
- description: "Add metadata linking bead to Agent Mail thread",
809
+ export const hive_link_thread = tool({
810
+ description: "Add metadata linking cell to Agent Mail thread",
798
811
  args: {
799
- bead_id: tool.schema.string().describe("Bead ID"),
812
+ cell_id: tool.schema.string().describe("Cell ID"),
800
813
  thread_id: tool.schema.string().describe("Agent Mail thread ID"),
801
814
  },
802
815
  async execute(args, ctx) {
803
- const projectKey = getBeadsWorkingDirectory();
804
- const adapter = await getBeadsAdapter(projectKey);
816
+ const projectKey = getHiveWorkingDirectory();
817
+ const adapter = await getHiveAdapter(projectKey);
805
818
 
806
819
  try {
807
- const bead = await adapter.getBead(projectKey, args.bead_id);
820
+ const cell = await adapter.getCell(projectKey, args.cell_id);
808
821
 
809
- if (!bead) {
810
- throw new BeadError(
811
- `Bead not found: ${args.bead_id}`,
812
- "beads_link_thread",
822
+ if (!cell) {
823
+ throw new HiveError(
824
+ `Cell not found: ${args.cell_id}`,
825
+ "hive_link_thread",
813
826
  );
814
827
  }
815
828
 
816
- const existingDesc = bead.description || "";
829
+ const existingDesc = cell.description || "";
817
830
  const threadMarker = `[thread:${args.thread_id}]`;
818
831
 
819
832
  if (existingDesc.includes(threadMarker)) {
820
- return `Bead ${args.bead_id} already linked to thread ${args.thread_id}`;
833
+ return `Cell ${args.cell_id} already linked to thread ${args.thread_id}`;
821
834
  }
822
835
 
823
836
  const newDesc = existingDesc
824
837
  ? `${existingDesc}\n\n${threadMarker}`
825
838
  : threadMarker;
826
839
 
827
- await adapter.updateBead(projectKey, args.bead_id, {
840
+ await adapter.updateCell(projectKey, args.cell_id, {
828
841
  description: newDesc,
829
842
  });
830
843
 
831
- await adapter.markDirty(projectKey, args.bead_id);
844
+ await adapter.markDirty(projectKey, args.cell_id);
832
845
 
833
- return `Linked bead ${args.bead_id} to thread ${args.thread_id}`;
846
+ return `Linked cell ${args.cell_id} to thread ${args.thread_id}`;
834
847
  } catch (error) {
835
848
  const message = error instanceof Error ? error.message : String(error);
836
- throw new BeadError(
849
+ throw new HiveError(
837
850
  `Failed to link thread: ${message}`,
838
- "beads_link_thread",
851
+ "hive_link_thread",
839
852
  );
840
853
  }
841
854
  },
@@ -845,14 +858,160 @@ export const beads_link_thread = tool({
845
858
  // Export all tools
846
859
  // ============================================================================
847
860
 
861
+ export const hiveTools = {
862
+ hive_create,
863
+ hive_create_epic,
864
+ hive_query,
865
+ hive_update,
866
+ hive_close,
867
+ hive_start,
868
+ hive_ready,
869
+ hive_sync,
870
+ hive_link_thread,
871
+ };
872
+
873
+ // ============================================================================
874
+ // Deprecation Warning System
875
+ // ============================================================================
876
+
877
+ /**
878
+ * Track which deprecated tools have been warned about.
879
+ * Only warn once per tool name to avoid spam.
880
+ */
881
+ const warnedTools = new Set<string>();
882
+
883
+ /**
884
+ * Log a deprecation warning for a renamed tool.
885
+ * Only warns once per tool name per session.
886
+ *
887
+ * @param oldName - The deprecated tool name (e.g., "hive_create")
888
+ * @param newName - The new tool name to use instead (e.g., "hive_create")
889
+ */
890
+ function warnDeprecated(oldName: string, newName: string): void {
891
+ if (warnedTools.has(oldName)) {
892
+ return; // Already warned
893
+ }
894
+
895
+ warnedTools.add(oldName);
896
+ console.warn(
897
+ `[DEPRECATED] ${oldName} is deprecated, use ${newName} instead. Will be removed in v1.0`
898
+ );
899
+ }
900
+
901
+ // ============================================================================
902
+ // Legacy Aliases (DEPRECATED - use hive_* instead)
903
+ // ============================================================================
904
+
905
+ /**
906
+ * @deprecated Use hive_create instead. Will be removed in v1.0
907
+ */
908
+ export const beads_create = tool({
909
+ ...hive_create,
910
+ async execute(args, ctx) {
911
+ warnDeprecated('beads_create', 'hive_create');
912
+ return hive_create.execute(args, ctx);
913
+ }
914
+ });
915
+
916
+ /**
917
+ * @deprecated Use hive_create_epic instead. Will be removed in v1.0
918
+ */
919
+ export const beads_create_epic = tool({
920
+ ...hive_create_epic,
921
+ async execute(args, ctx) {
922
+ warnDeprecated('beads_create_epic', 'hive_create_epic');
923
+ return hive_create_epic.execute(args, ctx);
924
+ }
925
+ });
926
+
927
+ /**
928
+ * @deprecated Use hive_query instead. Will be removed in v1.0
929
+ */
930
+ export const beads_query = tool({
931
+ ...hive_query,
932
+ async execute(args, ctx) {
933
+ warnDeprecated('beads_query', 'hive_query');
934
+ return hive_query.execute(args, ctx);
935
+ }
936
+ });
937
+
938
+ /**
939
+ * @deprecated Use hive_update instead. Will be removed in v1.0
940
+ */
941
+ export const beads_update = tool({
942
+ ...hive_update,
943
+ async execute(args, ctx) {
944
+ warnDeprecated('beads_update', 'hive_update');
945
+ return hive_update.execute(args, ctx);
946
+ }
947
+ });
948
+
949
+ /**
950
+ * @deprecated Use hive_close instead. Will be removed in v1.0
951
+ */
952
+ export const beads_close = tool({
953
+ ...hive_close,
954
+ async execute(args, ctx) {
955
+ warnDeprecated('beads_close', 'hive_close');
956
+ return hive_close.execute(args, ctx);
957
+ }
958
+ });
959
+
960
+ /**
961
+ * @deprecated Use hive_start instead. Will be removed in v1.0
962
+ */
963
+ export const beads_start = tool({
964
+ ...hive_start,
965
+ async execute(args, ctx) {
966
+ warnDeprecated('beads_start', 'hive_start');
967
+ return hive_start.execute(args, ctx);
968
+ }
969
+ });
970
+
971
+ /**
972
+ * @deprecated Use hive_ready instead. Will be removed in v1.0
973
+ */
974
+ export const beads_ready = tool({
975
+ ...hive_ready,
976
+ async execute(args, ctx) {
977
+ warnDeprecated('beads_ready', 'hive_ready');
978
+ return hive_ready.execute(args, ctx);
979
+ }
980
+ });
981
+
982
+ /**
983
+ * @deprecated Use hive_sync instead. Will be removed in v1.0
984
+ */
985
+ export const beads_sync = tool({
986
+ ...hive_sync,
987
+ async execute(args, ctx) {
988
+ warnDeprecated('beads_sync', 'hive_sync');
989
+ return hive_sync.execute(args, ctx);
990
+ }
991
+ });
992
+
993
+ /**
994
+ * @deprecated Use hive_link_thread instead. Will be removed in v1.0
995
+ */
996
+ export const beads_link_thread = tool({
997
+ ...hive_link_thread,
998
+ async execute(args, ctx) {
999
+ warnDeprecated('beads_link_thread', 'hive_link_thread');
1000
+ return hive_link_thread.execute(args, ctx);
1001
+ }
1002
+ });
1003
+
1004
+ /**
1005
+ * @deprecated Use hiveTools instead. Will be removed in v1.0
1006
+ */
848
1007
  export const beadsTools = {
849
- beads_create: beads_create,
850
- beads_create_epic: beads_create_epic,
851
- beads_query: beads_query,
852
- beads_update: beads_update,
853
- beads_close: beads_close,
854
- beads_start: beads_start,
855
- beads_ready: beads_ready,
856
- beads_sync: beads_sync,
857
- beads_link_thread: beads_link_thread,
1008
+ beads_create,
1009
+ beads_create_epic,
1010
+ beads_query,
1011
+ beads_update,
1012
+ beads_close,
1013
+ beads_start,
1014
+ beads_ready,
1015
+ beads_sync,
1016
+ beads_link_thread,
858
1017
  };