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.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +38 -0
- package/README.md +43 -46
- package/bin/swarm.ts +10 -54
- package/dist/compaction-hook.d.ts +57 -0
- package/dist/compaction-hook.d.ts.map +1 -0
- package/dist/hive.d.ts +741 -0
- package/dist/hive.d.ts.map +1 -0
- package/dist/index.d.ts +139 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1353 -350
- package/dist/learning.d.ts +9 -9
- package/dist/plugin.js +1176 -350
- package/dist/schemas/cell-events.d.ts +1352 -0
- package/dist/schemas/{bead-events.d.ts.map → cell-events.d.ts.map} +1 -1
- package/dist/schemas/{bead.d.ts → cell.d.ts} +173 -29
- package/dist/schemas/cell.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +11 -7
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/structured.d.ts +17 -7
- package/dist/structured.d.ts.map +1 -1
- package/dist/swarm-decompose.d.ts +5 -5
- package/dist/swarm-orchestrate.d.ts +16 -2
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +9 -9
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm-review.d.ts +210 -0
- package/dist/swarm-review.d.ts.map +1 -0
- package/dist/swarm-worktree.d.ts +185 -0
- package/dist/swarm-worktree.d.ts.map +1 -0
- package/dist/swarm.d.ts +7 -0
- package/dist/swarm.d.ts.map +1 -1
- package/dist/tool-availability.d.ts +3 -2
- package/dist/tool-availability.d.ts.map +1 -1
- package/docs/analysis-socratic-planner-pattern.md +1 -1
- package/docs/planning/ADR-007-swarm-enhancements-worktree-review.md +168 -0
- package/docs/testing/context-recovery-test.md +2 -2
- package/evals/README.md +2 -2
- package/evals/scorers/index.ts +7 -7
- package/examples/commands/swarm.md +21 -23
- package/examples/plugin-wrapper-template.ts +310 -44
- package/examples/skills/{beads-workflow → hive-workflow}/SKILL.md +40 -40
- package/examples/skills/swarm-coordination/SKILL.md +1 -1
- package/global-skills/swarm-coordination/SKILL.md +14 -14
- package/global-skills/swarm-coordination/references/coordinator-patterns.md +3 -3
- package/package.json +2 -2
- package/src/compaction-hook.ts +161 -0
- package/src/{beads.integration.test.ts → hive.integration.test.ts} +92 -80
- package/src/{beads.ts → hive.ts} +378 -219
- package/src/index.ts +57 -20
- package/src/learning.ts +9 -9
- package/src/output-guardrails.test.ts +4 -4
- package/src/output-guardrails.ts +9 -9
- package/src/planning-guardrails.test.ts +1 -1
- package/src/planning-guardrails.ts +1 -1
- package/src/schemas/{bead-events.test.ts → cell-events.test.ts} +83 -77
- package/src/schemas/cell-events.ts +807 -0
- package/src/schemas/{bead.ts → cell.ts} +95 -41
- package/src/schemas/evaluation.ts +1 -1
- package/src/schemas/index.ts +90 -18
- package/src/schemas/swarm-context.ts +2 -2
- package/src/structured.test.ts +15 -15
- package/src/structured.ts +18 -11
- package/src/swarm-decompose.ts +23 -23
- package/src/swarm-orchestrate.ts +135 -21
- package/src/swarm-prompts.ts +43 -43
- package/src/swarm-review.test.ts +702 -0
- package/src/swarm-review.ts +696 -0
- package/src/swarm-worktree.test.ts +501 -0
- package/src/swarm-worktree.ts +575 -0
- package/src/swarm.integration.test.ts +12 -12
- package/src/tool-availability.ts +36 -3
- package/dist/beads.d.ts +0 -386
- package/dist/beads.d.ts.map +0 -1
- package/dist/schemas/bead-events.d.ts +0 -698
- package/dist/schemas/bead.d.ts.map +0 -1
- package/src/schemas/bead-events.ts +0 -583
package/src/swarm-decompose.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Key responsibilities:
|
|
8
8
|
* - Decomposition prompt generation
|
|
9
|
-
* -
|
|
9
|
+
* - CellTree validation
|
|
10
10
|
* - File conflict detection
|
|
11
11
|
* - Instruction conflict detection
|
|
12
12
|
* - Delegation to planner subagents
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { tool } from "@opencode-ai/plugin";
|
|
16
16
|
import { z } from "zod";
|
|
17
|
-
import {
|
|
17
|
+
import { CellTreeSchema } from "./schemas";
|
|
18
18
|
import {
|
|
19
19
|
POSITIVE_MARKERS,
|
|
20
20
|
NEGATIVE_MARKERS,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
* Prompt for decomposing a task into parallelizable subtasks.
|
|
30
30
|
*
|
|
31
31
|
* Used by swarm_decompose to instruct the agent on how to break down work.
|
|
32
|
-
* The agent responds with a
|
|
32
|
+
* The agent responds with a CellTree that gets validated.
|
|
33
33
|
*/
|
|
34
34
|
const DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
|
|
35
35
|
|
|
@@ -44,9 +44,9 @@ const DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable sub
|
|
|
44
44
|
|
|
45
45
|
After decomposition, the coordinator will:
|
|
46
46
|
1. Create an epic bead for the overall task
|
|
47
|
-
2. Create child
|
|
47
|
+
2. Create child cells for each subtask
|
|
48
48
|
3. Track progress through bead status updates
|
|
49
|
-
4. Close
|
|
49
|
+
4. Close cells with summaries when complete
|
|
50
50
|
|
|
51
51
|
Agents MUST update their bead status as they work. No silent progress.
|
|
52
52
|
|
|
@@ -66,7 +66,7 @@ Respond with a JSON object matching this schema:
|
|
|
66
66
|
\`\`\`typescript
|
|
67
67
|
{
|
|
68
68
|
epic: {
|
|
69
|
-
title: string, // Epic title for the
|
|
69
|
+
title: string, // Epic title for the hive tracker
|
|
70
70
|
description?: string // Brief description of the overall goal
|
|
71
71
|
},
|
|
72
72
|
subtasks: [
|
|
@@ -121,9 +121,9 @@ const STRATEGY_DECOMPOSITION_PROMPT = `You are decomposing a task into paralleli
|
|
|
121
121
|
|
|
122
122
|
After decomposition, the coordinator will:
|
|
123
123
|
1. Create an epic bead for the overall task
|
|
124
|
-
2. Create child
|
|
124
|
+
2. Create child cells for each subtask
|
|
125
125
|
3. Track progress through bead status updates
|
|
126
|
-
4. Close
|
|
126
|
+
4. Close cells with summaries when complete
|
|
127
127
|
|
|
128
128
|
Agents MUST update their bead status as they work. No silent progress.
|
|
129
129
|
|
|
@@ -143,7 +143,7 @@ Respond with a JSON object matching this schema:
|
|
|
143
143
|
\`\`\`typescript
|
|
144
144
|
{
|
|
145
145
|
epic: {
|
|
146
|
-
title: string, // Epic title for the
|
|
146
|
+
title: string, // Epic title for the hive tracker
|
|
147
147
|
description?: string // Brief description of the overall goal
|
|
148
148
|
},
|
|
149
149
|
subtasks: [
|
|
@@ -425,7 +425,7 @@ function formatCassHistoryForPrompt(history: CassSearchResult): string {
|
|
|
425
425
|
* Decompose a task into a bead tree
|
|
426
426
|
*
|
|
427
427
|
* This is a PROMPT tool - it returns a prompt for the agent to respond to.
|
|
428
|
-
* The agent's response (JSON) should be validated with
|
|
428
|
+
* The agent's response (JSON) should be validated with CellTreeSchema.
|
|
429
429
|
*
|
|
430
430
|
* Optionally queries CASS for similar past tasks to inform decomposition.
|
|
431
431
|
*/
|
|
@@ -512,7 +512,7 @@ export const swarm_decompose = tool({
|
|
|
512
512
|
return JSON.stringify(
|
|
513
513
|
{
|
|
514
514
|
prompt,
|
|
515
|
-
expected_schema: "
|
|
515
|
+
expected_schema: "CellTree",
|
|
516
516
|
schema_hint: {
|
|
517
517
|
epic: { title: "string", description: "string?" },
|
|
518
518
|
subtasks: [
|
|
@@ -526,7 +526,7 @@ export const swarm_decompose = tool({
|
|
|
526
526
|
],
|
|
527
527
|
},
|
|
528
528
|
validation_note:
|
|
529
|
-
"Parse agent response as JSON and validate with
|
|
529
|
+
"Parse agent response as JSON and validate with CellTreeSchema from schemas/bead.ts",
|
|
530
530
|
cass_history: cassResultInfo,
|
|
531
531
|
// Add semantic-memory query instruction
|
|
532
532
|
memory_query: formatMemoryQueryForDecomposition(args.task, 3),
|
|
@@ -543,16 +543,16 @@ export const swarm_decompose = tool({
|
|
|
543
543
|
* Use this after the agent responds to swarm:decompose to validate the structure.
|
|
544
544
|
*/
|
|
545
545
|
export const swarm_validate_decomposition = tool({
|
|
546
|
-
description: "Validate a decomposition response against
|
|
546
|
+
description: "Validate a decomposition response against CellTreeSchema",
|
|
547
547
|
args: {
|
|
548
548
|
response: tool.schema
|
|
549
549
|
.string()
|
|
550
|
-
.describe("JSON response from agent (
|
|
550
|
+
.describe("JSON response from agent (CellTree format)"),
|
|
551
551
|
},
|
|
552
552
|
async execute(args) {
|
|
553
553
|
try {
|
|
554
554
|
const parsed = JSON.parse(args.response);
|
|
555
|
-
const validated =
|
|
555
|
+
const validated = CellTreeSchema.parse(parsed);
|
|
556
556
|
|
|
557
557
|
// Additional validation: check for file conflicts
|
|
558
558
|
const conflicts = detectFileConflicts(validated.subtasks);
|
|
@@ -608,7 +608,7 @@ export const swarm_validate_decomposition = tool({
|
|
|
608
608
|
return JSON.stringify(
|
|
609
609
|
{
|
|
610
610
|
valid: true,
|
|
611
|
-
|
|
611
|
+
cell_tree: validated,
|
|
612
612
|
stats: {
|
|
613
613
|
subtask_count: validated.subtasks.length,
|
|
614
614
|
total_files: new Set(validated.subtasks.flatMap((s) => s.files))
|
|
@@ -667,10 +667,10 @@ export const swarm_validate_decomposition = tool({
|
|
|
667
667
|
* - CASS queries
|
|
668
668
|
* - Skills discovery
|
|
669
669
|
* - File analysis
|
|
670
|
-
* -
|
|
670
|
+
* - CellTree generation
|
|
671
671
|
*
|
|
672
|
-
* The planner returns ONLY structured
|
|
673
|
-
* validates and uses to create
|
|
672
|
+
* The planner returns ONLY structured CellTree JSON, which the coordinator
|
|
673
|
+
* validates and uses to create cells.
|
|
674
674
|
*
|
|
675
675
|
* @example
|
|
676
676
|
* ```typescript
|
|
@@ -815,7 +815,7 @@ export const swarm_delegate_planning = tool({
|
|
|
815
815
|
const subagentInstructions = `
|
|
816
816
|
## CRITICAL: Output Format
|
|
817
817
|
|
|
818
|
-
You are a planner subagent. Your ONLY output must be valid JSON matching the
|
|
818
|
+
You are a planner subagent. Your ONLY output must be valid JSON matching the CellTree schema.
|
|
819
819
|
|
|
820
820
|
DO NOT include:
|
|
821
821
|
- Explanatory text before or after the JSON
|
|
@@ -849,7 +849,7 @@ OUTPUT ONLY the raw JSON object.
|
|
|
849
849
|
]
|
|
850
850
|
}
|
|
851
851
|
|
|
852
|
-
Now generate the
|
|
852
|
+
Now generate the CellTree for the given task.`;
|
|
853
853
|
|
|
854
854
|
const fullPrompt = `${planningPrompt}\n\n${subagentInstructions}`;
|
|
855
855
|
|
|
@@ -863,12 +863,12 @@ Now generate the BeadTree for the given task.`;
|
|
|
863
863
|
selected: selectedStrategy,
|
|
864
864
|
reasoning: strategyReasoning,
|
|
865
865
|
},
|
|
866
|
-
expected_output: "
|
|
866
|
+
expected_output: "CellTree JSON (raw JSON, no markdown)",
|
|
867
867
|
next_steps: [
|
|
868
868
|
"1. Spawn subagent with Task tool using returned prompt",
|
|
869
869
|
"2. Parse subagent response as JSON",
|
|
870
870
|
"3. Validate with swarm_validate_decomposition",
|
|
871
|
-
"4. Create
|
|
871
|
+
"4. Create cells with hive_create_epic",
|
|
872
872
|
],
|
|
873
873
|
cass_history: cassResultInfo,
|
|
874
874
|
skills: skillsInfo,
|
package/src/swarm-orchestrate.ts
CHANGED
|
@@ -68,6 +68,14 @@ import {
|
|
|
68
68
|
warnMissingTool,
|
|
69
69
|
} from "./tool-availability";
|
|
70
70
|
import { listSkills } from "./skills";
|
|
71
|
+
import {
|
|
72
|
+
canUseWorktreeIsolation,
|
|
73
|
+
getStartCommit,
|
|
74
|
+
} from "./swarm-worktree";
|
|
75
|
+
import {
|
|
76
|
+
isReviewApproved,
|
|
77
|
+
getReviewStatus,
|
|
78
|
+
} from "./swarm-review";
|
|
71
79
|
|
|
72
80
|
// ============================================================================
|
|
73
81
|
// Helper Functions
|
|
@@ -583,6 +591,13 @@ export const swarm_init = tool({
|
|
|
583
591
|
.string()
|
|
584
592
|
.optional()
|
|
585
593
|
.describe("Project path (for Agent Mail init)"),
|
|
594
|
+
isolation: tool.schema
|
|
595
|
+
.enum(["worktree", "reservation"])
|
|
596
|
+
.optional()
|
|
597
|
+
.default("reservation")
|
|
598
|
+
.describe(
|
|
599
|
+
"Isolation mode: 'worktree' for git worktree isolation (requires clean git state), 'reservation' for file reservations (default)",
|
|
600
|
+
),
|
|
586
601
|
},
|
|
587
602
|
async execute(args) {
|
|
588
603
|
// Check all tools
|
|
@@ -647,9 +662,53 @@ export const swarm_init = tool({
|
|
|
647
662
|
"No skills found. Add skills to .opencode/skills/ or .claude/skills/ for specialized guidance.";
|
|
648
663
|
}
|
|
649
664
|
|
|
665
|
+
// Check isolation mode
|
|
666
|
+
const isolationMode = args.isolation ?? "reservation";
|
|
667
|
+
let isolationInfo: {
|
|
668
|
+
mode: "worktree" | "reservation";
|
|
669
|
+
available: boolean;
|
|
670
|
+
start_commit?: string;
|
|
671
|
+
reason?: string;
|
|
672
|
+
} = {
|
|
673
|
+
mode: isolationMode,
|
|
674
|
+
available: true,
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
if (isolationMode === "worktree" && args.project_path) {
|
|
678
|
+
const worktreeCheck = await canUseWorktreeIsolation(args.project_path);
|
|
679
|
+
if (worktreeCheck.canUse) {
|
|
680
|
+
const startCommit = await getStartCommit(args.project_path);
|
|
681
|
+
isolationInfo = {
|
|
682
|
+
mode: "worktree",
|
|
683
|
+
available: true,
|
|
684
|
+
start_commit: startCommit ?? undefined,
|
|
685
|
+
};
|
|
686
|
+
} else {
|
|
687
|
+
// Fall back to reservation mode
|
|
688
|
+
isolationInfo = {
|
|
689
|
+
mode: "reservation",
|
|
690
|
+
available: false,
|
|
691
|
+
reason: `Worktree mode unavailable: ${worktreeCheck.reason}. Falling back to reservation mode.`,
|
|
692
|
+
};
|
|
693
|
+
warnings.push(
|
|
694
|
+
`⚠️ Worktree isolation unavailable: ${worktreeCheck.reason}. Using file reservations instead.`,
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
} else if (isolationMode === "worktree" && !args.project_path) {
|
|
698
|
+
isolationInfo = {
|
|
699
|
+
mode: "reservation",
|
|
700
|
+
available: false,
|
|
701
|
+
reason: "Worktree mode requires project_path. Falling back to reservation mode.",
|
|
702
|
+
};
|
|
703
|
+
warnings.push(
|
|
704
|
+
"⚠️ Worktree isolation requires project_path. Using file reservations instead.",
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
|
|
650
708
|
return JSON.stringify(
|
|
651
709
|
{
|
|
652
710
|
ready: true,
|
|
711
|
+
isolation: isolationInfo,
|
|
653
712
|
tool_availability: Object.fromEntries(
|
|
654
713
|
Array.from(availability.entries()).map(([k, v]) => [
|
|
655
714
|
k,
|
|
@@ -671,6 +730,10 @@ export const swarm_init = tool({
|
|
|
671
730
|
agent_mail: agentMailAvailable
|
|
672
731
|
? "✓ Use Agent Mail for coordination"
|
|
673
732
|
: "Start Agent Mail: agent-mail serve",
|
|
733
|
+
isolation:
|
|
734
|
+
isolationInfo.mode === "worktree"
|
|
735
|
+
? "✓ Using git worktree isolation"
|
|
736
|
+
: "✓ Using file reservation isolation",
|
|
674
737
|
},
|
|
675
738
|
report,
|
|
676
739
|
},
|
|
@@ -708,7 +771,7 @@ export const swarm_status = tool({
|
|
|
708
771
|
const agents: SpawnedAgent[] = [];
|
|
709
772
|
|
|
710
773
|
for (const bead of subtasks) {
|
|
711
|
-
// Map
|
|
774
|
+
// Map cell status to agent status
|
|
712
775
|
let agentStatus: SpawnedAgent["status"] = "pending";
|
|
713
776
|
switch (bead.status) {
|
|
714
777
|
case "in_progress":
|
|
@@ -815,7 +878,7 @@ export const swarm_progress = tool({
|
|
|
815
878
|
// Validate
|
|
816
879
|
const validated = AgentProgressSchema.parse(progress);
|
|
817
880
|
|
|
818
|
-
// Update
|
|
881
|
+
// Update cell status if needed
|
|
819
882
|
if (args.status === "blocked" || args.status === "in_progress") {
|
|
820
883
|
const beadStatus = args.status === "blocked" ? "blocked" : "in_progress";
|
|
821
884
|
await Bun.$`bd update ${args.bead_id} --status ${beadStatus} --json`
|
|
@@ -984,9 +1047,9 @@ export const swarm_broadcast = tool({
|
|
|
984
1047
|
* 2. RUN: Execute verification (UBS, typecheck, tests)
|
|
985
1048
|
* 3. READ: Check exit codes and output
|
|
986
1049
|
* 4. VERIFY: All checks must pass
|
|
987
|
-
* 5. ONLY THEN: Close the
|
|
1050
|
+
* 5. ONLY THEN: Close the cell
|
|
988
1051
|
*
|
|
989
|
-
* Closes
|
|
1052
|
+
* Closes cell, releases reservations, notifies coordinator.
|
|
990
1053
|
*/
|
|
991
1054
|
export const swarm_complete = tool({
|
|
992
1055
|
description:
|
|
@@ -1030,13 +1093,64 @@ export const swarm_complete = tool({
|
|
|
1030
1093
|
.number()
|
|
1031
1094
|
.optional()
|
|
1032
1095
|
.describe("Number of retry attempts during task"),
|
|
1096
|
+
skip_review: tool.schema
|
|
1097
|
+
.boolean()
|
|
1098
|
+
.optional()
|
|
1099
|
+
.describe(
|
|
1100
|
+
"Skip review gate check (default: false). Use only for tasks that don't require coordinator review.",
|
|
1101
|
+
),
|
|
1033
1102
|
},
|
|
1034
1103
|
async execute(args, _ctx) {
|
|
1035
|
-
// Extract epic ID early for error notifications
|
|
1104
|
+
// Extract epic ID early for error notifications and review gate
|
|
1036
1105
|
const epicId = args.bead_id.includes(".")
|
|
1037
1106
|
? args.bead_id.split(".")[0]
|
|
1038
1107
|
: args.bead_id;
|
|
1039
1108
|
|
|
1109
|
+
// Check review gate (unless skipped) - BEFORE try block so errors are clear
|
|
1110
|
+
if (!args.skip_review) {
|
|
1111
|
+
const reviewStatusResult = getReviewStatus(args.bead_id);
|
|
1112
|
+
|
|
1113
|
+
if (!reviewStatusResult.approved) {
|
|
1114
|
+
// Check if review was even attempted
|
|
1115
|
+
if (!reviewStatusResult.reviewed) {
|
|
1116
|
+
return JSON.stringify(
|
|
1117
|
+
{
|
|
1118
|
+
success: false,
|
|
1119
|
+
error: "Review required before completion",
|
|
1120
|
+
review_status: reviewStatusResult,
|
|
1121
|
+
hint: `This task requires coordinator review before completion.
|
|
1122
|
+
|
|
1123
|
+
**Next steps:**
|
|
1124
|
+
1. Request review with swarm_review(project_key="${args.project_key}", epic_id="${epicId}", task_id="${args.bead_id}", files_touched=[...])
|
|
1125
|
+
2. Wait for coordinator to review and approve with swarm_review_feedback
|
|
1126
|
+
3. Once approved, call swarm_complete again
|
|
1127
|
+
|
|
1128
|
+
Or use skip_review=true to bypass (not recommended for production work).`,
|
|
1129
|
+
},
|
|
1130
|
+
null,
|
|
1131
|
+
2,
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// Review was attempted but not approved
|
|
1136
|
+
return JSON.stringify(
|
|
1137
|
+
{
|
|
1138
|
+
success: false,
|
|
1139
|
+
error: "Review not approved",
|
|
1140
|
+
review_status: reviewStatusResult,
|
|
1141
|
+
hint: `Task was reviewed but not approved. ${reviewStatusResult.remaining_attempts} attempt(s) remaining.
|
|
1142
|
+
|
|
1143
|
+
**Next steps:**
|
|
1144
|
+
1. Address the feedback from the reviewer
|
|
1145
|
+
2. Request another review with swarm_review
|
|
1146
|
+
3. Once approved, call swarm_complete again`,
|
|
1147
|
+
},
|
|
1148
|
+
null,
|
|
1149
|
+
2,
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1040
1154
|
try {
|
|
1041
1155
|
// Verify agent is registered in swarm-mail
|
|
1042
1156
|
// This catches agents who skipped swarmmail_init
|
|
@@ -1189,8 +1303,8 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
1189
1303
|
}
|
|
1190
1304
|
}
|
|
1191
1305
|
|
|
1192
|
-
// Close the
|
|
1193
|
-
// This fixes the issue where
|
|
1306
|
+
// Close the cell - use project_key as working directory to find correct .beads/
|
|
1307
|
+
// This fixes the issue where cell ID prefix (e.g., "pdf-library-g84.2") doesn't match CWD
|
|
1194
1308
|
const closeResult =
|
|
1195
1309
|
await Bun.$`bd close ${args.bead_id} --reason ${args.summary} --json`
|
|
1196
1310
|
.cwd(args.project_key)
|
|
@@ -1208,7 +1322,7 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
1208
1322
|
return JSON.stringify(
|
|
1209
1323
|
{
|
|
1210
1324
|
success: false,
|
|
1211
|
-
error: "Failed to close
|
|
1325
|
+
error: "Failed to close cell",
|
|
1212
1326
|
failed_step: "bd close",
|
|
1213
1327
|
details: stderrOutput || stdoutOutput || "Unknown error from bd close command",
|
|
1214
1328
|
bead_id: args.bead_id,
|
|
@@ -1218,20 +1332,20 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
1218
1332
|
? [
|
|
1219
1333
|
`1. Verify project_key is correct: "${args.project_key}"`,
|
|
1220
1334
|
`2. Check .beads/ exists in that directory`,
|
|
1221
|
-
`3.
|
|
1222
|
-
`4. Try:
|
|
1335
|
+
`3. Cell ID prefix "${args.bead_id.split("-")[0]}" should match project`,
|
|
1336
|
+
`4. Try: hive_close(id="${args.bead_id}", reason="...")`,
|
|
1223
1337
|
]
|
|
1224
1338
|
: [
|
|
1225
|
-
`1. Check
|
|
1226
|
-
`2. Check
|
|
1227
|
-
`3. If
|
|
1228
|
-
`4. Try closing directly:
|
|
1339
|
+
`1. Check cell exists: bd show ${args.bead_id}`,
|
|
1340
|
+
`2. Check cell status (might already be closed): hive_query()`,
|
|
1341
|
+
`3. If cell is blocked, unblock first: hive_update(id="${args.bead_id}", status="in_progress")`,
|
|
1342
|
+
`4. Try closing directly: hive_close(id="${args.bead_id}", reason="...")`,
|
|
1229
1343
|
],
|
|
1230
1344
|
hint: isNoDatabaseError
|
|
1231
1345
|
? `The project_key "${args.project_key}" doesn't have a .beads/ directory. Make sure you're using the correct project path.`
|
|
1232
1346
|
: isNotFoundError
|
|
1233
|
-
? `
|
|
1234
|
-
: "If
|
|
1347
|
+
? `Cell "${args.bead_id}" not found. It may have been closed already or the ID is incorrect.`
|
|
1348
|
+
: "If cell is in 'blocked' status, you must change it to 'in_progress' or 'open' before closing.",
|
|
1235
1349
|
},
|
|
1236
1350
|
},
|
|
1237
1351
|
null,
|
|
@@ -1497,7 +1611,7 @@ Files touched: ${args.files_touched?.join(", ") || "none recorded"}`,
|
|
|
1497
1611
|
"",
|
|
1498
1612
|
`### Recovery Actions`,
|
|
1499
1613
|
"1. Check error message for specific issue",
|
|
1500
|
-
"2. Review failed step (UBS scan, typecheck,
|
|
1614
|
+
"2. Review failed step (UBS scan, typecheck, cell close, etc.)",
|
|
1501
1615
|
"3. Fix underlying issue or use skip flags if appropriate",
|
|
1502
1616
|
"4. Retry swarm_complete after fixing",
|
|
1503
1617
|
]
|
|
@@ -1553,7 +1667,7 @@ Files touched: ${args.files_touched?.join(", ") || "none recorded"}`,
|
|
|
1553
1667
|
common_fixes: {
|
|
1554
1668
|
"Verification Gate": "Use skip_verification=true to bypass (not recommended)",
|
|
1555
1669
|
"UBS scan": "Use skip_ubs_scan=true to bypass",
|
|
1556
|
-
"
|
|
1670
|
+
"Cell close": "Check cell status with hive_query(), may need hive_update() first",
|
|
1557
1671
|
"Self-evaluation": "Check evaluation JSON format matches EvaluationSchema",
|
|
1558
1672
|
},
|
|
1559
1673
|
},
|
|
@@ -1738,7 +1852,7 @@ export const swarm_accumulate_error = tool({
|
|
|
1738
1852
|
description:
|
|
1739
1853
|
"Record an error during subtask execution. Errors feed into retry prompts.",
|
|
1740
1854
|
args: {
|
|
1741
|
-
bead_id: tool.schema.string().describe("
|
|
1855
|
+
bead_id: tool.schema.string().describe("Cell ID where error occurred"),
|
|
1742
1856
|
error_type: tool.schema
|
|
1743
1857
|
.enum(["validation", "timeout", "conflict", "tool_failure", "unknown"])
|
|
1744
1858
|
.describe("Category of error"),
|
|
@@ -1791,7 +1905,7 @@ export const swarm_get_error_context = tool({
|
|
|
1791
1905
|
description:
|
|
1792
1906
|
"Get accumulated errors for a bead. Returns formatted context for retry prompts.",
|
|
1793
1907
|
args: {
|
|
1794
|
-
bead_id: tool.schema.string().describe("
|
|
1908
|
+
bead_id: tool.schema.string().describe("Cell ID to get errors for"),
|
|
1795
1909
|
include_resolved: tool.schema
|
|
1796
1910
|
.boolean()
|
|
1797
1911
|
.optional()
|
|
@@ -1873,7 +1987,7 @@ export const swarm_check_strikes = tool({
|
|
|
1873
1987
|
description:
|
|
1874
1988
|
"Check 3-strike status for a bead. Records failures, detects architectural problems, generates architecture review prompts.",
|
|
1875
1989
|
args: {
|
|
1876
|
-
bead_id: tool.schema.string().describe("
|
|
1990
|
+
bead_id: tool.schema.string().describe("Cell ID to check"),
|
|
1877
1991
|
action: tool.schema
|
|
1878
1992
|
.enum(["check", "add_strike", "clear", "get_prompt"])
|
|
1879
1993
|
.describe(
|
package/src/swarm-prompts.ts
CHANGED
|
@@ -22,7 +22,7 @@ import { tool } from "@opencode-ai/plugin";
|
|
|
22
22
|
* Prompt for decomposing a task into parallelizable subtasks.
|
|
23
23
|
*
|
|
24
24
|
* Used by swarm_decompose to instruct the agent on how to break down work.
|
|
25
|
-
* The agent responds with a
|
|
25
|
+
* The agent responds with a CellTree that gets validated.
|
|
26
26
|
*/
|
|
27
27
|
export const DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
|
|
28
28
|
|
|
@@ -31,17 +31,17 @@ export const DECOMPOSITION_PROMPT = `You are decomposing a task into paralleliza
|
|
|
31
31
|
|
|
32
32
|
{context_section}
|
|
33
33
|
|
|
34
|
-
## MANDATORY:
|
|
34
|
+
## MANDATORY: Hive Issue Tracking
|
|
35
35
|
|
|
36
|
-
**Every subtask MUST become a
|
|
36
|
+
**Every subtask MUST become a cell.** This is non-negotiable.
|
|
37
37
|
|
|
38
38
|
After decomposition, the coordinator will:
|
|
39
|
-
1. Create an epic
|
|
40
|
-
2. Create child
|
|
41
|
-
3. Track progress through
|
|
42
|
-
4. Close
|
|
39
|
+
1. Create an epic cell for the overall task
|
|
40
|
+
2. Create child cells for each subtask
|
|
41
|
+
3. Track progress through cell status updates
|
|
42
|
+
4. Close cells with summaries when complete
|
|
43
43
|
|
|
44
|
-
Agents MUST update their
|
|
44
|
+
Agents MUST update their cell status as they work. No silent progress.
|
|
45
45
|
|
|
46
46
|
## Requirements
|
|
47
47
|
|
|
@@ -59,7 +59,7 @@ Respond with a JSON object matching this schema:
|
|
|
59
59
|
\`\`\`typescript
|
|
60
60
|
{
|
|
61
61
|
epic: {
|
|
62
|
-
title: string, // Epic title for the
|
|
62
|
+
title: string, // Epic title for the hive tracker
|
|
63
63
|
description?: string // Brief description of the overall goal
|
|
64
64
|
},
|
|
65
65
|
subtasks: [
|
|
@@ -108,17 +108,17 @@ export const STRATEGY_DECOMPOSITION_PROMPT = `You are decomposing a task into pa
|
|
|
108
108
|
|
|
109
109
|
{skills_context}
|
|
110
110
|
|
|
111
|
-
## MANDATORY:
|
|
111
|
+
## MANDATORY: Hive Issue Tracking
|
|
112
112
|
|
|
113
|
-
**Every subtask MUST become a
|
|
113
|
+
**Every subtask MUST become a cell.** This is non-negotiable.
|
|
114
114
|
|
|
115
115
|
After decomposition, the coordinator will:
|
|
116
|
-
1. Create an epic
|
|
117
|
-
2. Create child
|
|
118
|
-
3. Track progress through
|
|
119
|
-
4. Close
|
|
116
|
+
1. Create an epic cell for the overall task
|
|
117
|
+
2. Create child cells for each subtask
|
|
118
|
+
3. Track progress through cell status updates
|
|
119
|
+
4. Close cells with summaries when complete
|
|
120
120
|
|
|
121
|
-
Agents MUST update their
|
|
121
|
+
Agents MUST update their cell status as they work. No silent progress.
|
|
122
122
|
|
|
123
123
|
## Requirements
|
|
124
124
|
|
|
@@ -136,7 +136,7 @@ Respond with a JSON object matching this schema:
|
|
|
136
136
|
\`\`\`typescript
|
|
137
137
|
{
|
|
138
138
|
epic: {
|
|
139
|
-
title: string, // Epic title for the
|
|
139
|
+
title: string, // Epic title for the hive tracker
|
|
140
140
|
description?: string // Brief description of the overall goal
|
|
141
141
|
},
|
|
142
142
|
subtasks: [
|
|
@@ -164,7 +164,7 @@ export const SUBTASK_PROMPT = `You are a swarm agent working on a subtask of a l
|
|
|
164
164
|
|
|
165
165
|
## Your Identity
|
|
166
166
|
- **Agent Name**: {agent_name}
|
|
167
|
-
- **
|
|
167
|
+
- **Cell ID**: {bead_id}
|
|
168
168
|
- **Epic ID**: {epic_id}
|
|
169
169
|
|
|
170
170
|
## Your Subtask
|
|
@@ -182,16 +182,16 @@ send a message to the coordinator requesting the change.
|
|
|
182
182
|
## Shared Context
|
|
183
183
|
{shared_context}
|
|
184
184
|
|
|
185
|
-
## MANDATORY:
|
|
185
|
+
## MANDATORY: Hive Tracking
|
|
186
186
|
|
|
187
|
-
You MUST keep your
|
|
187
|
+
You MUST keep your cell updated as you work:
|
|
188
188
|
|
|
189
|
-
1. **Your
|
|
190
|
-
2. **If blocked**: \`
|
|
191
|
-
3. **When done**: Use \`swarm_complete\` - it closes your
|
|
192
|
-
4. **Discovered issues**: Create new
|
|
189
|
+
1. **Your cell is already in_progress** - don't change this unless blocked
|
|
190
|
+
2. **If blocked**: \`hive_update {bead_id} --status blocked\` and message coordinator
|
|
191
|
+
3. **When done**: Use \`swarm_complete\` - it closes your cell automatically
|
|
192
|
+
4. **Discovered issues**: Create new cells with \`hive_create "issue" -t bug\`
|
|
193
193
|
|
|
194
|
-
**Never work silently.** Your
|
|
194
|
+
**Never work silently.** Your cell status is how the swarm tracks progress.
|
|
195
195
|
|
|
196
196
|
## MANDATORY: Swarm Mail Communication
|
|
197
197
|
|
|
@@ -214,11 +214,11 @@ swarmmail_send(
|
|
|
214
214
|
|
|
215
215
|
## Coordination Protocol
|
|
216
216
|
|
|
217
|
-
1. **Start**: Your
|
|
217
|
+
1. **Start**: Your cell is already marked in_progress
|
|
218
218
|
2. **Progress**: Use swarm_progress to report status updates
|
|
219
219
|
3. **Blocked**: Report immediately via Swarm Mail - don't spin
|
|
220
220
|
4. **Complete**: Use swarm_complete when done - it handles:
|
|
221
|
-
- Closing your
|
|
221
|
+
- Closing your cell with a summary
|
|
222
222
|
- Releasing file reservations
|
|
223
223
|
- Notifying the coordinator
|
|
224
224
|
|
|
@@ -243,10 +243,10 @@ Before writing code:
|
|
|
243
243
|
Begin work on your subtask now.`;
|
|
244
244
|
|
|
245
245
|
/**
|
|
246
|
-
* Streamlined subtask prompt (V2) - uses Swarm Mail and
|
|
246
|
+
* Streamlined subtask prompt (V2) - uses Swarm Mail and hive tracking
|
|
247
247
|
*
|
|
248
248
|
* This is a cleaner version of SUBTASK_PROMPT that's easier to parse.
|
|
249
|
-
* Agents MUST use Swarm Mail for communication and
|
|
249
|
+
* Agents MUST use Swarm Mail for communication and hive cells for tracking.
|
|
250
250
|
*
|
|
251
251
|
* Supports {error_context} placeholder for retry prompts.
|
|
252
252
|
*/
|
|
@@ -254,7 +254,7 @@ export const SUBTASK_PROMPT_V2 = `You are a swarm agent working on: **{subtask_t
|
|
|
254
254
|
|
|
255
255
|
## [IDENTITY]
|
|
256
256
|
Agent: (assigned at spawn)
|
|
257
|
-
|
|
257
|
+
Cell: {bead_id}
|
|
258
258
|
Epic: {epic_id}
|
|
259
259
|
|
|
260
260
|
## [TASK]
|
|
@@ -398,7 +398,7 @@ swarm_complete(
|
|
|
398
398
|
- Records learning signals
|
|
399
399
|
- Notifies coordinator
|
|
400
400
|
|
|
401
|
-
**DO NOT manually close the
|
|
401
|
+
**DO NOT manually close the cell with hive_close.** Use swarm_complete.
|
|
402
402
|
|
|
403
403
|
## [SWARM MAIL COMMUNICATION]
|
|
404
404
|
|
|
@@ -417,7 +417,7 @@ swarmmail_send(
|
|
|
417
417
|
importance="high",
|
|
418
418
|
thread_id="{epic_id}"
|
|
419
419
|
)
|
|
420
|
-
|
|
420
|
+
hive_update(id="{bead_id}", status="blocked")
|
|
421
421
|
\`\`\`
|
|
422
422
|
|
|
423
423
|
### Report Issues to Other Agents
|
|
@@ -438,15 +438,15 @@ swarmmail_release() # Manually release reservations
|
|
|
438
438
|
**Note:** \`swarm_complete\` automatically releases reservations. Only use manual release if aborting work.
|
|
439
439
|
|
|
440
440
|
## [OTHER TOOLS]
|
|
441
|
-
###
|
|
442
|
-
You can create new
|
|
441
|
+
### Hive - You Have Autonomy to File Issues
|
|
442
|
+
You can create new cells against this epic when you discover:
|
|
443
443
|
- **Bugs**: Found a bug while working? File it.
|
|
444
444
|
- **Tech debt**: Spotted something that needs cleanup? File it.
|
|
445
445
|
- **Follow-up work**: Task needs more work than scoped? File a follow-up.
|
|
446
446
|
- **Dependencies**: Need something from another agent? File and link it.
|
|
447
447
|
|
|
448
448
|
\`\`\`
|
|
449
|
-
|
|
449
|
+
hive_create(
|
|
450
450
|
title="<descriptive title>",
|
|
451
451
|
type="bug", # or "task", "chore"
|
|
452
452
|
priority=2,
|
|
@@ -457,9 +457,9 @@ beads_create(
|
|
|
457
457
|
|
|
458
458
|
**Don't silently ignore issues.** File them so they get tracked and addressed.
|
|
459
459
|
|
|
460
|
-
Other
|
|
461
|
-
-
|
|
462
|
-
-
|
|
460
|
+
Other cell operations:
|
|
461
|
+
- hive_update(id, status) - Mark blocked if stuck
|
|
462
|
+
- hive_query(status="open") - See what else needs work
|
|
463
463
|
|
|
464
464
|
### Skills
|
|
465
465
|
- skills_list() - Discover available skills
|
|
@@ -473,7 +473,7 @@ Other bead operations:
|
|
|
473
473
|
2. Step 2 (semantic-memory_find) MUST happen before starting work
|
|
474
474
|
3. Step 4 (swarmmail_reserve) - YOU reserve files, not coordinator
|
|
475
475
|
4. Step 6 (swarm_progress) - Report at milestones, don't work silently
|
|
476
|
-
5. Step 9 (swarm_complete) - Use this to close, NOT
|
|
476
|
+
5. Step 9 (swarm_complete) - Use this to close, NOT hive_close
|
|
477
477
|
|
|
478
478
|
**If you skip these steps:**
|
|
479
479
|
- Your work won't be tracked (swarm_complete will fail)
|
|
@@ -492,7 +492,7 @@ Begin now.`;
|
|
|
492
492
|
export const EVALUATION_PROMPT = `Evaluate the work completed for this subtask.
|
|
493
493
|
|
|
494
494
|
## Subtask
|
|
495
|
-
**
|
|
495
|
+
**Cell ID**: {bead_id}
|
|
496
496
|
**Title**: {subtask_title}
|
|
497
497
|
|
|
498
498
|
## Files Modified
|
|
@@ -691,12 +691,12 @@ export const swarm_subtask_prompt = tool({
|
|
|
691
691
|
/**
|
|
692
692
|
* Prepare a subtask for spawning with Task tool (V2 prompt)
|
|
693
693
|
*
|
|
694
|
-
* Generates a streamlined prompt that tells agents to USE Agent Mail and
|
|
694
|
+
* Generates a streamlined prompt that tells agents to USE Agent Mail and hive tracking.
|
|
695
695
|
* Returns JSON that can be directly used with Task tool.
|
|
696
696
|
*/
|
|
697
697
|
export const swarm_spawn_subtask = tool({
|
|
698
698
|
description:
|
|
699
|
-
"Prepare a subtask for spawning. Returns prompt with Agent Mail/
|
|
699
|
+
"Prepare a subtask for spawning. Returns prompt with Agent Mail/hive tracking instructions. IMPORTANT: Pass project_path for swarmmail_init.",
|
|
700
700
|
args: {
|
|
701
701
|
bead_id: tool.schema.string().describe("Subtask bead ID"),
|
|
702
702
|
epic_id: tool.schema.string().describe("Parent epic bead ID"),
|
|
@@ -916,7 +916,7 @@ export const swarm_plan_prompt = tool({
|
|
|
916
916
|
STRATEGIES[selectedStrategy as keyof typeof STRATEGIES]
|
|
917
917
|
.antiPatterns,
|
|
918
918
|
},
|
|
919
|
-
expected_schema: "
|
|
919
|
+
expected_schema: "CellTree",
|
|
920
920
|
schema_hint: {
|
|
921
921
|
epic: { title: "string", description: "string?" },
|
|
922
922
|
subtasks: [
|