opencode-swarm-plugin 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +37 -0
  3. package/README.md +43 -46
  4. package/bin/swarm.ts +8 -8
  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 +1418 -387
  12. package/dist/learning.d.ts +9 -9
  13. package/dist/plugin.js +1240 -386
  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/hive.ts +1017 -0
  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 -383
  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/beads.ts +0 -800
  78. package/src/schemas/bead-events.ts +0 -583
@@ -125,7 +125,7 @@ async function execTool(
125
125
  // Beads Tools
126
126
  // =============================================================================
127
127
 
128
- const beads_create = tool({
128
+ const hive_create = tool({
129
129
  description: "Create a new bead with type-safe validation",
130
130
  args: {
131
131
  title: tool.schema.string().describe("Bead title"),
@@ -145,10 +145,10 @@ const beads_create = tool({
145
145
  .optional()
146
146
  .describe("Parent bead ID for epic children"),
147
147
  },
148
- execute: (args, ctx) => execTool("beads_create", args, ctx),
148
+ execute: (args, ctx) => execTool("hive_create", args, ctx),
149
149
  });
150
150
 
151
- const beads_create_epic = tool({
151
+ const hive_create_epic = tool({
152
152
  description: "Create epic with subtasks in one atomic operation",
153
153
  args: {
154
154
  epic_title: tool.schema.string().describe("Epic title"),
@@ -166,10 +166,10 @@ const beads_create_epic = tool({
166
166
  )
167
167
  .describe("Subtasks to create under the epic"),
168
168
  },
169
- execute: (args, ctx) => execTool("beads_create_epic", args, ctx),
169
+ execute: (args, ctx) => execTool("hive_create_epic", args, ctx),
170
170
  });
171
171
 
172
- const beads_query = tool({
172
+ const hive_query = tool({
173
173
  description: "Query beads with filters (replaces bd list, bd ready, bd wip)",
174
174
  args: {
175
175
  status: tool.schema
@@ -189,13 +189,13 @@ const beads_query = tool({
189
189
  .optional()
190
190
  .describe("Max results (default: 20)"),
191
191
  },
192
- execute: (args, ctx) => execTool("beads_query", args, ctx),
192
+ execute: (args, ctx) => execTool("hive_query", args, ctx),
193
193
  });
194
194
 
195
- const beads_update = tool({
195
+ const hive_update = tool({
196
196
  description: "Update bead status/description",
197
197
  args: {
198
- id: tool.schema.string().describe("Bead ID"),
198
+ id: tool.schema.string().describe("Cell ID"),
199
199
  status: tool.schema
200
200
  .enum(["open", "in_progress", "blocked", "closed"])
201
201
  .optional()
@@ -208,44 +208,44 @@ const beads_update = tool({
208
208
  .optional()
209
209
  .describe("New priority"),
210
210
  },
211
- execute: (args, ctx) => execTool("beads_update", args, ctx),
211
+ execute: (args, ctx) => execTool("hive_update", args, ctx),
212
212
  });
213
213
 
214
- const beads_close = tool({
214
+ const hive_close = tool({
215
215
  description: "Close a bead with reason",
216
216
  args: {
217
- id: tool.schema.string().describe("Bead ID"),
217
+ id: tool.schema.string().describe("Cell ID"),
218
218
  reason: tool.schema.string().describe("Completion reason"),
219
219
  },
220
- execute: (args, ctx) => execTool("beads_close", args, ctx),
220
+ execute: (args, ctx) => execTool("hive_close", args, ctx),
221
221
  });
222
222
 
223
- const beads_start = tool({
223
+ const hive_start = tool({
224
224
  description: "Mark a bead as in-progress",
225
225
  args: {
226
- id: tool.schema.string().describe("Bead ID"),
226
+ id: tool.schema.string().describe("Cell ID"),
227
227
  },
228
- execute: (args, ctx) => execTool("beads_start", args, ctx),
228
+ execute: (args, ctx) => execTool("hive_start", args, ctx),
229
229
  });
230
230
 
231
- const beads_ready = tool({
231
+ const hive_ready = tool({
232
232
  description: "Get the next ready bead (unblocked, highest priority)",
233
233
  args: {},
234
- execute: (args, ctx) => execTool("beads_ready", args, ctx),
234
+ execute: (args, ctx) => execTool("hive_ready", args, ctx),
235
235
  });
236
236
 
237
- const beads_sync = tool({
237
+ const hive_sync = tool({
238
238
  description: "Sync beads to git and push (MANDATORY at session end)",
239
239
  args: {
240
240
  auto_pull: tool.schema.boolean().optional().describe("Pull before sync"),
241
241
  },
242
- execute: (args, ctx) => execTool("beads_sync", args, ctx),
242
+ execute: (args, ctx) => execTool("hive_sync", args, ctx),
243
243
  });
244
244
 
245
245
  const beads_link_thread = tool({
246
246
  description: "Add metadata linking bead to Agent Mail thread",
247
247
  args: {
248
- bead_id: tool.schema.string().describe("Bead ID"),
248
+ bead_id: tool.schema.string().describe("Cell ID"),
249
249
  thread_id: tool.schema.string().describe("Agent Mail thread ID"),
250
250
  },
251
251
  execute: (args, ctx) => execTool("beads_link_thread", args, ctx),
@@ -375,7 +375,7 @@ const structured_validate = tool({
375
375
  args: {
376
376
  response: tool.schema.string().describe("Agent response to validate"),
377
377
  schema_name: tool.schema
378
- .enum(["evaluation", "task_decomposition", "bead_tree"])
378
+ .enum(["evaluation", "task_decomposition", "cell_tree"])
379
379
  .describe("Schema to validate against"),
380
380
  max_retries: tool.schema
381
381
  .number()
@@ -403,12 +403,12 @@ const structured_parse_decomposition = tool({
403
403
  execute: (args, ctx) => execTool("structured_parse_decomposition", args, ctx),
404
404
  });
405
405
 
406
- const structured_parse_bead_tree = tool({
406
+ const structured_parse_cell_tree = tool({
407
407
  description: "Parse and validate bead tree response",
408
408
  args: {
409
409
  response: tool.schema.string().describe("Agent response"),
410
410
  },
411
- execute: (args, ctx) => execTool("structured_parse_bead_tree", args, ctx),
411
+ execute: (args, ctx) => execTool("structured_parse_cell_tree", args, ctx),
412
412
  });
413
413
 
414
414
  // =============================================================================
@@ -419,6 +419,12 @@ const swarm_init = tool({
419
419
  description: "Initialize swarm session and check tool availability",
420
420
  args: {
421
421
  project_path: tool.schema.string().optional().describe("Project path"),
422
+ isolation: tool.schema
423
+ .enum(["worktree", "reservation"])
424
+ .optional()
425
+ .describe(
426
+ "Isolation mode: 'worktree' for git worktree isolation, 'reservation' for file reservations (default)",
427
+ ),
422
428
  },
423
429
  execute: (args, ctx) => execTool("swarm_init", args, ctx),
424
430
  });
@@ -491,7 +497,7 @@ const swarm_decompose = tool({
491
497
  });
492
498
 
493
499
  const swarm_validate_decomposition = tool({
494
- description: "Validate a decomposition response against BeadTreeSchema",
500
+ description: "Validate a decomposition response against CellTreeSchema",
495
501
  args: {
496
502
  response: tool.schema.string().describe("Decomposition response"),
497
503
  },
@@ -512,7 +518,7 @@ const swarm_progress = tool({
512
518
  args: {
513
519
  project_key: tool.schema.string().describe("Project key"),
514
520
  agent_name: tool.schema.string().describe("Agent name"),
515
- bead_id: tool.schema.string().describe("Bead ID"),
521
+ bead_id: tool.schema.string().describe("Cell ID"),
516
522
  status: tool.schema
517
523
  .enum(["in_progress", "blocked", "completed", "failed"])
518
524
  .describe("Status"),
@@ -533,18 +539,26 @@ const swarm_progress = tool({
533
539
 
534
540
  const swarm_complete = tool({
535
541
  description:
536
- "Mark subtask complete, release reservations, notify coordinator",
542
+ "Mark subtask complete with Verification Gate. Runs UBS scan, typecheck, and tests before allowing completion.",
537
543
  args: {
538
544
  project_key: tool.schema.string().describe("Project key"),
539
545
  agent_name: tool.schema.string().describe("Agent name"),
540
- bead_id: tool.schema.string().describe("Bead ID"),
546
+ bead_id: tool.schema.string().describe("Cell ID"),
541
547
  summary: tool.schema.string().describe("Completion summary"),
542
- evaluation: tool.schema.string().optional().describe("Self-evaluation"),
548
+ evaluation: tool.schema.string().optional().describe("Self-evaluation JSON"),
543
549
  files_touched: tool.schema
544
550
  .array(tool.schema.string())
545
551
  .optional()
546
- .describe("Files modified"),
552
+ .describe("Files modified - will be verified"),
547
553
  skip_ubs_scan: tool.schema.boolean().optional().describe("Skip UBS scan"),
554
+ skip_verification: tool.schema
555
+ .boolean()
556
+ .optional()
557
+ .describe("Skip ALL verification (UBS, typecheck, tests)"),
558
+ skip_review: tool.schema
559
+ .boolean()
560
+ .optional()
561
+ .describe("Skip review gate check"),
548
562
  },
549
563
  execute: (args, ctx) => execTool("swarm_complete", args, ctx),
550
564
  });
@@ -552,7 +566,7 @@ const swarm_complete = tool({
552
566
  const swarm_record_outcome = tool({
553
567
  description: "Record subtask outcome for implicit feedback scoring",
554
568
  args: {
555
- bead_id: tool.schema.string().describe("Bead ID"),
569
+ bead_id: tool.schema.string().describe("Cell ID"),
556
570
  duration_ms: tool.schema.number().int().min(0).describe("Duration in ms"),
557
571
  error_count: tool.schema
558
572
  .number()
@@ -587,7 +601,7 @@ const swarm_subtask_prompt = tool({
587
601
  description: "Generate the prompt for a spawned subtask agent",
588
602
  args: {
589
603
  agent_name: tool.schema.string().describe("Agent name"),
590
- bead_id: tool.schema.string().describe("Bead ID"),
604
+ bead_id: tool.schema.string().describe("Cell ID"),
591
605
  epic_id: tool.schema.string().describe("Epic ID"),
592
606
  subtask_title: tool.schema.string().describe("Subtask title"),
593
607
  subtask_description: tool.schema
@@ -603,7 +617,7 @@ const swarm_subtask_prompt = tool({
603
617
  const swarm_spawn_subtask = tool({
604
618
  description: "Prepare a subtask for spawning with Task tool",
605
619
  args: {
606
- bead_id: tool.schema.string().describe("Bead ID"),
620
+ bead_id: tool.schema.string().describe("Cell ID"),
607
621
  epic_id: tool.schema.string().describe("Epic ID"),
608
622
  subtask_title: tool.schema.string().describe("Subtask title"),
609
623
  subtask_description: tool.schema
@@ -619,7 +633,7 @@ const swarm_spawn_subtask = tool({
619
633
  const swarm_complete_subtask = tool({
620
634
  description: "Handle subtask completion after Task agent returns",
621
635
  args: {
622
- bead_id: tool.schema.string().describe("Bead ID"),
636
+ bead_id: tool.schema.string().describe("Cell ID"),
623
637
  task_result: tool.schema.string().describe("Task result JSON"),
624
638
  files_touched: tool.schema
625
639
  .array(tool.schema.string())
@@ -632,7 +646,7 @@ const swarm_complete_subtask = tool({
632
646
  const swarm_evaluation_prompt = tool({
633
647
  description: "Generate self-evaluation prompt for a completed subtask",
634
648
  args: {
635
- bead_id: tool.schema.string().describe("Bead ID"),
649
+ bead_id: tool.schema.string().describe("Cell ID"),
636
650
  subtask_title: tool.schema.string().describe("Subtask title"),
637
651
  files_touched: tool.schema
638
652
  .array(tool.schema.string())
@@ -641,6 +655,117 @@ const swarm_evaluation_prompt = tool({
641
655
  execute: (args, ctx) => execTool("swarm_evaluation_prompt", args, ctx),
642
656
  });
643
657
 
658
+ const swarm_broadcast = tool({
659
+ description:
660
+ "Broadcast context update to all agents working on the same epic",
661
+ args: {
662
+ project_path: tool.schema.string().describe("Project path"),
663
+ agent_name: tool.schema.string().describe("Agent name"),
664
+ epic_id: tool.schema.string().describe("Epic ID"),
665
+ message: tool.schema.string().describe("Context update message"),
666
+ importance: tool.schema
667
+ .enum(["info", "warning", "blocker"])
668
+ .optional()
669
+ .describe("Priority level (default: info)"),
670
+ files_affected: tool.schema
671
+ .array(tool.schema.string())
672
+ .optional()
673
+ .describe("Files this context relates to"),
674
+ },
675
+ execute: (args, ctx) => execTool("swarm_broadcast", args, ctx),
676
+ });
677
+
678
+ // =============================================================================
679
+ // Worktree Isolation Tools
680
+ // =============================================================================
681
+
682
+ const swarm_worktree_create = tool({
683
+ description:
684
+ "Create a git worktree for isolated task execution. Worker operates in worktree, not main branch.",
685
+ args: {
686
+ project_path: tool.schema.string().describe("Absolute path to project root"),
687
+ task_id: tool.schema.string().describe("Task/bead ID (e.g., bd-abc123.1)"),
688
+ start_commit: tool.schema
689
+ .string()
690
+ .describe("Commit SHA to create worktree at (swarm start point)"),
691
+ },
692
+ execute: (args, ctx) => execTool("swarm_worktree_create", args, ctx),
693
+ });
694
+
695
+ const swarm_worktree_merge = tool({
696
+ description:
697
+ "Cherry-pick commits from worktree back to main branch. Call after worker completes.",
698
+ args: {
699
+ project_path: tool.schema.string().describe("Absolute path to project root"),
700
+ task_id: tool.schema.string().describe("Task/bead ID"),
701
+ start_commit: tool.schema
702
+ .string()
703
+ .optional()
704
+ .describe("Original start commit (to find new commits)"),
705
+ },
706
+ execute: (args, ctx) => execTool("swarm_worktree_merge", args, ctx),
707
+ });
708
+
709
+ const swarm_worktree_cleanup = tool({
710
+ description:
711
+ "Remove a worktree after completion or abort. Idempotent - safe to call multiple times.",
712
+ args: {
713
+ project_path: tool.schema.string().describe("Absolute path to project root"),
714
+ task_id: tool.schema.string().optional().describe("Task/bead ID to clean up"),
715
+ cleanup_all: tool.schema
716
+ .boolean()
717
+ .optional()
718
+ .describe("Remove all worktrees for this project"),
719
+ },
720
+ execute: (args, ctx) => execTool("swarm_worktree_cleanup", args, ctx),
721
+ });
722
+
723
+ const swarm_worktree_list = tool({
724
+ description: "List all active worktrees for a project",
725
+ args: {
726
+ project_path: tool.schema.string().describe("Absolute path to project root"),
727
+ },
728
+ execute: (args, ctx) => execTool("swarm_worktree_list", args, ctx),
729
+ });
730
+
731
+ // =============================================================================
732
+ // Structured Review Tools
733
+ // =============================================================================
734
+
735
+ const swarm_review = tool({
736
+ description:
737
+ "Generate a review prompt for a completed subtask. Includes epic context, dependencies, and diff.",
738
+ args: {
739
+ project_key: tool.schema.string().describe("Project path"),
740
+ epic_id: tool.schema.string().describe("Epic bead ID"),
741
+ task_id: tool.schema.string().describe("Subtask bead ID to review"),
742
+ files_touched: tool.schema
743
+ .array(tool.schema.string())
744
+ .optional()
745
+ .describe("Files modified (will get diff for these)"),
746
+ },
747
+ execute: (args, ctx) => execTool("swarm_review", args, ctx),
748
+ });
749
+
750
+ const swarm_review_feedback = tool({
751
+ description:
752
+ "Send review feedback to a worker. Tracks attempts (max 3). Fails task after 3 rejections.",
753
+ args: {
754
+ project_key: tool.schema.string().describe("Project path"),
755
+ task_id: tool.schema.string().describe("Subtask bead ID"),
756
+ worker_id: tool.schema.string().describe("Worker agent name"),
757
+ status: tool.schema
758
+ .enum(["approved", "needs_changes"])
759
+ .describe("Review status"),
760
+ summary: tool.schema.string().optional().describe("Review summary"),
761
+ issues: tool.schema
762
+ .string()
763
+ .optional()
764
+ .describe("JSON array of ReviewIssue objects (for needs_changes)"),
765
+ },
766
+ execute: (args, ctx) => execTool("swarm_review_feedback", args, ctx),
767
+ });
768
+
644
769
  // =============================================================================
645
770
  // Skills Tools
646
771
  // =============================================================================
@@ -754,20 +879,141 @@ const skills_execute = tool({
754
879
  // Plugin Export
755
880
  // =============================================================================
756
881
 
882
+ // =============================================================================
883
+ // Compaction Hook - Swarm Recovery Context
884
+ // =============================================================================
885
+
886
+ /**
887
+ * Check for swarm sign - evidence a swarm passed through
888
+ *
889
+ * Like deer scat on a trail, we look for traces:
890
+ * - In-progress beads (active work)
891
+ * - Open beads with parent_id (subtasks of an epic)
892
+ * - Unclosed epics
893
+ */
894
+ async function hasSwarmSign(): Promise<boolean> {
895
+ try {
896
+ const result = await new Promise<{ exitCode: number; stdout: string }>(
897
+ (resolve) => {
898
+ // Use swarm tool to query beads
899
+ const proc = spawn(SWARM_CLI, ["tool", "hive_query"], {
900
+ stdio: ["ignore", "pipe", "pipe"],
901
+ });
902
+ let stdout = "";
903
+ proc.stdout.on("data", (d) => {
904
+ stdout += d;
905
+ });
906
+ proc.on("close", (exitCode) =>
907
+ resolve({ exitCode: exitCode ?? 1, stdout }),
908
+ );
909
+ },
910
+ );
911
+
912
+ if (result.exitCode !== 0) return false;
913
+
914
+ const beads = JSON.parse(result.stdout);
915
+ if (!Array.isArray(beads)) return false;
916
+
917
+ // Look for swarm sign:
918
+ // 1. Any in_progress beads
919
+ // 2. Any open beads with a parent (subtasks)
920
+ // 3. Any epics that aren't closed
921
+ return beads.some(
922
+ (b: { status: string; parent_id?: string; type?: string }) =>
923
+ b.status === "in_progress" ||
924
+ (b.status === "open" && b.parent_id) ||
925
+ (b.type === "epic" && b.status !== "closed"),
926
+ );
927
+ } catch {
928
+ return false;
929
+ }
930
+ }
931
+
932
+ /**
933
+ * Swarm-aware compaction context
934
+ *
935
+ * Injected during compaction to keep the swarm cooking. The coordinator should
936
+ * wake up from compaction and immediately resume orchestration - spawning agents,
937
+ * monitoring progress, unblocking work.
938
+ */
939
+ const SWARM_COMPACTION_CONTEXT = `## 🐝 SWARM ACTIVE - Keep Cooking
940
+
941
+ You are the **COORDINATOR** of an active swarm. Context was compacted but the swarm is still running.
942
+
943
+ **YOUR JOB:** Keep orchestrating. Spawn agents. Monitor progress. Unblock work. Ship it.
944
+
945
+ ### Preserve in Summary
946
+
947
+ Extract from session context:
948
+
949
+ 1. **Epic & Subtasks** - IDs, titles, status, file assignments
950
+ 2. **What's Running** - Which agents are active, what they're working on
951
+ 3. **What's Blocked** - Blockers and what's needed to unblock
952
+ 4. **What's Done** - Completed work and any follow-ups needed
953
+ 5. **What's Next** - Pending subtasks ready to spawn
954
+
955
+ ### Summary Format
956
+
957
+ \`\`\`
958
+ ## 🐝 Swarm State
959
+
960
+ **Epic:** <bd-xxx> - <title>
961
+ **Project:** <path>
962
+ **Progress:** X/Y subtasks complete
963
+
964
+ **Active:**
965
+ - <bd-xxx>: <title> [in_progress] → <agent> working on <files>
966
+
967
+ **Blocked:**
968
+ - <bd-xxx>: <title> - BLOCKED: <reason>
969
+
970
+ **Completed:**
971
+ - <bd-xxx>: <title> ✓
972
+
973
+ **Ready to Spawn:**
974
+ - <bd-xxx>: <title> (files: <...>)
975
+ \`\`\`
976
+
977
+ ### On Resume - IMMEDIATELY
978
+
979
+ 1. \`swarm_status(epic_id="<epic>", project_key="<path>")\` - Get current state
980
+ 2. \`swarmmail_inbox(limit=5)\` - Check for agent messages
981
+ 3. **Spawn ready subtasks** - Don't wait, fire them off
982
+ 4. **Unblock blocked work** - Resolve dependencies, reassign if needed
983
+ 5. **Collect completed work** - Close done subtasks, verify quality
984
+
985
+ ### Keep the Swarm Cooking
986
+
987
+ - **Spawn aggressively** - If a subtask is ready and unblocked, spawn an agent
988
+ - **Monitor actively** - Check status, read messages, respond to blockers
989
+ - **Close the loop** - When all subtasks done, verify and close the epic
990
+ - **Don't stop** - The swarm runs until the epic is closed
991
+
992
+ **You are not waiting for instructions. You are the coordinator. Coordinate.**
993
+ `;
994
+
995
+ // Extended hooks type to include experimental compaction hook
996
+ type ExtendedHooks = Hooks & {
997
+ "experimental.session.compacting"?: (
998
+ input: { sessionID: string },
999
+ output: { context: string[] },
1000
+ ) => Promise<void>;
1001
+ };
1002
+
757
1003
  export const SwarmPlugin: Plugin = async (
758
1004
  _input: PluginInput,
759
- ): Promise<Hooks> => {
1005
+ ): Promise<ExtendedHooks> => {
760
1006
  return {
761
1007
  tool: {
762
1008
  // Beads
763
- beads_create,
764
- beads_create_epic,
765
- beads_query,
766
- beads_update,
767
- beads_close,
768
- beads_start,
769
- beads_ready,
770
- beads_sync,
1009
+ hive_create,
1010
+ hive_create_epic,
1011
+ hive_query,
1012
+ hive_update,
1013
+ hive_close,
1014
+ hive_start,
1015
+ hive_ready,
1016
+ hive_sync,
771
1017
  beads_link_thread,
772
1018
  // Swarm Mail (Embedded)
773
1019
  swarmmail_init,
@@ -783,7 +1029,7 @@ export const SwarmPlugin: Plugin = async (
783
1029
  structured_validate,
784
1030
  structured_parse_evaluation,
785
1031
  structured_parse_decomposition,
786
- structured_parse_bead_tree,
1032
+ structured_parse_cell_tree,
787
1033
  // Swarm
788
1034
  swarm_init,
789
1035
  swarm_select_strategy,
@@ -798,6 +1044,15 @@ export const SwarmPlugin: Plugin = async (
798
1044
  swarm_spawn_subtask,
799
1045
  swarm_complete_subtask,
800
1046
  swarm_evaluation_prompt,
1047
+ swarm_broadcast,
1048
+ // Worktree Isolation
1049
+ swarm_worktree_create,
1050
+ swarm_worktree_merge,
1051
+ swarm_worktree_cleanup,
1052
+ swarm_worktree_list,
1053
+ // Structured Review
1054
+ swarm_review,
1055
+ swarm_review_feedback,
801
1056
  // Skills
802
1057
  skills_list,
803
1058
  skills_read,
@@ -809,6 +1064,17 @@ export const SwarmPlugin: Plugin = async (
809
1064
  skills_add_script,
810
1065
  skills_execute,
811
1066
  },
1067
+
1068
+ // Swarm-aware compaction hook - only fires if there's an active swarm
1069
+ "experimental.session.compacting": async (
1070
+ _input: { sessionID: string },
1071
+ output: { context: string[] },
1072
+ ) => {
1073
+ const hasSign = await hasSwarmSign();
1074
+ if (hasSign) {
1075
+ output.context.push(SWARM_COMPACTION_CONTEXT);
1076
+ }
1077
+ },
812
1078
  };
813
1079
  };
814
1080