opencode-swarm-plugin 0.26.1 → 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.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +23 -0
- package/README.md +43 -46
- package/bin/swarm.ts +8 -8
- 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/dist/index.js
CHANGED
|
@@ -27051,10 +27051,10 @@ echo "Project directory: $1"
|
|
|
27051
27051
|
};
|
|
27052
27052
|
});
|
|
27053
27053
|
|
|
27054
|
-
// src/
|
|
27054
|
+
// src/hive.ts
|
|
27055
27055
|
init_dist();
|
|
27056
27056
|
import {
|
|
27057
|
-
|
|
27057
|
+
createHiveAdapter,
|
|
27058
27058
|
FlushManager,
|
|
27059
27059
|
importFromJSONL,
|
|
27060
27060
|
getSwarmMail
|
|
@@ -27062,32 +27062,32 @@ import {
|
|
|
27062
27062
|
import { existsSync, readFileSync } from "node:fs";
|
|
27063
27063
|
import { join } from "node:path";
|
|
27064
27064
|
|
|
27065
|
-
// src/schemas/
|
|
27065
|
+
// src/schemas/cell.ts
|
|
27066
27066
|
init_zod();
|
|
27067
|
-
var
|
|
27067
|
+
var CellStatusSchema = exports_external.enum([
|
|
27068
27068
|
"open",
|
|
27069
27069
|
"in_progress",
|
|
27070
27070
|
"blocked",
|
|
27071
27071
|
"closed"
|
|
27072
27072
|
]);
|
|
27073
|
-
var
|
|
27073
|
+
var CellTypeSchema = exports_external.enum([
|
|
27074
27074
|
"bug",
|
|
27075
27075
|
"feature",
|
|
27076
27076
|
"task",
|
|
27077
27077
|
"epic",
|
|
27078
27078
|
"chore"
|
|
27079
27079
|
]);
|
|
27080
|
-
var
|
|
27080
|
+
var CellDependencySchema = exports_external.object({
|
|
27081
27081
|
id: exports_external.string(),
|
|
27082
27082
|
type: exports_external.enum(["blocks", "blocked-by", "related", "discovered-from"])
|
|
27083
27083
|
});
|
|
27084
|
-
var
|
|
27085
|
-
id: exports_external.string().regex(/^[a-z0-9]+(-[a-z0-9]+)+(\.[\w-]+)?$/, "Invalid
|
|
27084
|
+
var CellSchema = exports_external.object({
|
|
27085
|
+
id: exports_external.string().regex(/^[a-z0-9]+(-[a-z0-9]+)+(\.[\w-]+)?$/, "Invalid cell ID format (expected: project-slug-hash or project-slug-hash.N)"),
|
|
27086
27086
|
title: exports_external.string().min(1, "Title required"),
|
|
27087
27087
|
description: exports_external.string().optional().default(""),
|
|
27088
|
-
status:
|
|
27088
|
+
status: CellStatusSchema.default("open"),
|
|
27089
27089
|
priority: exports_external.number().int().min(0).max(3).default(2),
|
|
27090
|
-
issue_type:
|
|
27090
|
+
issue_type: CellTypeSchema.default("task"),
|
|
27091
27091
|
created_at: exports_external.string().datetime({
|
|
27092
27092
|
offset: true,
|
|
27093
27093
|
message: "Must be ISO-8601 datetime with timezone (e.g., 2024-01-15T10:30:00Z)"
|
|
@@ -27098,30 +27098,30 @@ var BeadSchema = exports_external.object({
|
|
|
27098
27098
|
}).optional(),
|
|
27099
27099
|
closed_at: exports_external.string().datetime({ offset: true }).optional(),
|
|
27100
27100
|
parent_id: exports_external.string().optional(),
|
|
27101
|
-
dependencies: exports_external.array(
|
|
27101
|
+
dependencies: exports_external.array(CellDependencySchema).default([]),
|
|
27102
27102
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
27103
27103
|
});
|
|
27104
|
-
var
|
|
27104
|
+
var CellCreateArgsSchema = exports_external.object({
|
|
27105
27105
|
title: exports_external.string().min(1, "Title required"),
|
|
27106
|
-
type:
|
|
27106
|
+
type: CellTypeSchema.default("task"),
|
|
27107
27107
|
priority: exports_external.number().int().min(0).max(3).default(2),
|
|
27108
27108
|
description: exports_external.string().optional(),
|
|
27109
27109
|
parent_id: exports_external.string().optional(),
|
|
27110
27110
|
id: exports_external.string().optional()
|
|
27111
27111
|
});
|
|
27112
|
-
var
|
|
27112
|
+
var CellUpdateArgsSchema = exports_external.object({
|
|
27113
27113
|
id: exports_external.string(),
|
|
27114
|
-
status:
|
|
27114
|
+
status: CellStatusSchema.optional(),
|
|
27115
27115
|
description: exports_external.string().optional(),
|
|
27116
27116
|
priority: exports_external.number().int().min(0).max(3).optional()
|
|
27117
27117
|
});
|
|
27118
|
-
var
|
|
27118
|
+
var CellCloseArgsSchema = exports_external.object({
|
|
27119
27119
|
id: exports_external.string(),
|
|
27120
27120
|
reason: exports_external.string().min(1, "Reason required")
|
|
27121
27121
|
});
|
|
27122
|
-
var
|
|
27123
|
-
status:
|
|
27124
|
-
type:
|
|
27122
|
+
var CellQueryArgsSchema = exports_external.object({
|
|
27123
|
+
status: CellStatusSchema.optional(),
|
|
27124
|
+
type: CellTypeSchema.optional(),
|
|
27125
27125
|
ready: exports_external.boolean().optional(),
|
|
27126
27126
|
limit: exports_external.number().int().positive().default(20)
|
|
27127
27127
|
});
|
|
@@ -27132,7 +27132,7 @@ var SubtaskSpecSchema = exports_external.object({
|
|
|
27132
27132
|
dependencies: exports_external.array(exports_external.number().int().min(0)).default([]),
|
|
27133
27133
|
estimated_complexity: exports_external.number().int().min(1).max(5).default(3)
|
|
27134
27134
|
});
|
|
27135
|
-
var
|
|
27135
|
+
var CellTreeSchema = exports_external.object({
|
|
27136
27136
|
epic: exports_external.object({
|
|
27137
27137
|
title: exports_external.string().min(1),
|
|
27138
27138
|
description: exports_external.string().optional().default("")
|
|
@@ -27152,10 +27152,19 @@ var EpicCreateArgsSchema = exports_external.object({
|
|
|
27152
27152
|
});
|
|
27153
27153
|
var EpicCreateResultSchema = exports_external.object({
|
|
27154
27154
|
success: exports_external.boolean(),
|
|
27155
|
-
epic:
|
|
27156
|
-
subtasks: exports_external.array(
|
|
27155
|
+
epic: CellSchema,
|
|
27156
|
+
subtasks: exports_external.array(CellSchema),
|
|
27157
27157
|
rollback_hint: exports_external.string().optional()
|
|
27158
27158
|
});
|
|
27159
|
+
var BeadStatusSchema = CellStatusSchema;
|
|
27160
|
+
var BeadTypeSchema = CellTypeSchema;
|
|
27161
|
+
var BeadDependencySchema = CellDependencySchema;
|
|
27162
|
+
var BeadSchema = CellSchema;
|
|
27163
|
+
var BeadCreateArgsSchema = CellCreateArgsSchema;
|
|
27164
|
+
var BeadUpdateArgsSchema = CellUpdateArgsSchema;
|
|
27165
|
+
var BeadCloseArgsSchema = CellCloseArgsSchema;
|
|
27166
|
+
var BeadQueryArgsSchema = CellQueryArgsSchema;
|
|
27167
|
+
var BeadTreeSchema = CellTreeSchema;
|
|
27159
27168
|
// src/schemas/evaluation.ts
|
|
27160
27169
|
init_zod();
|
|
27161
27170
|
var CriterionEvaluationSchema = exports_external.object({
|
|
@@ -27437,29 +27446,29 @@ var QuerySwarmContextsArgsSchema = exports_external.object({
|
|
|
27437
27446
|
strategy: SwarmStrategySchema.optional(),
|
|
27438
27447
|
has_errors: exports_external.boolean().optional()
|
|
27439
27448
|
});
|
|
27440
|
-
// src/schemas/
|
|
27449
|
+
// src/schemas/cell-events.ts
|
|
27441
27450
|
init_zod();
|
|
27442
|
-
var
|
|
27451
|
+
var BaseCellEventSchema = exports_external.object({
|
|
27443
27452
|
id: exports_external.number().optional(),
|
|
27444
27453
|
type: exports_external.string(),
|
|
27445
27454
|
project_key: exports_external.string(),
|
|
27446
27455
|
timestamp: exports_external.number(),
|
|
27447
27456
|
sequence: exports_external.number().optional()
|
|
27448
27457
|
});
|
|
27449
|
-
var
|
|
27450
|
-
type: exports_external.literal("
|
|
27451
|
-
|
|
27458
|
+
var CellCreatedEventSchema = BaseCellEventSchema.extend({
|
|
27459
|
+
type: exports_external.literal("cell_created"),
|
|
27460
|
+
cell_id: exports_external.string(),
|
|
27452
27461
|
title: exports_external.string(),
|
|
27453
27462
|
description: exports_external.string().optional(),
|
|
27454
|
-
issue_type:
|
|
27463
|
+
issue_type: CellTypeSchema,
|
|
27455
27464
|
priority: exports_external.number().int().min(0).max(3),
|
|
27456
27465
|
parent_id: exports_external.string().optional(),
|
|
27457
27466
|
created_by: exports_external.string().optional(),
|
|
27458
27467
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
27459
27468
|
});
|
|
27460
|
-
var
|
|
27461
|
-
type: exports_external.literal("
|
|
27462
|
-
|
|
27469
|
+
var CellUpdatedEventSchema = BaseCellEventSchema.extend({
|
|
27470
|
+
type: exports_external.literal("cell_updated"),
|
|
27471
|
+
cell_id: exports_external.string(),
|
|
27463
27472
|
updated_by: exports_external.string().optional(),
|
|
27464
27473
|
changes: exports_external.object({
|
|
27465
27474
|
title: exports_external.object({
|
|
@@ -27476,167 +27485,167 @@ var BeadUpdatedEventSchema = BaseBeadEventSchema.extend({
|
|
|
27476
27485
|
}).optional()
|
|
27477
27486
|
})
|
|
27478
27487
|
});
|
|
27479
|
-
var
|
|
27480
|
-
type: exports_external.literal("
|
|
27481
|
-
|
|
27482
|
-
from_status:
|
|
27483
|
-
to_status:
|
|
27488
|
+
var CellStatusChangedEventSchema = BaseCellEventSchema.extend({
|
|
27489
|
+
type: exports_external.literal("cell_status_changed"),
|
|
27490
|
+
cell_id: exports_external.string(),
|
|
27491
|
+
from_status: CellStatusSchema,
|
|
27492
|
+
to_status: CellStatusSchema,
|
|
27484
27493
|
changed_by: exports_external.string().optional(),
|
|
27485
27494
|
reason: exports_external.string().optional()
|
|
27486
27495
|
});
|
|
27487
|
-
var
|
|
27488
|
-
type: exports_external.literal("
|
|
27489
|
-
|
|
27496
|
+
var CellClosedEventSchema = BaseCellEventSchema.extend({
|
|
27497
|
+
type: exports_external.literal("cell_closed"),
|
|
27498
|
+
cell_id: exports_external.string(),
|
|
27490
27499
|
reason: exports_external.string(),
|
|
27491
27500
|
closed_by: exports_external.string().optional(),
|
|
27492
27501
|
files_touched: exports_external.array(exports_external.string()).optional(),
|
|
27493
27502
|
duration_ms: exports_external.number().optional()
|
|
27494
27503
|
});
|
|
27495
|
-
var
|
|
27496
|
-
type: exports_external.literal("
|
|
27497
|
-
|
|
27504
|
+
var CellReopenedEventSchema = BaseCellEventSchema.extend({
|
|
27505
|
+
type: exports_external.literal("cell_reopened"),
|
|
27506
|
+
cell_id: exports_external.string(),
|
|
27498
27507
|
reason: exports_external.string().optional(),
|
|
27499
27508
|
reopened_by: exports_external.string().optional()
|
|
27500
27509
|
});
|
|
27501
|
-
var
|
|
27502
|
-
type: exports_external.literal("
|
|
27503
|
-
|
|
27510
|
+
var CellDeletedEventSchema = BaseCellEventSchema.extend({
|
|
27511
|
+
type: exports_external.literal("cell_deleted"),
|
|
27512
|
+
cell_id: exports_external.string(),
|
|
27504
27513
|
reason: exports_external.string().optional(),
|
|
27505
27514
|
deleted_by: exports_external.string().optional()
|
|
27506
27515
|
});
|
|
27507
|
-
var
|
|
27508
|
-
type: exports_external.literal("
|
|
27509
|
-
|
|
27510
|
-
dependency:
|
|
27516
|
+
var CellDependencyAddedEventSchema = BaseCellEventSchema.extend({
|
|
27517
|
+
type: exports_external.literal("cell_dependency_added"),
|
|
27518
|
+
cell_id: exports_external.string(),
|
|
27519
|
+
dependency: CellDependencySchema,
|
|
27511
27520
|
added_by: exports_external.string().optional(),
|
|
27512
27521
|
reason: exports_external.string().optional()
|
|
27513
27522
|
});
|
|
27514
|
-
var
|
|
27515
|
-
type: exports_external.literal("
|
|
27516
|
-
|
|
27517
|
-
dependency:
|
|
27523
|
+
var CellDependencyRemovedEventSchema = BaseCellEventSchema.extend({
|
|
27524
|
+
type: exports_external.literal("cell_dependency_removed"),
|
|
27525
|
+
cell_id: exports_external.string(),
|
|
27526
|
+
dependency: CellDependencySchema,
|
|
27518
27527
|
removed_by: exports_external.string().optional(),
|
|
27519
27528
|
reason: exports_external.string().optional()
|
|
27520
27529
|
});
|
|
27521
|
-
var
|
|
27522
|
-
type: exports_external.literal("
|
|
27523
|
-
|
|
27530
|
+
var CellLabelAddedEventSchema = BaseCellEventSchema.extend({
|
|
27531
|
+
type: exports_external.literal("cell_label_added"),
|
|
27532
|
+
cell_id: exports_external.string(),
|
|
27524
27533
|
label: exports_external.string(),
|
|
27525
27534
|
added_by: exports_external.string().optional()
|
|
27526
27535
|
});
|
|
27527
|
-
var
|
|
27528
|
-
type: exports_external.literal("
|
|
27529
|
-
|
|
27536
|
+
var CellLabelRemovedEventSchema = BaseCellEventSchema.extend({
|
|
27537
|
+
type: exports_external.literal("cell_label_removed"),
|
|
27538
|
+
cell_id: exports_external.string(),
|
|
27530
27539
|
label: exports_external.string(),
|
|
27531
27540
|
removed_by: exports_external.string().optional()
|
|
27532
27541
|
});
|
|
27533
|
-
var
|
|
27534
|
-
type: exports_external.literal("
|
|
27535
|
-
|
|
27542
|
+
var CellCommentAddedEventSchema = BaseCellEventSchema.extend({
|
|
27543
|
+
type: exports_external.literal("cell_comment_added"),
|
|
27544
|
+
cell_id: exports_external.string(),
|
|
27536
27545
|
comment_id: exports_external.number().optional(),
|
|
27537
27546
|
author: exports_external.string(),
|
|
27538
27547
|
body: exports_external.string(),
|
|
27539
27548
|
parent_comment_id: exports_external.number().optional(),
|
|
27540
27549
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
27541
27550
|
});
|
|
27542
|
-
var
|
|
27543
|
-
type: exports_external.literal("
|
|
27544
|
-
|
|
27551
|
+
var CellCommentUpdatedEventSchema = BaseCellEventSchema.extend({
|
|
27552
|
+
type: exports_external.literal("cell_comment_updated"),
|
|
27553
|
+
cell_id: exports_external.string(),
|
|
27545
27554
|
comment_id: exports_external.number(),
|
|
27546
27555
|
old_body: exports_external.string(),
|
|
27547
27556
|
new_body: exports_external.string(),
|
|
27548
27557
|
updated_by: exports_external.string()
|
|
27549
27558
|
});
|
|
27550
|
-
var
|
|
27551
|
-
type: exports_external.literal("
|
|
27552
|
-
|
|
27559
|
+
var CellCommentDeletedEventSchema = BaseCellEventSchema.extend({
|
|
27560
|
+
type: exports_external.literal("cell_comment_deleted"),
|
|
27561
|
+
cell_id: exports_external.string(),
|
|
27553
27562
|
comment_id: exports_external.number(),
|
|
27554
27563
|
deleted_by: exports_external.string(),
|
|
27555
27564
|
reason: exports_external.string().optional()
|
|
27556
27565
|
});
|
|
27557
|
-
var
|
|
27558
|
-
type: exports_external.literal("
|
|
27559
|
-
|
|
27566
|
+
var CellEpicChildAddedEventSchema = BaseCellEventSchema.extend({
|
|
27567
|
+
type: exports_external.literal("cell_epic_child_added"),
|
|
27568
|
+
cell_id: exports_external.string(),
|
|
27560
27569
|
child_id: exports_external.string(),
|
|
27561
27570
|
child_index: exports_external.number().optional(),
|
|
27562
27571
|
added_by: exports_external.string().optional()
|
|
27563
27572
|
});
|
|
27564
|
-
var
|
|
27565
|
-
type: exports_external.literal("
|
|
27566
|
-
|
|
27573
|
+
var CellEpicChildRemovedEventSchema = BaseCellEventSchema.extend({
|
|
27574
|
+
type: exports_external.literal("cell_epic_child_removed"),
|
|
27575
|
+
cell_id: exports_external.string(),
|
|
27567
27576
|
child_id: exports_external.string(),
|
|
27568
27577
|
removed_by: exports_external.string().optional(),
|
|
27569
27578
|
reason: exports_external.string().optional()
|
|
27570
27579
|
});
|
|
27571
|
-
var
|
|
27572
|
-
type: exports_external.literal("
|
|
27573
|
-
|
|
27580
|
+
var CellEpicClosureEligibleEventSchema = BaseCellEventSchema.extend({
|
|
27581
|
+
type: exports_external.literal("cell_epic_closure_eligible"),
|
|
27582
|
+
cell_id: exports_external.string(),
|
|
27574
27583
|
child_ids: exports_external.array(exports_external.string()),
|
|
27575
27584
|
total_duration_ms: exports_external.number().optional(),
|
|
27576
27585
|
all_files_touched: exports_external.array(exports_external.string()).optional()
|
|
27577
27586
|
});
|
|
27578
|
-
var
|
|
27579
|
-
type: exports_external.literal("
|
|
27580
|
-
|
|
27587
|
+
var CellAssignedEventSchema = BaseCellEventSchema.extend({
|
|
27588
|
+
type: exports_external.literal("cell_assigned"),
|
|
27589
|
+
cell_id: exports_external.string(),
|
|
27581
27590
|
agent_name: exports_external.string(),
|
|
27582
27591
|
task_description: exports_external.string().optional()
|
|
27583
27592
|
});
|
|
27584
|
-
var
|
|
27585
|
-
type: exports_external.literal("
|
|
27586
|
-
|
|
27593
|
+
var CellWorkStartedEventSchema = BaseCellEventSchema.extend({
|
|
27594
|
+
type: exports_external.literal("cell_work_started"),
|
|
27595
|
+
cell_id: exports_external.string(),
|
|
27587
27596
|
agent_name: exports_external.string(),
|
|
27588
27597
|
reserved_files: exports_external.array(exports_external.string()).optional()
|
|
27589
27598
|
});
|
|
27590
|
-
var
|
|
27591
|
-
type: exports_external.literal("
|
|
27592
|
-
|
|
27599
|
+
var CellCompactedEventSchema = BaseCellEventSchema.extend({
|
|
27600
|
+
type: exports_external.literal("cell_compacted"),
|
|
27601
|
+
cell_id: exports_external.string(),
|
|
27593
27602
|
events_archived: exports_external.number(),
|
|
27594
27603
|
new_start_sequence: exports_external.number()
|
|
27595
27604
|
});
|
|
27596
|
-
var
|
|
27597
|
-
|
|
27598
|
-
|
|
27599
|
-
|
|
27600
|
-
|
|
27601
|
-
|
|
27602
|
-
|
|
27603
|
-
|
|
27604
|
-
|
|
27605
|
-
|
|
27606
|
-
|
|
27607
|
-
|
|
27608
|
-
|
|
27609
|
-
|
|
27610
|
-
|
|
27611
|
-
|
|
27612
|
-
|
|
27613
|
-
|
|
27614
|
-
|
|
27615
|
-
|
|
27605
|
+
var CellEventSchema = exports_external.discriminatedUnion("type", [
|
|
27606
|
+
CellCreatedEventSchema,
|
|
27607
|
+
CellUpdatedEventSchema,
|
|
27608
|
+
CellStatusChangedEventSchema,
|
|
27609
|
+
CellClosedEventSchema,
|
|
27610
|
+
CellReopenedEventSchema,
|
|
27611
|
+
CellDeletedEventSchema,
|
|
27612
|
+
CellDependencyAddedEventSchema,
|
|
27613
|
+
CellDependencyRemovedEventSchema,
|
|
27614
|
+
CellLabelAddedEventSchema,
|
|
27615
|
+
CellLabelRemovedEventSchema,
|
|
27616
|
+
CellCommentAddedEventSchema,
|
|
27617
|
+
CellCommentUpdatedEventSchema,
|
|
27618
|
+
CellCommentDeletedEventSchema,
|
|
27619
|
+
CellEpicChildAddedEventSchema,
|
|
27620
|
+
CellEpicChildRemovedEventSchema,
|
|
27621
|
+
CellEpicClosureEligibleEventSchema,
|
|
27622
|
+
CellAssignedEventSchema,
|
|
27623
|
+
CellWorkStartedEventSchema,
|
|
27624
|
+
CellCompactedEventSchema
|
|
27616
27625
|
]);
|
|
27617
|
-
function
|
|
27626
|
+
function createCellEvent(type, data) {
|
|
27618
27627
|
const event = {
|
|
27619
27628
|
type,
|
|
27620
27629
|
timestamp: Date.now(),
|
|
27621
27630
|
...data
|
|
27622
27631
|
};
|
|
27623
|
-
const result =
|
|
27632
|
+
const result = CellEventSchema.safeParse(event);
|
|
27624
27633
|
if (!result.success) {
|
|
27625
|
-
throw new Error(`Invalid
|
|
27634
|
+
throw new Error(`Invalid cell event: ${result.error.message}`);
|
|
27626
27635
|
}
|
|
27627
27636
|
return result.data;
|
|
27628
27637
|
}
|
|
27629
|
-
function
|
|
27638
|
+
function isCellEventType(event, type) {
|
|
27630
27639
|
return event.type === type;
|
|
27631
27640
|
}
|
|
27632
|
-
function
|
|
27633
|
-
return event.
|
|
27641
|
+
function getCellIdFromEvent(event) {
|
|
27642
|
+
return event.cell_id;
|
|
27634
27643
|
}
|
|
27635
27644
|
function isStateTransitionEvent(event) {
|
|
27636
|
-
return event.type === "
|
|
27645
|
+
return event.type === "cell_status_changed" || event.type === "cell_closed" || event.type === "cell_reopened";
|
|
27637
27646
|
}
|
|
27638
27647
|
function isEpicEvent(event) {
|
|
27639
|
-
return event.type === "
|
|
27648
|
+
return event.type === "cell_epic_child_added" || event.type === "cell_epic_child_removed" || event.type === "cell_epic_closure_eligible";
|
|
27640
27649
|
}
|
|
27641
27650
|
function isAgentEvent(event) {
|
|
27642
27651
|
if ("agent_name" in event)
|
|
@@ -27659,17 +27668,43 @@ function isAgentEvent(event) {
|
|
|
27659
27668
|
return false;
|
|
27660
27669
|
});
|
|
27661
27670
|
}
|
|
27662
|
-
|
|
27671
|
+
var BaseBeadEventSchema = BaseCellEventSchema;
|
|
27672
|
+
var BeadCreatedEventSchema = CellCreatedEventSchema;
|
|
27673
|
+
var BeadUpdatedEventSchema = CellUpdatedEventSchema;
|
|
27674
|
+
var BeadStatusChangedEventSchema = CellStatusChangedEventSchema;
|
|
27675
|
+
var BeadClosedEventSchema = CellClosedEventSchema;
|
|
27676
|
+
var BeadReopenedEventSchema = CellReopenedEventSchema;
|
|
27677
|
+
var BeadDeletedEventSchema = CellDeletedEventSchema;
|
|
27678
|
+
var BeadDependencyAddedEventSchema = CellDependencyAddedEventSchema;
|
|
27679
|
+
var BeadDependencyRemovedEventSchema = CellDependencyRemovedEventSchema;
|
|
27680
|
+
var BeadLabelAddedEventSchema = CellLabelAddedEventSchema;
|
|
27681
|
+
var BeadLabelRemovedEventSchema = CellLabelRemovedEventSchema;
|
|
27682
|
+
var BeadCommentAddedEventSchema = CellCommentAddedEventSchema;
|
|
27683
|
+
var BeadCommentUpdatedEventSchema = CellCommentUpdatedEventSchema;
|
|
27684
|
+
var BeadCommentDeletedEventSchema = CellCommentDeletedEventSchema;
|
|
27685
|
+
var BeadEpicChildAddedEventSchema = CellEpicChildAddedEventSchema;
|
|
27686
|
+
var BeadEpicChildRemovedEventSchema = CellEpicChildRemovedEventSchema;
|
|
27687
|
+
var BeadEpicClosureEligibleEventSchema = CellEpicClosureEligibleEventSchema;
|
|
27688
|
+
var BeadAssignedEventSchema = CellAssignedEventSchema;
|
|
27689
|
+
var BeadWorkStartedEventSchema = CellWorkStartedEventSchema;
|
|
27690
|
+
var BeadCompactedEventSchema = CellCompactedEventSchema;
|
|
27691
|
+
var BeadEventSchema = CellEventSchema;
|
|
27692
|
+
var createBeadEvent = createCellEvent;
|
|
27693
|
+
var isBeadEventType = isCellEventType;
|
|
27694
|
+
var getBeadIdFromEvent = getCellIdFromEvent;
|
|
27695
|
+
// src/hive.ts
|
|
27663
27696
|
import { createEvent, appendEvent } from "swarm-mail";
|
|
27664
|
-
var
|
|
27665
|
-
function
|
|
27666
|
-
|
|
27697
|
+
var hiveWorkingDirectory = null;
|
|
27698
|
+
function setHiveWorkingDirectory(directory) {
|
|
27699
|
+
hiveWorkingDirectory = directory;
|
|
27667
27700
|
}
|
|
27668
|
-
function
|
|
27669
|
-
return
|
|
27701
|
+
function getHiveWorkingDirectory() {
|
|
27702
|
+
return hiveWorkingDirectory || process.cwd();
|
|
27670
27703
|
}
|
|
27704
|
+
var setBeadsWorkingDirectory = setHiveWorkingDirectory;
|
|
27705
|
+
var getBeadsWorkingDirectory = getHiveWorkingDirectory;
|
|
27671
27706
|
async function runGitCommand(args) {
|
|
27672
|
-
const cwd =
|
|
27707
|
+
const cwd = getHiveWorkingDirectory();
|
|
27673
27708
|
const proc = Bun.spawn(["git", ...args], {
|
|
27674
27709
|
cwd,
|
|
27675
27710
|
stdout: "pipe",
|
|
@@ -27683,7 +27718,7 @@ async function runGitCommand(args) {
|
|
|
27683
27718
|
return { exitCode, stdout, stderr };
|
|
27684
27719
|
}
|
|
27685
27720
|
|
|
27686
|
-
class
|
|
27721
|
+
class HiveError extends Error {
|
|
27687
27722
|
command;
|
|
27688
27723
|
exitCode;
|
|
27689
27724
|
stderr;
|
|
@@ -27692,38 +27727,41 @@ class BeadError extends Error {
|
|
|
27692
27727
|
this.command = command;
|
|
27693
27728
|
this.exitCode = exitCode;
|
|
27694
27729
|
this.stderr = stderr;
|
|
27695
|
-
this.name = "
|
|
27730
|
+
this.name = "HiveError";
|
|
27696
27731
|
}
|
|
27697
27732
|
}
|
|
27733
|
+
var BeadError = HiveError;
|
|
27698
27734
|
|
|
27699
|
-
class
|
|
27735
|
+
class HiveValidationError extends Error {
|
|
27700
27736
|
zodError;
|
|
27701
27737
|
constructor(message, zodError) {
|
|
27702
27738
|
super(message);
|
|
27703
27739
|
this.zodError = zodError;
|
|
27704
|
-
this.name = "
|
|
27740
|
+
this.name = "HiveValidationError";
|
|
27705
27741
|
}
|
|
27706
27742
|
}
|
|
27743
|
+
var BeadValidationError = HiveValidationError;
|
|
27707
27744
|
var adapterCache = new Map;
|
|
27708
|
-
async function
|
|
27745
|
+
async function getHiveAdapter(projectKey) {
|
|
27709
27746
|
if (adapterCache.has(projectKey)) {
|
|
27710
27747
|
return adapterCache.get(projectKey);
|
|
27711
27748
|
}
|
|
27712
27749
|
const swarmMail = await getSwarmMail(projectKey);
|
|
27713
27750
|
const db = await swarmMail.getDatabase();
|
|
27714
|
-
const adapter =
|
|
27751
|
+
const adapter = createHiveAdapter(db, projectKey);
|
|
27715
27752
|
await adapter.runMigrations();
|
|
27716
27753
|
await autoMigrateFromJSONL(adapter, projectKey);
|
|
27717
27754
|
adapterCache.set(projectKey, adapter);
|
|
27718
27755
|
return adapter;
|
|
27719
27756
|
}
|
|
27757
|
+
var getBeadsAdapter = getHiveAdapter;
|
|
27720
27758
|
async function autoMigrateFromJSONL(adapter, projectKey) {
|
|
27721
|
-
const jsonlPath = join(projectKey, ".
|
|
27759
|
+
const jsonlPath = join(projectKey, ".hive", "issues.jsonl");
|
|
27722
27760
|
if (!existsSync(jsonlPath)) {
|
|
27723
27761
|
return;
|
|
27724
27762
|
}
|
|
27725
|
-
const
|
|
27726
|
-
if (
|
|
27763
|
+
const existingCells = await adapter.queryCells(projectKey, { limit: 1 });
|
|
27764
|
+
if (existingCells.length > 0) {
|
|
27727
27765
|
return;
|
|
27728
27766
|
}
|
|
27729
27767
|
try {
|
|
@@ -27732,62 +27770,62 @@ async function autoMigrateFromJSONL(adapter, projectKey) {
|
|
|
27732
27770
|
skipExisting: true
|
|
27733
27771
|
});
|
|
27734
27772
|
if (result.created > 0 || result.updated > 0) {
|
|
27735
|
-
console.log(`[
|
|
27773
|
+
console.log(`[hive] Auto-migrated ${result.created} cells from ${jsonlPath} (${result.skipped} skipped, ${result.errors.length} errors)`);
|
|
27736
27774
|
}
|
|
27737
27775
|
if (result.errors.length > 0) {
|
|
27738
|
-
console.warn(`[
|
|
27776
|
+
console.warn(`[hive] Migration errors:`, result.errors.slice(0, 5).map((e) => `${e.cellId}: ${e.error}`));
|
|
27739
27777
|
}
|
|
27740
27778
|
} catch (error45) {
|
|
27741
|
-
console.warn(`[
|
|
27779
|
+
console.warn(`[hive] Failed to auto-migrate from ${jsonlPath}:`, error45 instanceof Error ? error45.message : String(error45));
|
|
27742
27780
|
}
|
|
27743
27781
|
}
|
|
27744
|
-
function
|
|
27782
|
+
function formatCellForOutput(adapterCell) {
|
|
27745
27783
|
return {
|
|
27746
|
-
id:
|
|
27747
|
-
title:
|
|
27748
|
-
description:
|
|
27749
|
-
status:
|
|
27750
|
-
priority:
|
|
27751
|
-
issue_type:
|
|
27752
|
-
created_at: new Date(
|
|
27753
|
-
updated_at: new Date(
|
|
27754
|
-
closed_at:
|
|
27755
|
-
parent_id:
|
|
27784
|
+
id: adapterCell.id,
|
|
27785
|
+
title: adapterCell.title,
|
|
27786
|
+
description: adapterCell.description || "",
|
|
27787
|
+
status: adapterCell.status,
|
|
27788
|
+
priority: adapterCell.priority,
|
|
27789
|
+
issue_type: adapterCell.type,
|
|
27790
|
+
created_at: new Date(adapterCell.created_at).toISOString(),
|
|
27791
|
+
updated_at: new Date(adapterCell.updated_at).toISOString(),
|
|
27792
|
+
closed_at: adapterCell.closed_at ? new Date(adapterCell.closed_at).toISOString() : undefined,
|
|
27793
|
+
parent_id: adapterCell.parent_id || undefined,
|
|
27756
27794
|
dependencies: [],
|
|
27757
27795
|
metadata: {}
|
|
27758
27796
|
};
|
|
27759
27797
|
}
|
|
27760
|
-
var
|
|
27761
|
-
description: "Create a new
|
|
27798
|
+
var hive_create = tool({
|
|
27799
|
+
description: "Create a new cell in the hive with type-safe validation",
|
|
27762
27800
|
args: {
|
|
27763
|
-
title: tool.schema.string().describe("
|
|
27801
|
+
title: tool.schema.string().describe("Cell title"),
|
|
27764
27802
|
type: tool.schema.enum(["bug", "feature", "task", "epic", "chore"]).optional().describe("Issue type (default: task)"),
|
|
27765
27803
|
priority: tool.schema.number().min(0).max(3).optional().describe("Priority 0-3 (default: 2)"),
|
|
27766
|
-
description: tool.schema.string().optional().describe("
|
|
27767
|
-
parent_id: tool.schema.string().optional().describe("Parent
|
|
27804
|
+
description: tool.schema.string().optional().describe("Cell description"),
|
|
27805
|
+
parent_id: tool.schema.string().optional().describe("Parent cell ID for epic children")
|
|
27768
27806
|
},
|
|
27769
27807
|
async execute(args, ctx) {
|
|
27770
|
-
const validated =
|
|
27771
|
-
const projectKey =
|
|
27772
|
-
const adapter = await
|
|
27808
|
+
const validated = CellCreateArgsSchema.parse(args);
|
|
27809
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27810
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27773
27811
|
try {
|
|
27774
|
-
const
|
|
27812
|
+
const cell = await adapter.createCell(projectKey, {
|
|
27775
27813
|
title: validated.title,
|
|
27776
27814
|
type: validated.type || "task",
|
|
27777
27815
|
priority: validated.priority ?? 2,
|
|
27778
27816
|
description: validated.description,
|
|
27779
27817
|
parent_id: validated.parent_id
|
|
27780
27818
|
});
|
|
27781
|
-
await adapter.markDirty(projectKey,
|
|
27782
|
-
const formatted =
|
|
27819
|
+
await adapter.markDirty(projectKey, cell.id);
|
|
27820
|
+
const formatted = formatCellForOutput(cell);
|
|
27783
27821
|
return JSON.stringify(formatted, null, 2);
|
|
27784
27822
|
} catch (error45) {
|
|
27785
27823
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27786
|
-
throw new
|
|
27824
|
+
throw new HiveError(`Failed to create cell: ${message}`, "hive_create");
|
|
27787
27825
|
}
|
|
27788
27826
|
}
|
|
27789
27827
|
});
|
|
27790
|
-
var
|
|
27828
|
+
var hive_create_epic = tool({
|
|
27791
27829
|
description: "Create epic with subtasks in one atomic operation",
|
|
27792
27830
|
args: {
|
|
27793
27831
|
epic_title: tool.schema.string().describe("Epic title"),
|
|
@@ -27810,11 +27848,11 @@ var beads_create_epic = tool({
|
|
|
27810
27848
|
},
|
|
27811
27849
|
async execute(args, ctx) {
|
|
27812
27850
|
const validated = EpicCreateArgsSchema.parse(args);
|
|
27813
|
-
const projectKey =
|
|
27814
|
-
const adapter = await
|
|
27851
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27852
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27815
27853
|
const created = [];
|
|
27816
27854
|
try {
|
|
27817
|
-
const epic = await adapter.
|
|
27855
|
+
const epic = await adapter.createCell(projectKey, {
|
|
27818
27856
|
title: validated.epic_title,
|
|
27819
27857
|
type: "epic",
|
|
27820
27858
|
priority: 1,
|
|
@@ -27823,19 +27861,19 @@ var beads_create_epic = tool({
|
|
|
27823
27861
|
await adapter.markDirty(projectKey, epic.id);
|
|
27824
27862
|
created.push(epic);
|
|
27825
27863
|
for (const subtask of validated.subtasks) {
|
|
27826
|
-
const
|
|
27864
|
+
const subtaskCell = await adapter.createCell(projectKey, {
|
|
27827
27865
|
title: subtask.title,
|
|
27828
27866
|
type: "task",
|
|
27829
27867
|
priority: subtask.priority ?? 2,
|
|
27830
27868
|
parent_id: epic.id
|
|
27831
27869
|
});
|
|
27832
|
-
await adapter.markDirty(projectKey,
|
|
27833
|
-
created.push(
|
|
27870
|
+
await adapter.markDirty(projectKey, subtaskCell.id);
|
|
27871
|
+
created.push(subtaskCell);
|
|
27834
27872
|
}
|
|
27835
27873
|
const result = {
|
|
27836
27874
|
success: true,
|
|
27837
|
-
epic:
|
|
27838
|
-
subtasks: created.slice(1).map((
|
|
27875
|
+
epic: formatCellForOutput(epic),
|
|
27876
|
+
subtasks: created.slice(1).map((c) => formatCellForOutput(c))
|
|
27839
27877
|
};
|
|
27840
27878
|
if (args.project_key) {
|
|
27841
27879
|
try {
|
|
@@ -27855,27 +27893,27 @@ var beads_create_epic = tool({
|
|
|
27855
27893
|
});
|
|
27856
27894
|
await appendEvent(event, args.project_key);
|
|
27857
27895
|
} catch (error45) {
|
|
27858
|
-
console.warn("[
|
|
27896
|
+
console.warn("[hive_create_epic] Failed to emit DecompositionGeneratedEvent:", error45);
|
|
27859
27897
|
}
|
|
27860
27898
|
}
|
|
27861
27899
|
return JSON.stringify(result, null, 2);
|
|
27862
27900
|
} catch (error45) {
|
|
27863
27901
|
const rollbackErrors = [];
|
|
27864
|
-
for (const
|
|
27902
|
+
for (const cell of created) {
|
|
27865
27903
|
try {
|
|
27866
|
-
await adapter.
|
|
27904
|
+
await adapter.deleteCell(projectKey, cell.id, {
|
|
27867
27905
|
reason: "Rollback partial epic"
|
|
27868
27906
|
});
|
|
27869
27907
|
} catch (rollbackError) {
|
|
27870
27908
|
const errMsg = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
|
|
27871
|
-
console.error(`Failed to rollback
|
|
27872
|
-
rollbackErrors.push(`${
|
|
27909
|
+
console.error(`Failed to rollback cell ${cell.id}:`, rollbackError);
|
|
27910
|
+
rollbackErrors.push(`${cell.id}: ${errMsg}`);
|
|
27873
27911
|
}
|
|
27874
27912
|
}
|
|
27875
27913
|
const errorMsg = error45 instanceof Error ? error45.message : String(error45);
|
|
27876
27914
|
let rollbackInfo = `
|
|
27877
27915
|
|
|
27878
|
-
Rolled back ${created.length - rollbackErrors.length}
|
|
27916
|
+
Rolled back ${created.length - rollbackErrors.length} cell(s)`;
|
|
27879
27917
|
if (rollbackErrors.length > 0) {
|
|
27880
27918
|
rollbackInfo += `
|
|
27881
27919
|
|
|
@@ -27883,151 +27921,151 @@ Rollback failures (${rollbackErrors.length}):
|
|
|
27883
27921
|
${rollbackErrors.join(`
|
|
27884
27922
|
`)}`;
|
|
27885
27923
|
}
|
|
27886
|
-
throw new
|
|
27924
|
+
throw new HiveError(`Epic creation failed: ${errorMsg}${rollbackInfo}`, "hive_create_epic", 1);
|
|
27887
27925
|
}
|
|
27888
27926
|
}
|
|
27889
27927
|
});
|
|
27890
|
-
var
|
|
27891
|
-
description: "Query
|
|
27928
|
+
var hive_query = tool({
|
|
27929
|
+
description: "Query hive cells with filters (replaces bd list, bd ready, bd wip)",
|
|
27892
27930
|
args: {
|
|
27893
27931
|
status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("Filter by status"),
|
|
27894
27932
|
type: tool.schema.enum(["bug", "feature", "task", "epic", "chore"]).optional().describe("Filter by type"),
|
|
27895
|
-
ready: tool.schema.boolean().optional().describe("Only show unblocked
|
|
27933
|
+
ready: tool.schema.boolean().optional().describe("Only show unblocked cells"),
|
|
27896
27934
|
limit: tool.schema.number().optional().describe("Max results to return (default: 20)")
|
|
27897
27935
|
},
|
|
27898
27936
|
async execute(args, ctx) {
|
|
27899
|
-
const validated =
|
|
27900
|
-
const projectKey =
|
|
27901
|
-
const adapter = await
|
|
27937
|
+
const validated = CellQueryArgsSchema.parse(args);
|
|
27938
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27939
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27902
27940
|
try {
|
|
27903
|
-
let
|
|
27941
|
+
let cells;
|
|
27904
27942
|
if (validated.ready) {
|
|
27905
|
-
const
|
|
27906
|
-
|
|
27943
|
+
const readyCell = await adapter.getNextReadyCell(projectKey);
|
|
27944
|
+
cells = readyCell ? [readyCell] : [];
|
|
27907
27945
|
} else {
|
|
27908
|
-
|
|
27946
|
+
cells = await adapter.queryCells(projectKey, {
|
|
27909
27947
|
status: validated.status,
|
|
27910
27948
|
type: validated.type,
|
|
27911
27949
|
limit: validated.limit || 20
|
|
27912
27950
|
});
|
|
27913
27951
|
}
|
|
27914
|
-
const formatted =
|
|
27952
|
+
const formatted = cells.map((c) => formatCellForOutput(c));
|
|
27915
27953
|
return JSON.stringify(formatted, null, 2);
|
|
27916
27954
|
} catch (error45) {
|
|
27917
27955
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27918
|
-
throw new
|
|
27956
|
+
throw new HiveError(`Failed to query cells: ${message}`, "hive_query");
|
|
27919
27957
|
}
|
|
27920
27958
|
}
|
|
27921
27959
|
});
|
|
27922
|
-
var
|
|
27923
|
-
description: "Update
|
|
27960
|
+
var hive_update = tool({
|
|
27961
|
+
description: "Update cell status/description",
|
|
27924
27962
|
args: {
|
|
27925
|
-
id: tool.schema.string().describe("
|
|
27963
|
+
id: tool.schema.string().describe("Cell ID"),
|
|
27926
27964
|
status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("New status"),
|
|
27927
27965
|
description: tool.schema.string().optional().describe("New description"),
|
|
27928
27966
|
priority: tool.schema.number().min(0).max(3).optional().describe("New priority")
|
|
27929
27967
|
},
|
|
27930
27968
|
async execute(args, ctx) {
|
|
27931
|
-
const validated =
|
|
27932
|
-
const projectKey =
|
|
27933
|
-
const adapter = await
|
|
27969
|
+
const validated = CellUpdateArgsSchema.parse(args);
|
|
27970
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27971
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27934
27972
|
try {
|
|
27935
|
-
let
|
|
27973
|
+
let cell;
|
|
27936
27974
|
if (validated.status) {
|
|
27937
|
-
|
|
27975
|
+
cell = await adapter.changeCellStatus(projectKey, validated.id, validated.status);
|
|
27938
27976
|
}
|
|
27939
27977
|
if (validated.description !== undefined || validated.priority !== undefined) {
|
|
27940
|
-
|
|
27978
|
+
cell = await adapter.updateCell(projectKey, validated.id, {
|
|
27941
27979
|
description: validated.description,
|
|
27942
27980
|
priority: validated.priority
|
|
27943
27981
|
});
|
|
27944
27982
|
} else if (!validated.status) {
|
|
27945
|
-
const
|
|
27946
|
-
if (!
|
|
27947
|
-
throw new
|
|
27983
|
+
const existingCell = await adapter.getCell(projectKey, validated.id);
|
|
27984
|
+
if (!existingCell) {
|
|
27985
|
+
throw new HiveError(`Cell not found: ${validated.id}`, "hive_update");
|
|
27948
27986
|
}
|
|
27949
|
-
|
|
27987
|
+
cell = existingCell;
|
|
27950
27988
|
}
|
|
27951
27989
|
await adapter.markDirty(projectKey, validated.id);
|
|
27952
|
-
const formatted =
|
|
27990
|
+
const formatted = formatCellForOutput(cell);
|
|
27953
27991
|
return JSON.stringify(formatted, null, 2);
|
|
27954
27992
|
} catch (error45) {
|
|
27955
27993
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27956
|
-
throw new
|
|
27994
|
+
throw new HiveError(`Failed to update cell: ${message}`, "hive_update");
|
|
27957
27995
|
}
|
|
27958
27996
|
}
|
|
27959
27997
|
});
|
|
27960
|
-
var
|
|
27961
|
-
description: "Close a
|
|
27998
|
+
var hive_close = tool({
|
|
27999
|
+
description: "Close a cell with reason",
|
|
27962
28000
|
args: {
|
|
27963
|
-
id: tool.schema.string().describe("
|
|
28001
|
+
id: tool.schema.string().describe("Cell ID"),
|
|
27964
28002
|
reason: tool.schema.string().describe("Completion reason")
|
|
27965
28003
|
},
|
|
27966
28004
|
async execute(args, ctx) {
|
|
27967
|
-
const validated =
|
|
27968
|
-
const projectKey =
|
|
27969
|
-
const adapter = await
|
|
28005
|
+
const validated = CellCloseArgsSchema.parse(args);
|
|
28006
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28007
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27970
28008
|
try {
|
|
27971
|
-
const
|
|
28009
|
+
const cell = await adapter.closeCell(projectKey, validated.id, validated.reason);
|
|
27972
28010
|
await adapter.markDirty(projectKey, validated.id);
|
|
27973
|
-
return `Closed ${
|
|
28011
|
+
return `Closed ${cell.id}: ${validated.reason}`;
|
|
27974
28012
|
} catch (error45) {
|
|
27975
28013
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27976
|
-
throw new
|
|
28014
|
+
throw new HiveError(`Failed to close cell: ${message}`, "hive_close");
|
|
27977
28015
|
}
|
|
27978
28016
|
}
|
|
27979
28017
|
});
|
|
27980
|
-
var
|
|
27981
|
-
description: "Mark a
|
|
28018
|
+
var hive_start = tool({
|
|
28019
|
+
description: "Mark a cell as in-progress (shortcut for update --status in_progress)",
|
|
27982
28020
|
args: {
|
|
27983
|
-
id: tool.schema.string().describe("
|
|
28021
|
+
id: tool.schema.string().describe("Cell ID")
|
|
27984
28022
|
},
|
|
27985
28023
|
async execute(args, ctx) {
|
|
27986
|
-
const projectKey =
|
|
27987
|
-
const adapter = await
|
|
28024
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28025
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27988
28026
|
try {
|
|
27989
|
-
const
|
|
28027
|
+
const cell = await adapter.changeCellStatus(projectKey, args.id, "in_progress");
|
|
27990
28028
|
await adapter.markDirty(projectKey, args.id);
|
|
27991
|
-
return `Started: ${
|
|
28029
|
+
return `Started: ${cell.id}`;
|
|
27992
28030
|
} catch (error45) {
|
|
27993
28031
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27994
|
-
throw new
|
|
28032
|
+
throw new HiveError(`Failed to start cell: ${message}`, "hive_start");
|
|
27995
28033
|
}
|
|
27996
28034
|
}
|
|
27997
28035
|
});
|
|
27998
|
-
var
|
|
27999
|
-
description: "Get the next ready
|
|
28036
|
+
var hive_ready = tool({
|
|
28037
|
+
description: "Get the next ready cell (unblocked, highest priority)",
|
|
28000
28038
|
args: {},
|
|
28001
28039
|
async execute(args, ctx) {
|
|
28002
|
-
const projectKey =
|
|
28003
|
-
const adapter = await
|
|
28040
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28041
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
28004
28042
|
try {
|
|
28005
|
-
const
|
|
28006
|
-
if (!
|
|
28007
|
-
return "No ready
|
|
28043
|
+
const cell = await adapter.getNextReadyCell(projectKey);
|
|
28044
|
+
if (!cell) {
|
|
28045
|
+
return "No ready cells";
|
|
28008
28046
|
}
|
|
28009
|
-
const formatted =
|
|
28047
|
+
const formatted = formatCellForOutput(cell);
|
|
28010
28048
|
return JSON.stringify(formatted, null, 2);
|
|
28011
28049
|
} catch (error45) {
|
|
28012
28050
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
28013
|
-
throw new
|
|
28051
|
+
throw new HiveError(`Failed to get ready cells: ${message}`, "hive_ready");
|
|
28014
28052
|
}
|
|
28015
28053
|
}
|
|
28016
28054
|
});
|
|
28017
|
-
var
|
|
28018
|
-
description: "Sync
|
|
28055
|
+
var hive_sync = tool({
|
|
28056
|
+
description: "Sync hive to git and push (MANDATORY at session end)",
|
|
28019
28057
|
args: {
|
|
28020
28058
|
auto_pull: tool.schema.boolean().optional().describe("Pull before sync (default: true)")
|
|
28021
28059
|
},
|
|
28022
28060
|
async execute(args, ctx) {
|
|
28023
28061
|
const autoPull = args.auto_pull ?? true;
|
|
28024
|
-
const projectKey =
|
|
28025
|
-
const adapter = await
|
|
28062
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28063
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
28026
28064
|
const TIMEOUT_MS = 30000;
|
|
28027
28065
|
const withTimeout = async (promise2, timeoutMs, operation) => {
|
|
28028
28066
|
let timeoutId;
|
|
28029
28067
|
const timeoutPromise = new Promise((_, reject) => {
|
|
28030
|
-
timeoutId = setTimeout(() => reject(new
|
|
28068
|
+
timeoutId = setTimeout(() => reject(new HiveError(`Operation timed out after ${timeoutMs}ms`, operation)), timeoutMs);
|
|
28031
28069
|
});
|
|
28032
28070
|
try {
|
|
28033
28071
|
return await Promise.race([promise2, timeoutPromise]);
|
|
@@ -28040,74 +28078,156 @@ var beads_sync = tool({
|
|
|
28040
28078
|
const flushManager = new FlushManager({
|
|
28041
28079
|
adapter,
|
|
28042
28080
|
projectKey,
|
|
28043
|
-
outputPath: `${projectKey}/.
|
|
28081
|
+
outputPath: `${projectKey}/.hive/issues.jsonl`
|
|
28044
28082
|
});
|
|
28045
|
-
const flushResult = await withTimeout(flushManager.flush(), TIMEOUT_MS, "flush
|
|
28046
|
-
if (flushResult.
|
|
28047
|
-
return "No
|
|
28083
|
+
const flushResult = await withTimeout(flushManager.flush(), TIMEOUT_MS, "flush hive");
|
|
28084
|
+
if (flushResult.cellsExported === 0) {
|
|
28085
|
+
return "No cells to sync";
|
|
28048
28086
|
}
|
|
28049
|
-
const
|
|
28087
|
+
const hiveStatusResult = await runGitCommand([
|
|
28050
28088
|
"status",
|
|
28051
28089
|
"--porcelain",
|
|
28052
|
-
".
|
|
28090
|
+
".hive/"
|
|
28053
28091
|
]);
|
|
28054
|
-
const hasChanges =
|
|
28092
|
+
const hasChanges = hiveStatusResult.stdout.trim() !== "";
|
|
28055
28093
|
if (hasChanges) {
|
|
28056
|
-
const addResult = await runGitCommand(["add", ".
|
|
28094
|
+
const addResult = await runGitCommand(["add", ".hive/"]);
|
|
28057
28095
|
if (addResult.exitCode !== 0) {
|
|
28058
|
-
throw new
|
|
28096
|
+
throw new HiveError(`Failed to stage hive: ${addResult.stderr}`, "git add .hive/", addResult.exitCode);
|
|
28059
28097
|
}
|
|
28060
|
-
const commitResult = await withTimeout(runGitCommand(["commit", "-m", "chore: sync
|
|
28098
|
+
const commitResult = await withTimeout(runGitCommand(["commit", "-m", "chore: sync hive"]), TIMEOUT_MS, "git commit");
|
|
28061
28099
|
if (commitResult.exitCode !== 0 && !commitResult.stdout.includes("nothing to commit")) {
|
|
28062
|
-
throw new
|
|
28100
|
+
throw new HiveError(`Failed to commit hive: ${commitResult.stderr}`, "git commit", commitResult.exitCode);
|
|
28063
28101
|
}
|
|
28064
28102
|
}
|
|
28065
28103
|
if (autoPull) {
|
|
28066
28104
|
const pullResult = await withTimeout(runGitCommand(["pull", "--rebase"]), TIMEOUT_MS, "git pull --rebase");
|
|
28067
28105
|
if (pullResult.exitCode !== 0) {
|
|
28068
|
-
throw new
|
|
28106
|
+
throw new HiveError(`Failed to pull: ${pullResult.stderr}`, "git pull --rebase", pullResult.exitCode);
|
|
28069
28107
|
}
|
|
28070
28108
|
}
|
|
28071
28109
|
const pushResult = await withTimeout(runGitCommand(["push"]), TIMEOUT_MS, "git push");
|
|
28072
28110
|
if (pushResult.exitCode !== 0) {
|
|
28073
|
-
throw new
|
|
28111
|
+
throw new HiveError(`Failed to push: ${pushResult.stderr}`, "git push", pushResult.exitCode);
|
|
28074
28112
|
}
|
|
28075
|
-
return "
|
|
28113
|
+
return "Hive synced and pushed successfully";
|
|
28076
28114
|
}
|
|
28077
28115
|
});
|
|
28078
|
-
var
|
|
28079
|
-
description: "Add metadata linking
|
|
28116
|
+
var hive_link_thread = tool({
|
|
28117
|
+
description: "Add metadata linking cell to Agent Mail thread",
|
|
28080
28118
|
args: {
|
|
28081
|
-
|
|
28119
|
+
cell_id: tool.schema.string().describe("Cell ID"),
|
|
28082
28120
|
thread_id: tool.schema.string().describe("Agent Mail thread ID")
|
|
28083
28121
|
},
|
|
28084
28122
|
async execute(args, ctx) {
|
|
28085
|
-
const projectKey =
|
|
28086
|
-
const adapter = await
|
|
28123
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28124
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
28087
28125
|
try {
|
|
28088
|
-
const
|
|
28089
|
-
if (!
|
|
28090
|
-
throw new
|
|
28126
|
+
const cell = await adapter.getCell(projectKey, args.cell_id);
|
|
28127
|
+
if (!cell) {
|
|
28128
|
+
throw new HiveError(`Cell not found: ${args.cell_id}`, "hive_link_thread");
|
|
28091
28129
|
}
|
|
28092
|
-
const existingDesc =
|
|
28130
|
+
const existingDesc = cell.description || "";
|
|
28093
28131
|
const threadMarker = `[thread:${args.thread_id}]`;
|
|
28094
28132
|
if (existingDesc.includes(threadMarker)) {
|
|
28095
|
-
return `
|
|
28133
|
+
return `Cell ${args.cell_id} already linked to thread ${args.thread_id}`;
|
|
28096
28134
|
}
|
|
28097
28135
|
const newDesc = existingDesc ? `${existingDesc}
|
|
28098
28136
|
|
|
28099
28137
|
${threadMarker}` : threadMarker;
|
|
28100
|
-
await adapter.
|
|
28138
|
+
await adapter.updateCell(projectKey, args.cell_id, {
|
|
28101
28139
|
description: newDesc
|
|
28102
28140
|
});
|
|
28103
|
-
await adapter.markDirty(projectKey, args.
|
|
28104
|
-
return `Linked
|
|
28141
|
+
await adapter.markDirty(projectKey, args.cell_id);
|
|
28142
|
+
return `Linked cell ${args.cell_id} to thread ${args.thread_id}`;
|
|
28105
28143
|
} catch (error45) {
|
|
28106
28144
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
28107
|
-
throw new
|
|
28145
|
+
throw new HiveError(`Failed to link thread: ${message}`, "hive_link_thread");
|
|
28108
28146
|
}
|
|
28109
28147
|
}
|
|
28110
28148
|
});
|
|
28149
|
+
var hiveTools = {
|
|
28150
|
+
hive_create,
|
|
28151
|
+
hive_create_epic,
|
|
28152
|
+
hive_query,
|
|
28153
|
+
hive_update,
|
|
28154
|
+
hive_close,
|
|
28155
|
+
hive_start,
|
|
28156
|
+
hive_ready,
|
|
28157
|
+
hive_sync,
|
|
28158
|
+
hive_link_thread
|
|
28159
|
+
};
|
|
28160
|
+
var warnedTools = new Set;
|
|
28161
|
+
function warnDeprecated(oldName, newName) {
|
|
28162
|
+
if (warnedTools.has(oldName)) {
|
|
28163
|
+
return;
|
|
28164
|
+
}
|
|
28165
|
+
warnedTools.add(oldName);
|
|
28166
|
+
console.warn(`[DEPRECATED] ${oldName} is deprecated, use ${newName} instead. Will be removed in v1.0`);
|
|
28167
|
+
}
|
|
28168
|
+
var beads_create = tool({
|
|
28169
|
+
...hive_create,
|
|
28170
|
+
async execute(args, ctx) {
|
|
28171
|
+
warnDeprecated("beads_create", "hive_create");
|
|
28172
|
+
return hive_create.execute(args, ctx);
|
|
28173
|
+
}
|
|
28174
|
+
});
|
|
28175
|
+
var beads_create_epic = tool({
|
|
28176
|
+
...hive_create_epic,
|
|
28177
|
+
async execute(args, ctx) {
|
|
28178
|
+
warnDeprecated("beads_create_epic", "hive_create_epic");
|
|
28179
|
+
return hive_create_epic.execute(args, ctx);
|
|
28180
|
+
}
|
|
28181
|
+
});
|
|
28182
|
+
var beads_query = tool({
|
|
28183
|
+
...hive_query,
|
|
28184
|
+
async execute(args, ctx) {
|
|
28185
|
+
warnDeprecated("beads_query", "hive_query");
|
|
28186
|
+
return hive_query.execute(args, ctx);
|
|
28187
|
+
}
|
|
28188
|
+
});
|
|
28189
|
+
var beads_update = tool({
|
|
28190
|
+
...hive_update,
|
|
28191
|
+
async execute(args, ctx) {
|
|
28192
|
+
warnDeprecated("beads_update", "hive_update");
|
|
28193
|
+
return hive_update.execute(args, ctx);
|
|
28194
|
+
}
|
|
28195
|
+
});
|
|
28196
|
+
var beads_close = tool({
|
|
28197
|
+
...hive_close,
|
|
28198
|
+
async execute(args, ctx) {
|
|
28199
|
+
warnDeprecated("beads_close", "hive_close");
|
|
28200
|
+
return hive_close.execute(args, ctx);
|
|
28201
|
+
}
|
|
28202
|
+
});
|
|
28203
|
+
var beads_start = tool({
|
|
28204
|
+
...hive_start,
|
|
28205
|
+
async execute(args, ctx) {
|
|
28206
|
+
warnDeprecated("beads_start", "hive_start");
|
|
28207
|
+
return hive_start.execute(args, ctx);
|
|
28208
|
+
}
|
|
28209
|
+
});
|
|
28210
|
+
var beads_ready = tool({
|
|
28211
|
+
...hive_ready,
|
|
28212
|
+
async execute(args, ctx) {
|
|
28213
|
+
warnDeprecated("beads_ready", "hive_ready");
|
|
28214
|
+
return hive_ready.execute(args, ctx);
|
|
28215
|
+
}
|
|
28216
|
+
});
|
|
28217
|
+
var beads_sync = tool({
|
|
28218
|
+
...hive_sync,
|
|
28219
|
+
async execute(args, ctx) {
|
|
28220
|
+
warnDeprecated("beads_sync", "hive_sync");
|
|
28221
|
+
return hive_sync.execute(args, ctx);
|
|
28222
|
+
}
|
|
28223
|
+
});
|
|
28224
|
+
var beads_link_thread = tool({
|
|
28225
|
+
...hive_link_thread,
|
|
28226
|
+
async execute(args, ctx) {
|
|
28227
|
+
warnDeprecated("beads_link_thread", "hive_link_thread");
|
|
28228
|
+
return hive_link_thread.execute(args, ctx);
|
|
28229
|
+
}
|
|
28230
|
+
});
|
|
28111
28231
|
var beadsTools = {
|
|
28112
28232
|
beads_create,
|
|
28113
28233
|
beads_create_epic,
|
|
@@ -28237,6 +28357,29 @@ var toolCheckers = {
|
|
|
28237
28357
|
};
|
|
28238
28358
|
}
|
|
28239
28359
|
},
|
|
28360
|
+
hive: async () => {
|
|
28361
|
+
const exists = await commandExists("hive");
|
|
28362
|
+
if (!exists) {
|
|
28363
|
+
return {
|
|
28364
|
+
available: false,
|
|
28365
|
+
checkedAt: new Date().toISOString(),
|
|
28366
|
+
error: "hive command not found"
|
|
28367
|
+
};
|
|
28368
|
+
}
|
|
28369
|
+
try {
|
|
28370
|
+
const result = await Bun.$`hive --version`.quiet().nothrow();
|
|
28371
|
+
return {
|
|
28372
|
+
available: result.exitCode === 0,
|
|
28373
|
+
checkedAt: new Date().toISOString()
|
|
28374
|
+
};
|
|
28375
|
+
} catch (e) {
|
|
28376
|
+
return {
|
|
28377
|
+
available: false,
|
|
28378
|
+
checkedAt: new Date().toISOString(),
|
|
28379
|
+
error: String(e)
|
|
28380
|
+
};
|
|
28381
|
+
}
|
|
28382
|
+
},
|
|
28240
28383
|
beads: async () => {
|
|
28241
28384
|
const exists = await commandExists("bd");
|
|
28242
28385
|
if (!exists) {
|
|
@@ -28290,7 +28433,8 @@ var fallbackBehaviors = {
|
|
|
28290
28433
|
"semantic-memory": "Learning data stored in-memory only (lost on session end)",
|
|
28291
28434
|
cass: "Decomposition proceeds without historical context from past sessions",
|
|
28292
28435
|
ubs: "Subtask completion skips bug scanning - manual review recommended",
|
|
28293
|
-
|
|
28436
|
+
hive: "Swarm cannot track issues - task coordination will be less reliable",
|
|
28437
|
+
beads: "DEPRECATED: Use hive instead. Swarm cannot track issues - task coordination will be less reliable",
|
|
28294
28438
|
"swarm-mail": "Multi-agent coordination disabled - file conflicts possible if multiple agents active",
|
|
28295
28439
|
"agent-mail": "DEPRECATED: Use swarm-mail instead. Legacy MCP server mode - file conflicts possible if multiple agents active"
|
|
28296
28440
|
};
|
|
@@ -28321,6 +28465,7 @@ async function checkAllTools() {
|
|
|
28321
28465
|
"semantic-memory",
|
|
28322
28466
|
"cass",
|
|
28323
28467
|
"ubs",
|
|
28468
|
+
"hive",
|
|
28324
28469
|
"beads",
|
|
28325
28470
|
"swarm-mail",
|
|
28326
28471
|
"agent-mail"
|
|
@@ -29922,7 +30067,7 @@ function formatZodErrors(error45) {
|
|
|
29922
30067
|
var SCHEMA_REGISTRY = {
|
|
29923
30068
|
evaluation: EvaluationSchema,
|
|
29924
30069
|
task_decomposition: TaskDecompositionSchema,
|
|
29925
|
-
|
|
30070
|
+
cell_tree: CellTreeSchema
|
|
29926
30071
|
};
|
|
29927
30072
|
function getSchemaByName(name) {
|
|
29928
30073
|
const schema = SCHEMA_REGISTRY[name];
|
|
@@ -30058,7 +30203,7 @@ var structured_validate = tool({
|
|
|
30058
30203
|
description: "Validate agent response against a schema. Extracts JSON and validates with Zod. Returns structured errors for retry feedback.",
|
|
30059
30204
|
args: {
|
|
30060
30205
|
response: tool.schema.string().describe("Agent response to validate"),
|
|
30061
|
-
schema_name: tool.schema.enum(["evaluation", "task_decomposition", "
|
|
30206
|
+
schema_name: tool.schema.enum(["evaluation", "task_decomposition", "cell_tree"]).describe("Schema to validate against: " + "evaluation = agent self-eval with criteria, " + "task_decomposition = swarm task breakdown, " + "cell_tree = epic with subtasks"),
|
|
30062
30207
|
max_retries: tool.schema.number().min(1).max(5).optional().describe("Max retries (for tracking - actual retry logic is external)")
|
|
30063
30208
|
},
|
|
30064
30209
|
async execute(args, ctx) {
|
|
@@ -30244,15 +30389,15 @@ var structured_parse_decomposition = tool({
|
|
|
30244
30389
|
}
|
|
30245
30390
|
}
|
|
30246
30391
|
});
|
|
30247
|
-
var
|
|
30248
|
-
description: "Parse and validate bead tree response. Uses
|
|
30392
|
+
var structured_parse_cell_tree = tool({
|
|
30393
|
+
description: "Parse and validate bead tree response. Uses CellTreeSchema. Validates before creating epic with subtasks.",
|
|
30249
30394
|
args: {
|
|
30250
30395
|
response: tool.schema.string().describe("Agent response containing bead tree")
|
|
30251
30396
|
},
|
|
30252
30397
|
async execute(args, ctx) {
|
|
30253
30398
|
try {
|
|
30254
30399
|
const [extracted, method] = extractJsonFromText(args.response);
|
|
30255
|
-
const validated =
|
|
30400
|
+
const validated = CellTreeSchema.parse(extracted);
|
|
30256
30401
|
const allFiles = validated.subtasks.flatMap((s) => s.files);
|
|
30257
30402
|
const uniqueFiles = [...new Set(allFiles)];
|
|
30258
30403
|
return JSON.stringify({
|
|
@@ -30311,7 +30456,7 @@ var structuredTools = {
|
|
|
30311
30456
|
structured_validate,
|
|
30312
30457
|
structured_parse_evaluation,
|
|
30313
30458
|
structured_parse_decomposition,
|
|
30314
|
-
|
|
30459
|
+
structured_parse_cell_tree
|
|
30315
30460
|
};
|
|
30316
30461
|
|
|
30317
30462
|
// src/swarm.ts
|
|
@@ -30334,9 +30479,9 @@ var DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subta
|
|
|
30334
30479
|
|
|
30335
30480
|
After decomposition, the coordinator will:
|
|
30336
30481
|
1. Create an epic bead for the overall task
|
|
30337
|
-
2. Create child
|
|
30482
|
+
2. Create child cells for each subtask
|
|
30338
30483
|
3. Track progress through bead status updates
|
|
30339
|
-
4. Close
|
|
30484
|
+
4. Close cells with summaries when complete
|
|
30340
30485
|
|
|
30341
30486
|
Agents MUST update their bead status as they work. No silent progress.
|
|
30342
30487
|
|
|
@@ -30356,7 +30501,7 @@ Respond with a JSON object matching this schema:
|
|
|
30356
30501
|
\`\`\`typescript
|
|
30357
30502
|
{
|
|
30358
30503
|
epic: {
|
|
30359
|
-
title: string, // Epic title for the
|
|
30504
|
+
title: string, // Epic title for the hive tracker
|
|
30360
30505
|
description?: string // Brief description of the overall goal
|
|
30361
30506
|
},
|
|
30362
30507
|
subtasks: [
|
|
@@ -30407,9 +30552,9 @@ var STRATEGY_DECOMPOSITION_PROMPT = `You are decomposing a task into paralleliza
|
|
|
30407
30552
|
|
|
30408
30553
|
After decomposition, the coordinator will:
|
|
30409
30554
|
1. Create an epic bead for the overall task
|
|
30410
|
-
2. Create child
|
|
30555
|
+
2. Create child cells for each subtask
|
|
30411
30556
|
3. Track progress through bead status updates
|
|
30412
|
-
4. Close
|
|
30557
|
+
4. Close cells with summaries when complete
|
|
30413
30558
|
|
|
30414
30559
|
Agents MUST update their bead status as they work. No silent progress.
|
|
30415
30560
|
|
|
@@ -30429,7 +30574,7 @@ Respond with a JSON object matching this schema:
|
|
|
30429
30574
|
\`\`\`typescript
|
|
30430
30575
|
{
|
|
30431
30576
|
epic: {
|
|
30432
|
-
title: string, // Epic title for the
|
|
30577
|
+
title: string, // Epic title for the hive tracker
|
|
30433
30578
|
description?: string // Brief description of the overall goal
|
|
30434
30579
|
},
|
|
30435
30580
|
subtasks: [
|
|
@@ -30619,7 +30764,7 @@ ${fullContext}` : `## Additional Context
|
|
|
30619
30764
|
const prompt = DECOMPOSITION_PROMPT.replace("{task}", args.task).replace("{max_subtasks}", (args.max_subtasks ?? 5).toString()).replace("{context_section}", contextSection);
|
|
30620
30765
|
return JSON.stringify({
|
|
30621
30766
|
prompt,
|
|
30622
|
-
expected_schema: "
|
|
30767
|
+
expected_schema: "CellTree",
|
|
30623
30768
|
schema_hint: {
|
|
30624
30769
|
epic: { title: "string", description: "string?" },
|
|
30625
30770
|
subtasks: [
|
|
@@ -30632,21 +30777,21 @@ ${fullContext}` : `## Additional Context
|
|
|
30632
30777
|
}
|
|
30633
30778
|
]
|
|
30634
30779
|
},
|
|
30635
|
-
validation_note: "Parse agent response as JSON and validate with
|
|
30780
|
+
validation_note: "Parse agent response as JSON and validate with CellTreeSchema from schemas/bead.ts",
|
|
30636
30781
|
cass_history: cassResultInfo,
|
|
30637
30782
|
memory_query: formatMemoryQueryForDecomposition2(args.task, 3)
|
|
30638
30783
|
}, null, 2);
|
|
30639
30784
|
}
|
|
30640
30785
|
});
|
|
30641
30786
|
var swarm_validate_decomposition = tool({
|
|
30642
|
-
description: "Validate a decomposition response against
|
|
30787
|
+
description: "Validate a decomposition response against CellTreeSchema",
|
|
30643
30788
|
args: {
|
|
30644
|
-
response: tool.schema.string().describe("JSON response from agent (
|
|
30789
|
+
response: tool.schema.string().describe("JSON response from agent (CellTree format)")
|
|
30645
30790
|
},
|
|
30646
30791
|
async execute(args) {
|
|
30647
30792
|
try {
|
|
30648
30793
|
const parsed = JSON.parse(args.response);
|
|
30649
|
-
const validated =
|
|
30794
|
+
const validated = CellTreeSchema.parse(parsed);
|
|
30650
30795
|
const conflicts = detectFileConflicts(validated.subtasks);
|
|
30651
30796
|
if (conflicts.length > 0) {
|
|
30652
30797
|
return JSON.stringify({
|
|
@@ -30677,7 +30822,7 @@ var swarm_validate_decomposition = tool({
|
|
|
30677
30822
|
const instructionConflicts = detectInstructionConflicts(validated.subtasks);
|
|
30678
30823
|
return JSON.stringify({
|
|
30679
30824
|
valid: true,
|
|
30680
|
-
|
|
30825
|
+
cell_tree: validated,
|
|
30681
30826
|
stats: {
|
|
30682
30827
|
subtask_count: validated.subtasks.length,
|
|
30683
30828
|
total_files: new Set(validated.subtasks.flatMap((s) => s.files)).size,
|
|
@@ -30779,7 +30924,7 @@ ${args.context}` : `## Additional Context
|
|
|
30779
30924
|
const subagentInstructions = `
|
|
30780
30925
|
## CRITICAL: Output Format
|
|
30781
30926
|
|
|
30782
|
-
You are a planner subagent. Your ONLY output must be valid JSON matching the
|
|
30927
|
+
You are a planner subagent. Your ONLY output must be valid JSON matching the CellTree schema.
|
|
30783
30928
|
|
|
30784
30929
|
DO NOT include:
|
|
30785
30930
|
- Explanatory text before or after the JSON
|
|
@@ -30813,7 +30958,7 @@ OUTPUT ONLY the raw JSON object.
|
|
|
30813
30958
|
]
|
|
30814
30959
|
}
|
|
30815
30960
|
|
|
30816
|
-
Now generate the
|
|
30961
|
+
Now generate the CellTree for the given task.`;
|
|
30817
30962
|
const fullPrompt = `${planningPrompt}
|
|
30818
30963
|
|
|
30819
30964
|
${subagentInstructions}`;
|
|
@@ -30825,12 +30970,12 @@ ${subagentInstructions}`;
|
|
|
30825
30970
|
selected: selectedStrategy,
|
|
30826
30971
|
reasoning: strategyReasoning
|
|
30827
30972
|
},
|
|
30828
|
-
expected_output: "
|
|
30973
|
+
expected_output: "CellTree JSON (raw JSON, no markdown)",
|
|
30829
30974
|
next_steps: [
|
|
30830
30975
|
"1. Spawn subagent with Task tool using returned prompt",
|
|
30831
30976
|
"2. Parse subagent response as JSON",
|
|
30832
30977
|
"3. Validate with swarm_validate_decomposition",
|
|
30833
|
-
"4. Create
|
|
30978
|
+
"4. Create cells with hive_create_epic"
|
|
30834
30979
|
],
|
|
30835
30980
|
cass_history: cassResultInfo,
|
|
30836
30981
|
skills: skillsInfo,
|
|
@@ -31089,17 +31234,17 @@ var STRATEGY_DECOMPOSITION_PROMPT2 = `You are decomposing a task into paralleliz
|
|
|
31089
31234
|
|
|
31090
31235
|
{skills_context}
|
|
31091
31236
|
|
|
31092
|
-
## MANDATORY:
|
|
31237
|
+
## MANDATORY: Hive Issue Tracking
|
|
31093
31238
|
|
|
31094
|
-
**Every subtask MUST become a
|
|
31239
|
+
**Every subtask MUST become a cell.** This is non-negotiable.
|
|
31095
31240
|
|
|
31096
31241
|
After decomposition, the coordinator will:
|
|
31097
|
-
1. Create an epic
|
|
31098
|
-
2. Create child
|
|
31099
|
-
3. Track progress through
|
|
31100
|
-
4. Close
|
|
31242
|
+
1. Create an epic cell for the overall task
|
|
31243
|
+
2. Create child cells for each subtask
|
|
31244
|
+
3. Track progress through cell status updates
|
|
31245
|
+
4. Close cells with summaries when complete
|
|
31101
31246
|
|
|
31102
|
-
Agents MUST update their
|
|
31247
|
+
Agents MUST update their cell status as they work. No silent progress.
|
|
31103
31248
|
|
|
31104
31249
|
## Requirements
|
|
31105
31250
|
|
|
@@ -31117,7 +31262,7 @@ Respond with a JSON object matching this schema:
|
|
|
31117
31262
|
\`\`\`typescript
|
|
31118
31263
|
{
|
|
31119
31264
|
epic: {
|
|
31120
|
-
title: string, // Epic title for the
|
|
31265
|
+
title: string, // Epic title for the hive tracker
|
|
31121
31266
|
description?: string // Brief description of the overall goal
|
|
31122
31267
|
},
|
|
31123
31268
|
subtasks: [
|
|
@@ -31138,7 +31283,7 @@ var SUBTASK_PROMPT = `You are a swarm agent working on a subtask of a larger epi
|
|
|
31138
31283
|
|
|
31139
31284
|
## Your Identity
|
|
31140
31285
|
- **Agent Name**: {agent_name}
|
|
31141
|
-
- **
|
|
31286
|
+
- **Cell ID**: {bead_id}
|
|
31142
31287
|
- **Epic ID**: {epic_id}
|
|
31143
31288
|
|
|
31144
31289
|
## Your Subtask
|
|
@@ -31156,16 +31301,16 @@ send a message to the coordinator requesting the change.
|
|
|
31156
31301
|
## Shared Context
|
|
31157
31302
|
{shared_context}
|
|
31158
31303
|
|
|
31159
|
-
## MANDATORY:
|
|
31304
|
+
## MANDATORY: Hive Tracking
|
|
31160
31305
|
|
|
31161
|
-
You MUST keep your
|
|
31306
|
+
You MUST keep your cell updated as you work:
|
|
31162
31307
|
|
|
31163
|
-
1. **Your
|
|
31164
|
-
2. **If blocked**: \`
|
|
31165
|
-
3. **When done**: Use \`swarm_complete\` - it closes your
|
|
31166
|
-
4. **Discovered issues**: Create new
|
|
31308
|
+
1. **Your cell is already in_progress** - don't change this unless blocked
|
|
31309
|
+
2. **If blocked**: \`hive_update {bead_id} --status blocked\` and message coordinator
|
|
31310
|
+
3. **When done**: Use \`swarm_complete\` - it closes your cell automatically
|
|
31311
|
+
4. **Discovered issues**: Create new cells with \`hive_create "issue" -t bug\`
|
|
31167
31312
|
|
|
31168
|
-
**Never work silently.** Your
|
|
31313
|
+
**Never work silently.** Your cell status is how the swarm tracks progress.
|
|
31169
31314
|
|
|
31170
31315
|
## MANDATORY: Swarm Mail Communication
|
|
31171
31316
|
|
|
@@ -31188,11 +31333,11 @@ swarmmail_send(
|
|
|
31188
31333
|
|
|
31189
31334
|
## Coordination Protocol
|
|
31190
31335
|
|
|
31191
|
-
1. **Start**: Your
|
|
31336
|
+
1. **Start**: Your cell is already marked in_progress
|
|
31192
31337
|
2. **Progress**: Use swarm_progress to report status updates
|
|
31193
31338
|
3. **Blocked**: Report immediately via Swarm Mail - don't spin
|
|
31194
31339
|
4. **Complete**: Use swarm_complete when done - it handles:
|
|
31195
|
-
- Closing your
|
|
31340
|
+
- Closing your cell with a summary
|
|
31196
31341
|
- Releasing file reservations
|
|
31197
31342
|
- Notifying the coordinator
|
|
31198
31343
|
|
|
@@ -31219,7 +31364,7 @@ var SUBTASK_PROMPT_V2 = `You are a swarm agent working on: **{subtask_title}**
|
|
|
31219
31364
|
|
|
31220
31365
|
## [IDENTITY]
|
|
31221
31366
|
Agent: (assigned at spawn)
|
|
31222
|
-
|
|
31367
|
+
Cell: {bead_id}
|
|
31223
31368
|
Epic: {epic_id}
|
|
31224
31369
|
|
|
31225
31370
|
## [TASK]
|
|
@@ -31363,7 +31508,7 @@ swarm_complete(
|
|
|
31363
31508
|
- Records learning signals
|
|
31364
31509
|
- Notifies coordinator
|
|
31365
31510
|
|
|
31366
|
-
**DO NOT manually close the
|
|
31511
|
+
**DO NOT manually close the cell with hive_close.** Use swarm_complete.
|
|
31367
31512
|
|
|
31368
31513
|
## [SWARM MAIL COMMUNICATION]
|
|
31369
31514
|
|
|
@@ -31382,7 +31527,7 @@ swarmmail_send(
|
|
|
31382
31527
|
importance="high",
|
|
31383
31528
|
thread_id="{epic_id}"
|
|
31384
31529
|
)
|
|
31385
|
-
|
|
31530
|
+
hive_update(id="{bead_id}", status="blocked")
|
|
31386
31531
|
\`\`\`
|
|
31387
31532
|
|
|
31388
31533
|
### Report Issues to Other Agents
|
|
@@ -31403,15 +31548,15 @@ swarmmail_release() # Manually release reservations
|
|
|
31403
31548
|
**Note:** \`swarm_complete\` automatically releases reservations. Only use manual release if aborting work.
|
|
31404
31549
|
|
|
31405
31550
|
## [OTHER TOOLS]
|
|
31406
|
-
###
|
|
31407
|
-
You can create new
|
|
31551
|
+
### Hive - You Have Autonomy to File Issues
|
|
31552
|
+
You can create new cells against this epic when you discover:
|
|
31408
31553
|
- **Bugs**: Found a bug while working? File it.
|
|
31409
31554
|
- **Tech debt**: Spotted something that needs cleanup? File it.
|
|
31410
31555
|
- **Follow-up work**: Task needs more work than scoped? File a follow-up.
|
|
31411
31556
|
- **Dependencies**: Need something from another agent? File and link it.
|
|
31412
31557
|
|
|
31413
31558
|
\`\`\`
|
|
31414
|
-
|
|
31559
|
+
hive_create(
|
|
31415
31560
|
title="<descriptive title>",
|
|
31416
31561
|
type="bug", # or "task", "chore"
|
|
31417
31562
|
priority=2,
|
|
@@ -31422,9 +31567,9 @@ beads_create(
|
|
|
31422
31567
|
|
|
31423
31568
|
**Don't silently ignore issues.** File them so they get tracked and addressed.
|
|
31424
31569
|
|
|
31425
|
-
Other
|
|
31426
|
-
-
|
|
31427
|
-
-
|
|
31570
|
+
Other cell operations:
|
|
31571
|
+
- hive_update(id, status) - Mark blocked if stuck
|
|
31572
|
+
- hive_query(status="open") - See what else needs work
|
|
31428
31573
|
|
|
31429
31574
|
### Skills
|
|
31430
31575
|
- skills_list() - Discover available skills
|
|
@@ -31438,7 +31583,7 @@ Other bead operations:
|
|
|
31438
31583
|
2. Step 2 (semantic-memory_find) MUST happen before starting work
|
|
31439
31584
|
3. Step 4 (swarmmail_reserve) - YOU reserve files, not coordinator
|
|
31440
31585
|
4. Step 6 (swarm_progress) - Report at milestones, don't work silently
|
|
31441
|
-
5. Step 9 (swarm_complete) - Use this to close, NOT
|
|
31586
|
+
5. Step 9 (swarm_complete) - Use this to close, NOT hive_close
|
|
31442
31587
|
|
|
31443
31588
|
**If you skip these steps:**
|
|
31444
31589
|
- Your work won't be tracked (swarm_complete will fail)
|
|
@@ -31451,7 +31596,7 @@ Begin now.`;
|
|
|
31451
31596
|
var EVALUATION_PROMPT = `Evaluate the work completed for this subtask.
|
|
31452
31597
|
|
|
31453
31598
|
## Subtask
|
|
31454
|
-
**
|
|
31599
|
+
**Cell ID**: {bead_id}
|
|
31455
31600
|
**Title**: {subtask_title}
|
|
31456
31601
|
|
|
31457
31602
|
## Files Modified
|
|
@@ -31553,7 +31698,7 @@ var swarm_subtask_prompt = tool({
|
|
|
31553
31698
|
}
|
|
31554
31699
|
});
|
|
31555
31700
|
var swarm_spawn_subtask = tool({
|
|
31556
|
-
description: "Prepare a subtask for spawning. Returns prompt with Agent Mail/
|
|
31701
|
+
description: "Prepare a subtask for spawning. Returns prompt with Agent Mail/hive tracking instructions. IMPORTANT: Pass project_path for swarmmail_init.",
|
|
31557
31702
|
args: {
|
|
31558
31703
|
bead_id: tool.schema.string().describe("Subtask bead ID"),
|
|
31559
31704
|
epic_id: tool.schema.string().describe("Parent epic bead ID"),
|
|
@@ -31678,7 +31823,7 @@ ${args.context}` : `## Additional Context
|
|
|
31678
31823
|
guidelines: STRATEGIES2[selectedStrategy].guidelines,
|
|
31679
31824
|
anti_patterns: STRATEGIES2[selectedStrategy].antiPatterns
|
|
31680
31825
|
},
|
|
31681
|
-
expected_schema: "
|
|
31826
|
+
expected_schema: "CellTree",
|
|
31682
31827
|
schema_hint: {
|
|
31683
31828
|
epic: { title: "string", description: "string?" },
|
|
31684
31829
|
subtasks: [
|
|
@@ -31710,12 +31855,672 @@ init_learning();
|
|
|
31710
31855
|
import {
|
|
31711
31856
|
getSwarmInbox as getSwarmInbox2,
|
|
31712
31857
|
releaseSwarmFiles as releaseSwarmFiles2,
|
|
31713
|
-
sendSwarmMessage as
|
|
31858
|
+
sendSwarmMessage as sendSwarmMessage3,
|
|
31714
31859
|
getAgent,
|
|
31715
31860
|
createEvent as createEvent2,
|
|
31716
31861
|
appendEvent as appendEvent2
|
|
31717
31862
|
} from "swarm-mail";
|
|
31718
31863
|
init_skills();
|
|
31864
|
+
|
|
31865
|
+
// src/swarm-worktree.ts
|
|
31866
|
+
init_dist();
|
|
31867
|
+
init_zod();
|
|
31868
|
+
import { join as join6 } from "node:path";
|
|
31869
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
31870
|
+
var WORKTREE_DIR = ".swarm/worktrees";
|
|
31871
|
+
function getWorktreePath(projectPath, taskId) {
|
|
31872
|
+
const safeTaskId = taskId.replace(/[^a-zA-Z0-9.-]/g, "_");
|
|
31873
|
+
return join6(projectPath, WORKTREE_DIR, safeTaskId);
|
|
31874
|
+
}
|
|
31875
|
+
function parseTaskIdFromPath(worktreePath) {
|
|
31876
|
+
const parts = worktreePath.split("/");
|
|
31877
|
+
const worktreesIdx = parts.indexOf("worktrees");
|
|
31878
|
+
if (worktreesIdx >= 0 && worktreesIdx < parts.length - 1) {
|
|
31879
|
+
return parts[worktreesIdx + 1];
|
|
31880
|
+
}
|
|
31881
|
+
return null;
|
|
31882
|
+
}
|
|
31883
|
+
async function isGitRepo(path) {
|
|
31884
|
+
const result = await Bun.$`git -C ${path} rev-parse --git-dir`.quiet().nothrow();
|
|
31885
|
+
return result.exitCode === 0;
|
|
31886
|
+
}
|
|
31887
|
+
async function hasUncommittedChanges(path) {
|
|
31888
|
+
const result = await Bun.$`git -C ${path} status --porcelain`.quiet().nothrow();
|
|
31889
|
+
if (result.exitCode !== 0)
|
|
31890
|
+
return true;
|
|
31891
|
+
return result.stdout.toString().trim().length > 0;
|
|
31892
|
+
}
|
|
31893
|
+
async function getCurrentCommit(path) {
|
|
31894
|
+
const result = await Bun.$`git -C ${path} rev-parse HEAD`.quiet().nothrow();
|
|
31895
|
+
if (result.exitCode !== 0)
|
|
31896
|
+
return null;
|
|
31897
|
+
return result.stdout.toString().trim();
|
|
31898
|
+
}
|
|
31899
|
+
async function getWorktreeCommits(worktreePath, startCommit) {
|
|
31900
|
+
const result = await Bun.$`git -C ${worktreePath} log --format=%H ${startCommit}..HEAD`.quiet().nothrow();
|
|
31901
|
+
if (result.exitCode !== 0)
|
|
31902
|
+
return [];
|
|
31903
|
+
return result.stdout.toString().trim().split(`
|
|
31904
|
+
`).filter((c) => c.length > 0);
|
|
31905
|
+
}
|
|
31906
|
+
async function ensureWorktreeDir(projectPath) {
|
|
31907
|
+
const worktreeDir = join6(projectPath, WORKTREE_DIR);
|
|
31908
|
+
await Bun.$`mkdir -p ${worktreeDir}`.quiet().nothrow();
|
|
31909
|
+
}
|
|
31910
|
+
var swarm_worktree_create = tool({
|
|
31911
|
+
description: "Create a git worktree for isolated task execution. Worker operates in worktree, not main branch.",
|
|
31912
|
+
args: {
|
|
31913
|
+
project_path: exports_external.string().describe("Absolute path to project root"),
|
|
31914
|
+
task_id: exports_external.string().describe("Task/bead ID (e.g., bd-abc123.1)"),
|
|
31915
|
+
start_commit: exports_external.string().describe("Commit SHA to create worktree at (swarm start point)")
|
|
31916
|
+
},
|
|
31917
|
+
async execute(args) {
|
|
31918
|
+
if (!await isGitRepo(args.project_path)) {
|
|
31919
|
+
const result2 = {
|
|
31920
|
+
success: false,
|
|
31921
|
+
error: `${args.project_path} is not a git repository`
|
|
31922
|
+
};
|
|
31923
|
+
return JSON.stringify(result2, null, 2);
|
|
31924
|
+
}
|
|
31925
|
+
const worktreePath = getWorktreePath(args.project_path, args.task_id);
|
|
31926
|
+
const exists = existsSync5(worktreePath);
|
|
31927
|
+
if (exists) {
|
|
31928
|
+
const result2 = {
|
|
31929
|
+
success: false,
|
|
31930
|
+
error: `Worktree already exists for task ${args.task_id}`,
|
|
31931
|
+
worktree_path: worktreePath
|
|
31932
|
+
};
|
|
31933
|
+
return JSON.stringify(result2, null, 2);
|
|
31934
|
+
}
|
|
31935
|
+
await ensureWorktreeDir(args.project_path);
|
|
31936
|
+
const createResult = await Bun.$`git -C ${args.project_path} worktree add --detach ${worktreePath} ${args.start_commit}`.quiet().nothrow();
|
|
31937
|
+
if (createResult.exitCode !== 0) {
|
|
31938
|
+
const result2 = {
|
|
31939
|
+
success: false,
|
|
31940
|
+
error: `Failed to create worktree: ${createResult.stderr.toString()}`
|
|
31941
|
+
};
|
|
31942
|
+
return JSON.stringify(result2, null, 2);
|
|
31943
|
+
}
|
|
31944
|
+
const result = {
|
|
31945
|
+
success: true,
|
|
31946
|
+
worktree_path: worktreePath,
|
|
31947
|
+
task_id: args.task_id,
|
|
31948
|
+
created_at_commit: args.start_commit
|
|
31949
|
+
};
|
|
31950
|
+
return JSON.stringify(result, null, 2);
|
|
31951
|
+
}
|
|
31952
|
+
});
|
|
31953
|
+
var swarm_worktree_merge = tool({
|
|
31954
|
+
description: "Cherry-pick commits from worktree back to main branch. Call after worker completes.",
|
|
31955
|
+
args: {
|
|
31956
|
+
project_path: exports_external.string().describe("Absolute path to project root"),
|
|
31957
|
+
task_id: exports_external.string().describe("Task/bead ID"),
|
|
31958
|
+
start_commit: exports_external.string().optional().describe("Original start commit (to find new commits)")
|
|
31959
|
+
},
|
|
31960
|
+
async execute(args) {
|
|
31961
|
+
const worktreePath = getWorktreePath(args.project_path, args.task_id);
|
|
31962
|
+
const exists = existsSync5(worktreePath);
|
|
31963
|
+
if (!exists) {
|
|
31964
|
+
const result2 = {
|
|
31965
|
+
success: false,
|
|
31966
|
+
error: `Worktree not found for task ${args.task_id}`
|
|
31967
|
+
};
|
|
31968
|
+
return JSON.stringify(result2, null, 2);
|
|
31969
|
+
}
|
|
31970
|
+
let startCommit = args.start_commit;
|
|
31971
|
+
if (!startCommit) {
|
|
31972
|
+
const mergeBaseResult = await Bun.$`git -C ${args.project_path} merge-base HEAD ${worktreePath}`.quiet().nothrow();
|
|
31973
|
+
if (mergeBaseResult.exitCode === 0) {
|
|
31974
|
+
startCommit = mergeBaseResult.stdout.toString().trim();
|
|
31975
|
+
}
|
|
31976
|
+
}
|
|
31977
|
+
if (!startCommit) {
|
|
31978
|
+
const result2 = {
|
|
31979
|
+
success: false,
|
|
31980
|
+
error: "Could not determine start commit for cherry-pick"
|
|
31981
|
+
};
|
|
31982
|
+
return JSON.stringify(result2, null, 2);
|
|
31983
|
+
}
|
|
31984
|
+
const commits = await getWorktreeCommits(worktreePath, startCommit);
|
|
31985
|
+
if (commits.length === 0) {
|
|
31986
|
+
const result2 = {
|
|
31987
|
+
success: false,
|
|
31988
|
+
error: `Worktree has no commits since ${startCommit.slice(0, 7)}`
|
|
31989
|
+
};
|
|
31990
|
+
return JSON.stringify(result2, null, 2);
|
|
31991
|
+
}
|
|
31992
|
+
const reversedCommits = commits.reverse();
|
|
31993
|
+
let lastMergedCommit = null;
|
|
31994
|
+
for (const commit of reversedCommits) {
|
|
31995
|
+
const cherryResult = await Bun.$`git -C ${args.project_path} cherry-pick ${commit}`.quiet().nothrow();
|
|
31996
|
+
if (cherryResult.exitCode !== 0) {
|
|
31997
|
+
const stderr = cherryResult.stderr.toString();
|
|
31998
|
+
if (stderr.includes("conflict") || stderr.includes("CONFLICT")) {
|
|
31999
|
+
const statusResult = await Bun.$`git -C ${args.project_path} status --porcelain`.quiet().nothrow();
|
|
32000
|
+
const conflictingFiles = statusResult.stdout.toString().split(`
|
|
32001
|
+
`).filter((line) => line.startsWith("UU") || line.startsWith("AA")).map((line) => line.slice(3).trim());
|
|
32002
|
+
await Bun.$`git -C ${args.project_path} cherry-pick --abort`.quiet().nothrow();
|
|
32003
|
+
const result3 = {
|
|
32004
|
+
success: false,
|
|
32005
|
+
error: `Merge conflict during cherry-pick of ${commit.slice(0, 7)}`,
|
|
32006
|
+
conflicting_files: conflictingFiles
|
|
32007
|
+
};
|
|
32008
|
+
return JSON.stringify(result3, null, 2);
|
|
32009
|
+
}
|
|
32010
|
+
const result2 = {
|
|
32011
|
+
success: false,
|
|
32012
|
+
error: `Failed to cherry-pick ${commit.slice(0, 7)}: ${stderr}`
|
|
32013
|
+
};
|
|
32014
|
+
return JSON.stringify(result2, null, 2);
|
|
32015
|
+
}
|
|
32016
|
+
lastMergedCommit = commit;
|
|
32017
|
+
}
|
|
32018
|
+
const result = {
|
|
32019
|
+
success: true,
|
|
32020
|
+
task_id: args.task_id,
|
|
32021
|
+
merged_commit: lastMergedCommit || undefined
|
|
32022
|
+
};
|
|
32023
|
+
return JSON.stringify(result, null, 2);
|
|
32024
|
+
}
|
|
32025
|
+
});
|
|
32026
|
+
var swarm_worktree_cleanup = tool({
|
|
32027
|
+
description: "Remove a worktree after completion or abort. Idempotent - safe to call multiple times.",
|
|
32028
|
+
args: {
|
|
32029
|
+
project_path: exports_external.string().describe("Absolute path to project root"),
|
|
32030
|
+
task_id: exports_external.string().optional().describe("Task/bead ID to clean up"),
|
|
32031
|
+
cleanup_all: exports_external.boolean().optional().describe("Remove all worktrees for this project")
|
|
32032
|
+
},
|
|
32033
|
+
async execute(args) {
|
|
32034
|
+
if (args.cleanup_all) {
|
|
32035
|
+
const listResult = await Bun.$`git -C ${args.project_path} worktree list --porcelain`.quiet().nothrow();
|
|
32036
|
+
if (listResult.exitCode !== 0) {
|
|
32037
|
+
const result3 = {
|
|
32038
|
+
success: false,
|
|
32039
|
+
error: `Failed to list worktrees: ${listResult.stderr.toString()}`
|
|
32040
|
+
};
|
|
32041
|
+
return JSON.stringify(result3, null, 2);
|
|
32042
|
+
}
|
|
32043
|
+
const output = listResult.stdout.toString();
|
|
32044
|
+
const worktreeDir = join6(args.project_path, WORKTREE_DIR);
|
|
32045
|
+
const worktrees = output.split(`
|
|
32046
|
+
|
|
32047
|
+
`).filter((block) => block.includes(worktreeDir)).map((block) => {
|
|
32048
|
+
const pathMatch = block.match(/^worktree (.+)$/m);
|
|
32049
|
+
return pathMatch ? pathMatch[1] : null;
|
|
32050
|
+
}).filter((p) => p !== null);
|
|
32051
|
+
let removedCount = 0;
|
|
32052
|
+
for (const wt of worktrees) {
|
|
32053
|
+
const removeResult2 = await Bun.$`git -C ${args.project_path} worktree remove --force ${wt}`.quiet().nothrow();
|
|
32054
|
+
if (removeResult2.exitCode === 0) {
|
|
32055
|
+
removedCount++;
|
|
32056
|
+
}
|
|
32057
|
+
}
|
|
32058
|
+
const result2 = {
|
|
32059
|
+
success: true,
|
|
32060
|
+
removed_count: removedCount
|
|
32061
|
+
};
|
|
32062
|
+
return JSON.stringify(result2, null, 2);
|
|
32063
|
+
}
|
|
32064
|
+
if (!args.task_id) {
|
|
32065
|
+
const result2 = {
|
|
32066
|
+
success: false,
|
|
32067
|
+
error: "Either task_id or cleanup_all must be provided"
|
|
32068
|
+
};
|
|
32069
|
+
return JSON.stringify(result2, null, 2);
|
|
32070
|
+
}
|
|
32071
|
+
const worktreePath = getWorktreePath(args.project_path, args.task_id);
|
|
32072
|
+
const exists = existsSync5(worktreePath);
|
|
32073
|
+
if (!exists) {
|
|
32074
|
+
const result2 = {
|
|
32075
|
+
success: true,
|
|
32076
|
+
already_removed: true,
|
|
32077
|
+
removed_path: worktreePath
|
|
32078
|
+
};
|
|
32079
|
+
return JSON.stringify(result2, null, 2);
|
|
32080
|
+
}
|
|
32081
|
+
const removeResult = await Bun.$`git -C ${args.project_path} worktree remove --force ${worktreePath}`.quiet().nothrow();
|
|
32082
|
+
if (removeResult.exitCode !== 0) {
|
|
32083
|
+
await Bun.$`rm -rf ${worktreePath}`.quiet().nothrow();
|
|
32084
|
+
await Bun.$`git -C ${args.project_path} worktree prune`.quiet().nothrow();
|
|
32085
|
+
}
|
|
32086
|
+
const result = {
|
|
32087
|
+
success: true,
|
|
32088
|
+
removed_path: worktreePath,
|
|
32089
|
+
task_id: args.task_id
|
|
32090
|
+
};
|
|
32091
|
+
return JSON.stringify(result, null, 2);
|
|
32092
|
+
}
|
|
32093
|
+
});
|
|
32094
|
+
var swarm_worktree_list = tool({
|
|
32095
|
+
description: "List all active worktrees for a project",
|
|
32096
|
+
args: {
|
|
32097
|
+
project_path: exports_external.string().describe("Absolute path to project root")
|
|
32098
|
+
},
|
|
32099
|
+
async execute(args) {
|
|
32100
|
+
const listResult = await Bun.$`git -C ${args.project_path} worktree list --porcelain`.quiet().nothrow();
|
|
32101
|
+
if (listResult.exitCode !== 0) {
|
|
32102
|
+
return JSON.stringify({
|
|
32103
|
+
worktrees: [],
|
|
32104
|
+
count: 0,
|
|
32105
|
+
error: `Failed to list worktrees: ${listResult.stderr.toString()}`
|
|
32106
|
+
}, null, 2);
|
|
32107
|
+
}
|
|
32108
|
+
const output = listResult.stdout.toString();
|
|
32109
|
+
const worktreeDir = join6(args.project_path, WORKTREE_DIR);
|
|
32110
|
+
const worktrees = [];
|
|
32111
|
+
const blocks = output.split(`
|
|
32112
|
+
|
|
32113
|
+
`).filter((b) => b.trim());
|
|
32114
|
+
for (const block of blocks) {
|
|
32115
|
+
const pathMatch = block.match(/^worktree (.+)$/m);
|
|
32116
|
+
const commitMatch = block.match(/^HEAD ([a-f0-9]+)$/m);
|
|
32117
|
+
const branchMatch = block.match(/^branch (.+)$/m);
|
|
32118
|
+
if (pathMatch && pathMatch[1].includes(worktreeDir)) {
|
|
32119
|
+
const path = pathMatch[1];
|
|
32120
|
+
const taskId = parseTaskIdFromPath(path);
|
|
32121
|
+
if (taskId) {
|
|
32122
|
+
worktrees.push({
|
|
32123
|
+
task_id: taskId,
|
|
32124
|
+
path,
|
|
32125
|
+
commit: commitMatch ? commitMatch[1] : "unknown",
|
|
32126
|
+
branch: branchMatch ? branchMatch[1] : undefined
|
|
32127
|
+
});
|
|
32128
|
+
}
|
|
32129
|
+
}
|
|
32130
|
+
}
|
|
32131
|
+
return JSON.stringify({
|
|
32132
|
+
worktrees,
|
|
32133
|
+
count: worktrees.length
|
|
32134
|
+
}, null, 2);
|
|
32135
|
+
}
|
|
32136
|
+
});
|
|
32137
|
+
async function canUseWorktreeIsolation(projectPath) {
|
|
32138
|
+
if (!await isGitRepo(projectPath)) {
|
|
32139
|
+
return { canUse: false, reason: "Not a git repository" };
|
|
32140
|
+
}
|
|
32141
|
+
if (await hasUncommittedChanges(projectPath)) {
|
|
32142
|
+
return {
|
|
32143
|
+
canUse: false,
|
|
32144
|
+
reason: "Uncommitted changes exist - commit or stash first"
|
|
32145
|
+
};
|
|
32146
|
+
}
|
|
32147
|
+
return { canUse: true };
|
|
32148
|
+
}
|
|
32149
|
+
async function getStartCommit(projectPath) {
|
|
32150
|
+
return getCurrentCommit(projectPath);
|
|
32151
|
+
}
|
|
32152
|
+
var worktreeTools = {
|
|
32153
|
+
swarm_worktree_create,
|
|
32154
|
+
swarm_worktree_merge,
|
|
32155
|
+
swarm_worktree_cleanup,
|
|
32156
|
+
swarm_worktree_list
|
|
32157
|
+
};
|
|
32158
|
+
|
|
32159
|
+
// src/swarm-review.ts
|
|
32160
|
+
init_dist();
|
|
32161
|
+
init_zod();
|
|
32162
|
+
import { sendSwarmMessage as sendSwarmMessage2 } from "swarm-mail";
|
|
32163
|
+
var ReviewIssueSchema = exports_external.object({
|
|
32164
|
+
file: exports_external.string(),
|
|
32165
|
+
line: exports_external.number().optional(),
|
|
32166
|
+
issue: exports_external.string(),
|
|
32167
|
+
suggestion: exports_external.string().optional()
|
|
32168
|
+
});
|
|
32169
|
+
var ReviewResultSchema = exports_external.object({
|
|
32170
|
+
status: exports_external.enum(["approved", "needs_changes"]),
|
|
32171
|
+
summary: exports_external.string().optional(),
|
|
32172
|
+
issues: exports_external.array(ReviewIssueSchema).optional(),
|
|
32173
|
+
remaining_attempts: exports_external.number().optional()
|
|
32174
|
+
}).refine((data) => {
|
|
32175
|
+
if (data.status === "needs_changes") {
|
|
32176
|
+
return data.issues && data.issues.length > 0;
|
|
32177
|
+
}
|
|
32178
|
+
return true;
|
|
32179
|
+
}, {
|
|
32180
|
+
message: "issues array is required when status is 'needs_changes'"
|
|
32181
|
+
});
|
|
32182
|
+
var reviewAttempts = new Map;
|
|
32183
|
+
var MAX_REVIEW_ATTEMPTS = 3;
|
|
32184
|
+
function getAttemptCount(taskId) {
|
|
32185
|
+
return reviewAttempts.get(taskId) || 0;
|
|
32186
|
+
}
|
|
32187
|
+
function incrementAttempt(taskId) {
|
|
32188
|
+
const current = getAttemptCount(taskId);
|
|
32189
|
+
const newCount = current + 1;
|
|
32190
|
+
reviewAttempts.set(taskId, newCount);
|
|
32191
|
+
return newCount;
|
|
32192
|
+
}
|
|
32193
|
+
function clearAttempts(taskId) {
|
|
32194
|
+
reviewAttempts.delete(taskId);
|
|
32195
|
+
}
|
|
32196
|
+
function getRemainingAttempts(taskId) {
|
|
32197
|
+
return MAX_REVIEW_ATTEMPTS - getAttemptCount(taskId);
|
|
32198
|
+
}
|
|
32199
|
+
function generateReviewPrompt(context) {
|
|
32200
|
+
const sections = [];
|
|
32201
|
+
sections.push(`# Code Review: ${context.task_title}`);
|
|
32202
|
+
sections.push("");
|
|
32203
|
+
sections.push("## Epic Goal");
|
|
32204
|
+
sections.push(`**${context.epic_title}**`);
|
|
32205
|
+
if (context.epic_description) {
|
|
32206
|
+
sections.push(context.epic_description);
|
|
32207
|
+
}
|
|
32208
|
+
sections.push("");
|
|
32209
|
+
sections.push("## Task Requirements");
|
|
32210
|
+
sections.push(`**${context.task_title}**`);
|
|
32211
|
+
if (context.task_description) {
|
|
32212
|
+
sections.push(context.task_description);
|
|
32213
|
+
}
|
|
32214
|
+
sections.push("");
|
|
32215
|
+
if (context.completed_dependencies && context.completed_dependencies.length > 0) {
|
|
32216
|
+
sections.push("## This Task Builds On");
|
|
32217
|
+
for (const dep of context.completed_dependencies) {
|
|
32218
|
+
sections.push(`- **${dep.title}** (${dep.id})`);
|
|
32219
|
+
if (dep.summary) {
|
|
32220
|
+
sections.push(` ${dep.summary}`);
|
|
32221
|
+
}
|
|
32222
|
+
}
|
|
32223
|
+
sections.push("");
|
|
32224
|
+
}
|
|
32225
|
+
if (context.downstream_tasks && context.downstream_tasks.length > 0) {
|
|
32226
|
+
sections.push("## Downstream Tasks (depend on this)");
|
|
32227
|
+
for (const task of context.downstream_tasks) {
|
|
32228
|
+
sections.push(`- **${task.title}** (${task.id})`);
|
|
32229
|
+
}
|
|
32230
|
+
sections.push("");
|
|
32231
|
+
}
|
|
32232
|
+
sections.push("## Files Modified");
|
|
32233
|
+
for (const file2 of context.files_touched) {
|
|
32234
|
+
sections.push(`- \`${file2}\``);
|
|
32235
|
+
}
|
|
32236
|
+
sections.push("");
|
|
32237
|
+
sections.push("## Code Changes");
|
|
32238
|
+
sections.push("```diff");
|
|
32239
|
+
sections.push(context.diff);
|
|
32240
|
+
sections.push("```");
|
|
32241
|
+
sections.push("");
|
|
32242
|
+
sections.push("## Review Criteria");
|
|
32243
|
+
sections.push("");
|
|
32244
|
+
sections.push("Please evaluate the changes against these criteria:");
|
|
32245
|
+
sections.push("");
|
|
32246
|
+
sections.push("1. **Fulfills Requirements**: Does the code implement what the task requires?");
|
|
32247
|
+
sections.push("2. **Serves Epic Goal**: Does this work contribute to the overall epic objective?");
|
|
32248
|
+
sections.push("3. **Enables Downstream**: Can downstream tasks use this work as expected?");
|
|
32249
|
+
sections.push("4. **Type Safety**: Are types correct and complete?");
|
|
32250
|
+
sections.push("5. **No Critical Bugs**: Are there any obvious bugs or issues?");
|
|
32251
|
+
sections.push("6. **Test Coverage**: Are there tests for the new code? (warning only)");
|
|
32252
|
+
sections.push("");
|
|
32253
|
+
sections.push("## Response Format");
|
|
32254
|
+
sections.push("");
|
|
32255
|
+
sections.push("Respond with a JSON object:");
|
|
32256
|
+
sections.push("```json");
|
|
32257
|
+
sections.push(`{
|
|
32258
|
+
"status": "approved" | "needs_changes",
|
|
32259
|
+
"summary": "Brief summary of your review",
|
|
32260
|
+
"issues": [
|
|
32261
|
+
{
|
|
32262
|
+
"file": "path/to/file.ts",
|
|
32263
|
+
"line": 42,
|
|
32264
|
+
"issue": "Description of the problem",
|
|
32265
|
+
"suggestion": "How to fix it"
|
|
32266
|
+
}
|
|
32267
|
+
]
|
|
32268
|
+
}`);
|
|
32269
|
+
sections.push("```");
|
|
32270
|
+
return sections.join(`
|
|
32271
|
+
`);
|
|
32272
|
+
}
|
|
32273
|
+
async function getHiveAdapterSafe(projectPath) {
|
|
32274
|
+
try {
|
|
32275
|
+
return getHiveAdapter(projectPath);
|
|
32276
|
+
} catch {
|
|
32277
|
+
return null;
|
|
32278
|
+
}
|
|
32279
|
+
}
|
|
32280
|
+
async function getCellDependencies(adapter, projectKey, _cellId, epicId) {
|
|
32281
|
+
const completedDependencies = [];
|
|
32282
|
+
const downstreamTasks = [];
|
|
32283
|
+
try {
|
|
32284
|
+
const subtasks = await adapter.queryCells(projectKey, { parent_id: epicId });
|
|
32285
|
+
for (const subtask of subtasks) {
|
|
32286
|
+
if (subtask.id === _cellId)
|
|
32287
|
+
continue;
|
|
32288
|
+
if (subtask.status === "closed") {
|
|
32289
|
+
completedDependencies.push({
|
|
32290
|
+
id: subtask.id,
|
|
32291
|
+
title: subtask.title,
|
|
32292
|
+
summary: subtask.closed_reason ?? undefined
|
|
32293
|
+
});
|
|
32294
|
+
}
|
|
32295
|
+
if (subtask.status !== "closed") {
|
|
32296
|
+
downstreamTasks.push({
|
|
32297
|
+
id: subtask.id,
|
|
32298
|
+
title: subtask.title
|
|
32299
|
+
});
|
|
32300
|
+
}
|
|
32301
|
+
}
|
|
32302
|
+
} catch {}
|
|
32303
|
+
return { completed: completedDependencies, downstream: downstreamTasks };
|
|
32304
|
+
}
|
|
32305
|
+
var swarm_review = tool({
|
|
32306
|
+
description: "Generate a review prompt for a completed subtask. Includes epic context, dependencies, and diff.",
|
|
32307
|
+
args: {
|
|
32308
|
+
project_key: exports_external.string().describe("Project path"),
|
|
32309
|
+
epic_id: exports_external.string().describe("Epic cell ID"),
|
|
32310
|
+
task_id: exports_external.string().describe("Subtask cell ID to review"),
|
|
32311
|
+
files_touched: exports_external.array(exports_external.string()).optional().describe("Files modified (will get diff for these)")
|
|
32312
|
+
},
|
|
32313
|
+
async execute(args) {
|
|
32314
|
+
let epicTitle = args.epic_id;
|
|
32315
|
+
let epicDescription;
|
|
32316
|
+
let taskTitle = args.task_id;
|
|
32317
|
+
let taskDescription;
|
|
32318
|
+
let completedDependencies = [];
|
|
32319
|
+
let downstreamTasks = [];
|
|
32320
|
+
const adapter = await getHiveAdapterSafe(args.project_key);
|
|
32321
|
+
if (adapter) {
|
|
32322
|
+
try {
|
|
32323
|
+
const epic = await adapter.getCell(args.project_key, args.epic_id);
|
|
32324
|
+
if (epic) {
|
|
32325
|
+
epicTitle = epic.title || epicTitle;
|
|
32326
|
+
epicDescription = epic.description ?? undefined;
|
|
32327
|
+
}
|
|
32328
|
+
const task = await adapter.getCell(args.project_key, args.task_id);
|
|
32329
|
+
if (task) {
|
|
32330
|
+
taskTitle = task.title || taskTitle;
|
|
32331
|
+
taskDescription = task.description ?? undefined;
|
|
32332
|
+
}
|
|
32333
|
+
const deps = await getCellDependencies(adapter, args.project_key, args.task_id, args.epic_id);
|
|
32334
|
+
completedDependencies = deps.completed;
|
|
32335
|
+
downstreamTasks = deps.downstream;
|
|
32336
|
+
} catch {}
|
|
32337
|
+
}
|
|
32338
|
+
let diff = "";
|
|
32339
|
+
if (args.files_touched && args.files_touched.length > 0) {
|
|
32340
|
+
try {
|
|
32341
|
+
const diffResult = await Bun.$`git diff HEAD~1 -- ${args.files_touched}`.cwd(args.project_key).quiet().nothrow();
|
|
32342
|
+
if (diffResult.exitCode === 0) {
|
|
32343
|
+
diff = diffResult.stdout.toString();
|
|
32344
|
+
} else {
|
|
32345
|
+
const stagedResult = await Bun.$`git diff --cached -- ${args.files_touched}`.cwd(args.project_key).quiet().nothrow();
|
|
32346
|
+
diff = stagedResult.stdout.toString();
|
|
32347
|
+
}
|
|
32348
|
+
} catch {}
|
|
32349
|
+
}
|
|
32350
|
+
const reviewPrompt = generateReviewPrompt({
|
|
32351
|
+
epic_id: args.epic_id,
|
|
32352
|
+
epic_title: epicTitle,
|
|
32353
|
+
epic_description: epicDescription,
|
|
32354
|
+
task_id: args.task_id,
|
|
32355
|
+
task_title: taskTitle,
|
|
32356
|
+
task_description: taskDescription,
|
|
32357
|
+
files_touched: args.files_touched || [],
|
|
32358
|
+
diff: diff || "(no diff available)",
|
|
32359
|
+
completed_dependencies: completedDependencies.length > 0 ? completedDependencies : undefined,
|
|
32360
|
+
downstream_tasks: downstreamTasks.length > 0 ? downstreamTasks : undefined
|
|
32361
|
+
});
|
|
32362
|
+
return JSON.stringify({
|
|
32363
|
+
review_prompt: reviewPrompt,
|
|
32364
|
+
context: {
|
|
32365
|
+
epic_id: args.epic_id,
|
|
32366
|
+
epic_title: epicTitle,
|
|
32367
|
+
task_id: args.task_id,
|
|
32368
|
+
task_title: taskTitle,
|
|
32369
|
+
files_touched: args.files_touched || [],
|
|
32370
|
+
completed_dependencies: completedDependencies.length,
|
|
32371
|
+
downstream_tasks: downstreamTasks.length,
|
|
32372
|
+
remaining_attempts: getRemainingAttempts(args.task_id)
|
|
32373
|
+
}
|
|
32374
|
+
}, null, 2);
|
|
32375
|
+
}
|
|
32376
|
+
});
|
|
32377
|
+
var swarm_review_feedback = tool({
|
|
32378
|
+
description: "Send review feedback to a worker. Tracks attempts (max 3). Fails task after 3 rejections.",
|
|
32379
|
+
args: {
|
|
32380
|
+
project_key: exports_external.string().describe("Project path"),
|
|
32381
|
+
task_id: exports_external.string().describe("Subtask cell ID"),
|
|
32382
|
+
worker_id: exports_external.string().describe("Worker agent name"),
|
|
32383
|
+
status: exports_external.enum(["approved", "needs_changes"]).describe("Review status"),
|
|
32384
|
+
summary: exports_external.string().optional().describe("Review summary"),
|
|
32385
|
+
issues: exports_external.string().optional().describe("JSON array of ReviewIssue objects (for needs_changes)")
|
|
32386
|
+
},
|
|
32387
|
+
async execute(args) {
|
|
32388
|
+
let parsedIssues = [];
|
|
32389
|
+
if (args.issues) {
|
|
32390
|
+
try {
|
|
32391
|
+
parsedIssues = JSON.parse(args.issues);
|
|
32392
|
+
} catch {
|
|
32393
|
+
return JSON.stringify({
|
|
32394
|
+
success: false,
|
|
32395
|
+
error: "Failed to parse issues JSON"
|
|
32396
|
+
}, null, 2);
|
|
32397
|
+
}
|
|
32398
|
+
}
|
|
32399
|
+
if (args.status === "needs_changes" && parsedIssues.length === 0) {
|
|
32400
|
+
return JSON.stringify({
|
|
32401
|
+
success: false,
|
|
32402
|
+
error: "needs_changes status requires at least one issue"
|
|
32403
|
+
}, null, 2);
|
|
32404
|
+
}
|
|
32405
|
+
const epicId = args.task_id.includes(".") ? args.task_id.split(".")[0] : args.task_id;
|
|
32406
|
+
if (args.status === "approved") {
|
|
32407
|
+
markReviewApproved(args.task_id);
|
|
32408
|
+
await sendSwarmMessage2({
|
|
32409
|
+
projectPath: args.project_key,
|
|
32410
|
+
fromAgent: "coordinator",
|
|
32411
|
+
toAgents: [args.worker_id],
|
|
32412
|
+
subject: `APPROVED: ${args.task_id}`,
|
|
32413
|
+
body: `## Review Approved ✓
|
|
32414
|
+
|
|
32415
|
+
${args.summary || "Your work has been approved."}
|
|
32416
|
+
|
|
32417
|
+
You may now complete the task with \`swarm_complete\`.`,
|
|
32418
|
+
threadId: epicId,
|
|
32419
|
+
importance: "normal"
|
|
32420
|
+
});
|
|
32421
|
+
return JSON.stringify({
|
|
32422
|
+
success: true,
|
|
32423
|
+
status: "approved",
|
|
32424
|
+
task_id: args.task_id,
|
|
32425
|
+
message: "Review approved. Worker can now complete the task."
|
|
32426
|
+
}, null, 2);
|
|
32427
|
+
}
|
|
32428
|
+
const attemptNumber = incrementAttempt(args.task_id);
|
|
32429
|
+
const remaining = MAX_REVIEW_ATTEMPTS - attemptNumber;
|
|
32430
|
+
if (remaining <= 0) {
|
|
32431
|
+
const adapter = await getHiveAdapterSafe(args.project_key);
|
|
32432
|
+
if (adapter) {
|
|
32433
|
+
try {
|
|
32434
|
+
await adapter.changeCellStatus(args.project_key, args.task_id, "blocked");
|
|
32435
|
+
} catch {}
|
|
32436
|
+
}
|
|
32437
|
+
await sendSwarmMessage2({
|
|
32438
|
+
projectPath: args.project_key,
|
|
32439
|
+
fromAgent: "coordinator",
|
|
32440
|
+
toAgents: [args.worker_id],
|
|
32441
|
+
subject: `FAILED: ${args.task_id} - max review attempts reached`,
|
|
32442
|
+
body: `## Task Failed ✗
|
|
32443
|
+
|
|
32444
|
+
Maximum review attempts (${MAX_REVIEW_ATTEMPTS}) reached.
|
|
32445
|
+
|
|
32446
|
+
**Last Issues:**
|
|
32447
|
+
${parsedIssues.map((i) => `- ${i.file}${i.line ? `:${i.line}` : ""}: ${i.issue}`).join(`
|
|
32448
|
+
`)}
|
|
32449
|
+
|
|
32450
|
+
The task has been marked as blocked. A human or different approach is needed.`,
|
|
32451
|
+
threadId: epicId,
|
|
32452
|
+
importance: "urgent"
|
|
32453
|
+
});
|
|
32454
|
+
return JSON.stringify({
|
|
32455
|
+
success: true,
|
|
32456
|
+
status: "needs_changes",
|
|
32457
|
+
task_failed: true,
|
|
32458
|
+
task_id: args.task_id,
|
|
32459
|
+
attempt: attemptNumber,
|
|
32460
|
+
remaining_attempts: 0,
|
|
32461
|
+
message: `Task failed after ${MAX_REVIEW_ATTEMPTS} review attempts`
|
|
32462
|
+
}, null, 2);
|
|
32463
|
+
}
|
|
32464
|
+
const issuesList = parsedIssues.map((i) => {
|
|
32465
|
+
let line = `- **${i.file}**`;
|
|
32466
|
+
if (i.line)
|
|
32467
|
+
line += `:${i.line}`;
|
|
32468
|
+
line += `: ${i.issue}`;
|
|
32469
|
+
if (i.suggestion)
|
|
32470
|
+
line += `
|
|
32471
|
+
→ ${i.suggestion}`;
|
|
32472
|
+
return line;
|
|
32473
|
+
}).join(`
|
|
32474
|
+
`);
|
|
32475
|
+
await sendSwarmMessage2({
|
|
32476
|
+
projectPath: args.project_key,
|
|
32477
|
+
fromAgent: "coordinator",
|
|
32478
|
+
toAgents: [args.worker_id],
|
|
32479
|
+
subject: `NEEDS CHANGES: ${args.task_id} (attempt ${attemptNumber}/${MAX_REVIEW_ATTEMPTS})`,
|
|
32480
|
+
body: `## Review: Changes Needed
|
|
32481
|
+
|
|
32482
|
+
${args.summary || "Please address the following issues:"}
|
|
32483
|
+
|
|
32484
|
+
**Issues:**
|
|
32485
|
+
${issuesList}
|
|
32486
|
+
|
|
32487
|
+
**Remaining attempts:** ${remaining}
|
|
32488
|
+
|
|
32489
|
+
Please fix these issues and request another review.`,
|
|
32490
|
+
threadId: epicId,
|
|
32491
|
+
importance: "high"
|
|
32492
|
+
});
|
|
32493
|
+
return JSON.stringify({
|
|
32494
|
+
success: true,
|
|
32495
|
+
status: "needs_changes",
|
|
32496
|
+
task_id: args.task_id,
|
|
32497
|
+
attempt: attemptNumber,
|
|
32498
|
+
remaining_attempts: remaining,
|
|
32499
|
+
issues: parsedIssues,
|
|
32500
|
+
message: `Feedback sent. ${remaining} attempt(s) remaining.`
|
|
32501
|
+
}, null, 2);
|
|
32502
|
+
}
|
|
32503
|
+
});
|
|
32504
|
+
var reviewStatus = new Map;
|
|
32505
|
+
function markReviewApproved(taskId) {
|
|
32506
|
+
reviewStatus.set(taskId, { approved: true, timestamp: Date.now() });
|
|
32507
|
+
clearAttempts(taskId);
|
|
32508
|
+
}
|
|
32509
|
+
function getReviewStatus(taskId) {
|
|
32510
|
+
const status = reviewStatus.get(taskId);
|
|
32511
|
+
return {
|
|
32512
|
+
reviewed: status !== undefined,
|
|
32513
|
+
approved: status?.approved ?? false,
|
|
32514
|
+
attempt_count: getAttemptCount(taskId),
|
|
32515
|
+
remaining_attempts: getRemainingAttempts(taskId)
|
|
32516
|
+
};
|
|
32517
|
+
}
|
|
32518
|
+
var reviewTools = {
|
|
32519
|
+
swarm_review,
|
|
32520
|
+
swarm_review_feedback
|
|
32521
|
+
};
|
|
32522
|
+
|
|
32523
|
+
// src/swarm-orchestrate.ts
|
|
31719
32524
|
async function queryEpicSubtasks(epicId) {
|
|
31720
32525
|
const beadsAvailable = await isToolAvailable("beads");
|
|
31721
32526
|
if (!beadsAvailable) {
|
|
@@ -31985,7 +32790,8 @@ var globalStrikeStorage = new InMemoryStrikeStorage;
|
|
|
31985
32790
|
var swarm_init = tool({
|
|
31986
32791
|
description: "Initialize swarm session: discovers available skills, checks tool availability. ALWAYS call at swarm start.",
|
|
31987
32792
|
args: {
|
|
31988
|
-
project_path: tool.schema.string().optional().describe("Project path (for Agent Mail init)")
|
|
32793
|
+
project_path: tool.schema.string().optional().describe("Project path (for Agent Mail init)"),
|
|
32794
|
+
isolation: tool.schema.enum(["worktree", "reservation"]).optional().default("reservation").describe("Isolation mode: 'worktree' for git worktree isolation (requires clean git state), 'reservation' for file reservations (default)")
|
|
31989
32795
|
},
|
|
31990
32796
|
async execute(args) {
|
|
31991
32797
|
const availability = await checkAllTools();
|
|
@@ -32027,8 +32833,39 @@ var swarm_init = tool({
|
|
|
32027
32833
|
} else {
|
|
32028
32834
|
skillsGuidance = "No skills found. Add skills to .opencode/skills/ or .claude/skills/ for specialized guidance.";
|
|
32029
32835
|
}
|
|
32836
|
+
const isolationMode = args.isolation ?? "reservation";
|
|
32837
|
+
let isolationInfo = {
|
|
32838
|
+
mode: isolationMode,
|
|
32839
|
+
available: true
|
|
32840
|
+
};
|
|
32841
|
+
if (isolationMode === "worktree" && args.project_path) {
|
|
32842
|
+
const worktreeCheck = await canUseWorktreeIsolation(args.project_path);
|
|
32843
|
+
if (worktreeCheck.canUse) {
|
|
32844
|
+
const startCommit = await getStartCommit(args.project_path);
|
|
32845
|
+
isolationInfo = {
|
|
32846
|
+
mode: "worktree",
|
|
32847
|
+
available: true,
|
|
32848
|
+
start_commit: startCommit ?? undefined
|
|
32849
|
+
};
|
|
32850
|
+
} else {
|
|
32851
|
+
isolationInfo = {
|
|
32852
|
+
mode: "reservation",
|
|
32853
|
+
available: false,
|
|
32854
|
+
reason: `Worktree mode unavailable: ${worktreeCheck.reason}. Falling back to reservation mode.`
|
|
32855
|
+
};
|
|
32856
|
+
warnings.push(`⚠️ Worktree isolation unavailable: ${worktreeCheck.reason}. Using file reservations instead.`);
|
|
32857
|
+
}
|
|
32858
|
+
} else if (isolationMode === "worktree" && !args.project_path) {
|
|
32859
|
+
isolationInfo = {
|
|
32860
|
+
mode: "reservation",
|
|
32861
|
+
available: false,
|
|
32862
|
+
reason: "Worktree mode requires project_path. Falling back to reservation mode."
|
|
32863
|
+
};
|
|
32864
|
+
warnings.push("⚠️ Worktree isolation requires project_path. Using file reservations instead.");
|
|
32865
|
+
}
|
|
32030
32866
|
return JSON.stringify({
|
|
32031
32867
|
ready: true,
|
|
32868
|
+
isolation: isolationInfo,
|
|
32032
32869
|
tool_availability: Object.fromEntries(Array.from(availability.entries()).map(([k, v]) => [
|
|
32033
32870
|
k,
|
|
32034
32871
|
{
|
|
@@ -32042,7 +32879,8 @@ var swarm_init = tool({
|
|
|
32042
32879
|
recommendations: {
|
|
32043
32880
|
skills: skillsGuidance,
|
|
32044
32881
|
beads: beadsAvailable ? "✓ Use beads for all task tracking" : "Install beads: npm i -g @joelhooks/beads",
|
|
32045
|
-
agent_mail: agentMailAvailable2 ? "✓ Use Agent Mail for coordination" : "Start Agent Mail: agent-mail serve"
|
|
32882
|
+
agent_mail: agentMailAvailable2 ? "✓ Use Agent Mail for coordination" : "Start Agent Mail: agent-mail serve",
|
|
32883
|
+
isolation: isolationInfo.mode === "worktree" ? "✓ Using git worktree isolation" : "✓ Using file reservation isolation"
|
|
32046
32884
|
},
|
|
32047
32885
|
report
|
|
32048
32886
|
}, null, 2);
|
|
@@ -32134,7 +32972,7 @@ var swarm_progress = tool({
|
|
|
32134
32972
|
await Bun.$`bd update ${args.bead_id} --status ${beadStatus} --json`.quiet().nothrow();
|
|
32135
32973
|
}
|
|
32136
32974
|
const epicId = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
|
|
32137
|
-
await
|
|
32975
|
+
await sendSwarmMessage3({
|
|
32138
32976
|
projectPath: args.project_key,
|
|
32139
32977
|
fromAgent: args.agent_name,
|
|
32140
32978
|
toAgents: [],
|
|
@@ -32202,7 +33040,7 @@ ${args.files_affected.map((f) => `- \`${f}\``).join(`
|
|
|
32202
33040
|
].filter(Boolean).join(`
|
|
32203
33041
|
`);
|
|
32204
33042
|
const mailImportance = args.importance === "blocker" ? "urgent" : args.importance === "warning" ? "high" : "normal";
|
|
32205
|
-
await
|
|
33043
|
+
await sendSwarmMessage3({
|
|
32206
33044
|
projectPath: args.project_path,
|
|
32207
33045
|
fromAgent: args.agent_name,
|
|
32208
33046
|
toAgents: [],
|
|
@@ -32237,10 +33075,42 @@ var swarm_complete = tool({
|
|
|
32237
33075
|
planned_files: tool.schema.array(tool.schema.string()).optional().describe("Files that were originally planned to be modified"),
|
|
32238
33076
|
start_time: tool.schema.number().optional().describe("Task start timestamp (Unix ms) for duration calculation"),
|
|
32239
33077
|
error_count: tool.schema.number().optional().describe("Number of errors encountered during task"),
|
|
32240
|
-
retry_count: tool.schema.number().optional().describe("Number of retry attempts during task")
|
|
33078
|
+
retry_count: tool.schema.number().optional().describe("Number of retry attempts during task"),
|
|
33079
|
+
skip_review: tool.schema.boolean().optional().describe("Skip review gate check (default: false). Use only for tasks that don't require coordinator review.")
|
|
32241
33080
|
},
|
|
32242
33081
|
async execute(args, _ctx) {
|
|
32243
33082
|
const epicId = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
|
|
33083
|
+
if (!args.skip_review) {
|
|
33084
|
+
const reviewStatusResult = getReviewStatus(args.bead_id);
|
|
33085
|
+
if (!reviewStatusResult.approved) {
|
|
33086
|
+
if (!reviewStatusResult.reviewed) {
|
|
33087
|
+
return JSON.stringify({
|
|
33088
|
+
success: false,
|
|
33089
|
+
error: "Review required before completion",
|
|
33090
|
+
review_status: reviewStatusResult,
|
|
33091
|
+
hint: `This task requires coordinator review before completion.
|
|
33092
|
+
|
|
33093
|
+
**Next steps:**
|
|
33094
|
+
1. Request review with swarm_review(project_key="${args.project_key}", epic_id="${epicId}", task_id="${args.bead_id}", files_touched=[...])
|
|
33095
|
+
2. Wait for coordinator to review and approve with swarm_review_feedback
|
|
33096
|
+
3. Once approved, call swarm_complete again
|
|
33097
|
+
|
|
33098
|
+
Or use skip_review=true to bypass (not recommended for production work).`
|
|
33099
|
+
}, null, 2);
|
|
33100
|
+
}
|
|
33101
|
+
return JSON.stringify({
|
|
33102
|
+
success: false,
|
|
33103
|
+
error: "Review not approved",
|
|
33104
|
+
review_status: reviewStatusResult,
|
|
33105
|
+
hint: `Task was reviewed but not approved. ${reviewStatusResult.remaining_attempts} attempt(s) remaining.
|
|
33106
|
+
|
|
33107
|
+
**Next steps:**
|
|
33108
|
+
1. Address the feedback from the reviewer
|
|
33109
|
+
2. Request another review with swarm_review
|
|
33110
|
+
3. Once approved, call swarm_complete again`
|
|
33111
|
+
}, null, 2);
|
|
33112
|
+
}
|
|
33113
|
+
}
|
|
32244
33114
|
try {
|
|
32245
33115
|
const projectKey = args.project_key.replace(/\//g, "-").replace(/\\/g, "-");
|
|
32246
33116
|
let agentRegistered = false;
|
|
@@ -32335,7 +33205,7 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32335
33205
|
const isNotFoundError = stderrOutput.includes("not found") || stderrOutput.includes("does not exist");
|
|
32336
33206
|
return JSON.stringify({
|
|
32337
33207
|
success: false,
|
|
32338
|
-
error: "Failed to close
|
|
33208
|
+
error: "Failed to close cell",
|
|
32339
33209
|
failed_step: "bd close",
|
|
32340
33210
|
details: stderrOutput || stdoutOutput || "Unknown error from bd close command",
|
|
32341
33211
|
bead_id: args.bead_id,
|
|
@@ -32344,15 +33214,15 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32344
33214
|
steps: isNoDatabaseError ? [
|
|
32345
33215
|
`1. Verify project_key is correct: "${args.project_key}"`,
|
|
32346
33216
|
`2. Check .beads/ exists in that directory`,
|
|
32347
|
-
`3.
|
|
32348
|
-
`4. Try:
|
|
33217
|
+
`3. Cell ID prefix "${args.bead_id.split("-")[0]}" should match project`,
|
|
33218
|
+
`4. Try: hive_close(id="${args.bead_id}", reason="...")`
|
|
32349
33219
|
] : [
|
|
32350
|
-
`1. Check
|
|
32351
|
-
`2. Check
|
|
32352
|
-
`3. If
|
|
32353
|
-
`4. Try closing directly:
|
|
33220
|
+
`1. Check cell exists: bd show ${args.bead_id}`,
|
|
33221
|
+
`2. Check cell status (might already be closed): hive_query()`,
|
|
33222
|
+
`3. If cell is blocked, unblock first: hive_update(id="${args.bead_id}", status="in_progress")`,
|
|
33223
|
+
`4. Try closing directly: hive_close(id="${args.bead_id}", reason="...")`
|
|
32354
33224
|
],
|
|
32355
|
-
hint: isNoDatabaseError ? `The project_key "${args.project_key}" doesn't have a .beads/ directory. Make sure you're using the correct project path.` : isNotFoundError ? `
|
|
33225
|
+
hint: isNoDatabaseError ? `The project_key "${args.project_key}" doesn't have a .beads/ directory. Make sure you're using the correct project path.` : isNotFoundError ? `Cell "${args.bead_id}" not found. It may have been closed already or the ID is incorrect.` : "If cell is in 'blocked' status, you must change it to 'in_progress' or 'open' before closing."
|
|
32356
33226
|
}
|
|
32357
33227
|
}, null, 2);
|
|
32358
33228
|
}
|
|
@@ -32420,7 +33290,7 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32420
33290
|
let messageSent = false;
|
|
32421
33291
|
let messageError;
|
|
32422
33292
|
try {
|
|
32423
|
-
await
|
|
33293
|
+
await sendSwarmMessage3({
|
|
32424
33294
|
projectPath: args.project_key,
|
|
32425
33295
|
fromAgent: args.agent_name,
|
|
32426
33296
|
toAgents: [],
|
|
@@ -32530,14 +33400,14 @@ ${errorStack.slice(0, 1000)}
|
|
|
32530
33400
|
"",
|
|
32531
33401
|
`### Recovery Actions`,
|
|
32532
33402
|
"1. Check error message for specific issue",
|
|
32533
|
-
"2. Review failed step (UBS scan, typecheck,
|
|
33403
|
+
"2. Review failed step (UBS scan, typecheck, cell close, etc.)",
|
|
32534
33404
|
"3. Fix underlying issue or use skip flags if appropriate",
|
|
32535
33405
|
"4. Retry swarm_complete after fixing"
|
|
32536
33406
|
].filter(Boolean).join(`
|
|
32537
33407
|
`);
|
|
32538
33408
|
let notificationSent = false;
|
|
32539
33409
|
try {
|
|
32540
|
-
await
|
|
33410
|
+
await sendSwarmMessage3({
|
|
32541
33411
|
projectPath: args.project_key,
|
|
32542
33412
|
fromAgent: args.agent_name,
|
|
32543
33413
|
toAgents: [],
|
|
@@ -32575,7 +33445,7 @@ ${errorStack.slice(0, 1000)}
|
|
|
32575
33445
|
common_fixes: {
|
|
32576
33446
|
"Verification Gate": "Use skip_verification=true to bypass (not recommended)",
|
|
32577
33447
|
"UBS scan": "Use skip_ubs_scan=true to bypass",
|
|
32578
|
-
"
|
|
33448
|
+
"Cell close": "Check cell status with hive_query(), may need hive_update() first",
|
|
32579
33449
|
"Self-evaluation": "Check evaluation JSON format matches EvaluationSchema"
|
|
32580
33450
|
}
|
|
32581
33451
|
}
|
|
@@ -32674,7 +33544,7 @@ var swarm_record_outcome = tool({
|
|
|
32674
33544
|
var swarm_accumulate_error = tool({
|
|
32675
33545
|
description: "Record an error during subtask execution. Errors feed into retry prompts.",
|
|
32676
33546
|
args: {
|
|
32677
|
-
bead_id: tool.schema.string().describe("
|
|
33547
|
+
bead_id: tool.schema.string().describe("Cell ID where error occurred"),
|
|
32678
33548
|
error_type: tool.schema.enum(["validation", "timeout", "conflict", "tool_failure", "unknown"]).describe("Category of error"),
|
|
32679
33549
|
message: tool.schema.string().describe("Human-readable error message"),
|
|
32680
33550
|
stack_trace: tool.schema.string().optional().describe("Stack trace for debugging"),
|
|
@@ -32701,7 +33571,7 @@ var swarm_accumulate_error = tool({
|
|
|
32701
33571
|
var swarm_get_error_context = tool({
|
|
32702
33572
|
description: "Get accumulated errors for a bead. Returns formatted context for retry prompts.",
|
|
32703
33573
|
args: {
|
|
32704
|
-
bead_id: tool.schema.string().describe("
|
|
33574
|
+
bead_id: tool.schema.string().describe("Cell ID to get errors for"),
|
|
32705
33575
|
include_resolved: tool.schema.boolean().optional().describe("Include resolved errors (default: false)")
|
|
32706
33576
|
},
|
|
32707
33577
|
async execute(args) {
|
|
@@ -32737,7 +33607,7 @@ var swarm_resolve_error = tool({
|
|
|
32737
33607
|
var swarm_check_strikes = tool({
|
|
32738
33608
|
description: "Check 3-strike status for a bead. Records failures, detects architectural problems, generates architecture review prompts.",
|
|
32739
33609
|
args: {
|
|
32740
|
-
bead_id: tool.schema.string().describe("
|
|
33610
|
+
bead_id: tool.schema.string().describe("Cell ID to check"),
|
|
32741
33611
|
action: tool.schema.enum(["check", "add_strike", "clear", "get_prompt"]).describe("Action: check count, add strike, clear strikes, or get prompt"),
|
|
32742
33612
|
attempt: tool.schema.string().optional().describe("Description of fix attempt (required for add_strike)"),
|
|
32743
33613
|
reason: tool.schema.string().optional().describe("Why the fix failed (required for add_strike)")
|
|
@@ -33002,7 +33872,7 @@ ${args.files_context.map((f) => `- \`${f}\``).join(`
|
|
|
33002
33872
|
*Learned from swarm execution on ${new Date().toISOString().split("T")[0]}*`;
|
|
33003
33873
|
const { getSkill: getSkill2, invalidateSkillsCache: invalidateSkillsCache2 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
|
|
33004
33874
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("node:fs/promises");
|
|
33005
|
-
const { join:
|
|
33875
|
+
const { join: join7 } = await import("node:path");
|
|
33006
33876
|
const existing = await getSkill2(args.skill_name);
|
|
33007
33877
|
if (existing) {
|
|
33008
33878
|
return JSON.stringify({
|
|
@@ -33013,8 +33883,8 @@ ${args.files_context.map((f) => `- \`${f}\``).join(`
|
|
|
33013
33883
|
suggestion: "Use skills_update to add to existing skill, or choose a different name"
|
|
33014
33884
|
}, null, 2);
|
|
33015
33885
|
}
|
|
33016
|
-
const skillDir =
|
|
33017
|
-
const skillPath =
|
|
33886
|
+
const skillDir = join7(process.cwd(), ".opencode", "skills", args.skill_name);
|
|
33887
|
+
const skillPath = join7(skillDir, "SKILL.md");
|
|
33018
33888
|
const frontmatter = [
|
|
33019
33889
|
"---",
|
|
33020
33890
|
`name: ${args.skill_name}`,
|
|
@@ -34184,14 +35054,14 @@ var DEFAULT_GUARDRAIL_CONFIG = {
|
|
|
34184
35054
|
cass_stats: 8000
|
|
34185
35055
|
},
|
|
34186
35056
|
skipTools: [
|
|
34187
|
-
"
|
|
34188
|
-
"
|
|
34189
|
-
"
|
|
34190
|
-
"
|
|
34191
|
-
"
|
|
34192
|
-
"
|
|
34193
|
-
"
|
|
34194
|
-
"
|
|
35057
|
+
"hive_create",
|
|
35058
|
+
"hive_create_epic",
|
|
35059
|
+
"hive_query",
|
|
35060
|
+
"hive_update",
|
|
35061
|
+
"hive_close",
|
|
35062
|
+
"hive_start",
|
|
35063
|
+
"hive_ready",
|
|
35064
|
+
"hive_sync",
|
|
34195
35065
|
"agentmail_init",
|
|
34196
35066
|
"agentmail_send",
|
|
34197
35067
|
"agentmail_inbox",
|
|
@@ -34211,7 +35081,7 @@ var DEFAULT_GUARDRAIL_CONFIG = {
|
|
|
34211
35081
|
"structured_validate",
|
|
34212
35082
|
"structured_parse_evaluation",
|
|
34213
35083
|
"structured_parse_decomposition",
|
|
34214
|
-
"
|
|
35084
|
+
"structured_parse_cell_tree",
|
|
34215
35085
|
"swarm_select_strategy",
|
|
34216
35086
|
"swarm_plan_prompt",
|
|
34217
35087
|
"swarm_decompose",
|
|
@@ -34395,7 +35265,7 @@ function analyzeTodoWrite(args) {
|
|
|
34395
35265
|
warning: `⚠️ This looks like a multi-file implementation plan (${fileModificationCount}/${todos.length} items are file modifications).
|
|
34396
35266
|
|
|
34397
35267
|
Consider using swarm instead:
|
|
34398
|
-
swarm_decompose →
|
|
35268
|
+
swarm_decompose → hive_create_epic → parallel task spawns
|
|
34399
35269
|
|
|
34400
35270
|
TodoWrite is for tracking progress, not parallelizable implementation work.
|
|
34401
35271
|
Swarm workers can complete these ${fileModificationCount} tasks in parallel.
|
|
@@ -34876,9 +35746,88 @@ async function resetStorage() {
|
|
|
34876
35746
|
|
|
34877
35747
|
// src/index.ts
|
|
34878
35748
|
init_skills();
|
|
35749
|
+
|
|
35750
|
+
// src/compaction-hook.ts
|
|
35751
|
+
var SWARM_COMPACTION_CONTEXT = `## \uD83D\uDC1D SWARM ACTIVE - Keep Cooking
|
|
35752
|
+
|
|
35753
|
+
You are the **COORDINATOR** of an active swarm. Context was compacted but the swarm is still running.
|
|
35754
|
+
|
|
35755
|
+
**YOUR JOB:** Keep orchestrating. Spawn agents. Monitor progress. Unblock work. Ship it.
|
|
35756
|
+
|
|
35757
|
+
### Preserve in Summary
|
|
35758
|
+
|
|
35759
|
+
Extract from session context:
|
|
35760
|
+
|
|
35761
|
+
1. **Epic & Subtasks** - IDs, titles, status, file assignments
|
|
35762
|
+
2. **What's Running** - Which agents are active, what they're working on
|
|
35763
|
+
3. **What's Blocked** - Blockers and what's needed to unblock
|
|
35764
|
+
4. **What's Done** - Completed work and any follow-ups needed
|
|
35765
|
+
5. **What's Next** - Pending subtasks ready to spawn
|
|
35766
|
+
|
|
35767
|
+
### Summary Format
|
|
35768
|
+
|
|
35769
|
+
\`\`\`
|
|
35770
|
+
## \uD83D\uDC1D Swarm State
|
|
35771
|
+
|
|
35772
|
+
**Epic:** <bd-xxx> - <title>
|
|
35773
|
+
**Project:** <path>
|
|
35774
|
+
**Progress:** X/Y subtasks complete
|
|
35775
|
+
|
|
35776
|
+
**Active:**
|
|
35777
|
+
- <bd-xxx>: <title> [in_progress] → <agent> working on <files>
|
|
35778
|
+
|
|
35779
|
+
**Blocked:**
|
|
35780
|
+
- <bd-xxx>: <title> - BLOCKED: <reason>
|
|
35781
|
+
|
|
35782
|
+
**Completed:**
|
|
35783
|
+
- <bd-xxx>: <title> ✓
|
|
35784
|
+
|
|
35785
|
+
**Ready to Spawn:**
|
|
35786
|
+
- <bd-xxx>: <title> (files: <...>)
|
|
35787
|
+
\`\`\`
|
|
35788
|
+
|
|
35789
|
+
### On Resume - IMMEDIATELY
|
|
35790
|
+
|
|
35791
|
+
1. \`swarm_status(epic_id="<epic>", project_key="<path>")\` - Get current state
|
|
35792
|
+
2. \`swarmmail_inbox(limit=5)\` - Check for agent messages
|
|
35793
|
+
3. **Spawn ready subtasks** - Don't wait, fire them off
|
|
35794
|
+
4. **Unblock blocked work** - Resolve dependencies, reassign if needed
|
|
35795
|
+
5. **Collect completed work** - Close done subtasks, verify quality
|
|
35796
|
+
|
|
35797
|
+
### Keep the Swarm Cooking
|
|
35798
|
+
|
|
35799
|
+
- **Spawn aggressively** - If a subtask is ready and unblocked, spawn an agent
|
|
35800
|
+
- **Monitor actively** - Check status, read messages, respond to blockers
|
|
35801
|
+
- **Close the loop** - When all subtasks done, verify and close the epic
|
|
35802
|
+
- **Don't stop** - The swarm runs until the epic is closed
|
|
35803
|
+
|
|
35804
|
+
**You are not waiting for instructions. You are the coordinator. Coordinate.**
|
|
35805
|
+
`;
|
|
35806
|
+
async function hasSwarmSign() {
|
|
35807
|
+
try {
|
|
35808
|
+
const projectKey = getHiveWorkingDirectory();
|
|
35809
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
35810
|
+
const cells = await adapter.queryCells(projectKey, {});
|
|
35811
|
+
if (!Array.isArray(cells))
|
|
35812
|
+
return false;
|
|
35813
|
+
return cells.some((c) => c.status === "in_progress" || c.status === "open" && c.parent_id || c.type === "epic" && c.status !== "closed");
|
|
35814
|
+
} catch {
|
|
35815
|
+
return false;
|
|
35816
|
+
}
|
|
35817
|
+
}
|
|
35818
|
+
function createCompactionHook() {
|
|
35819
|
+
return async (_input, output) => {
|
|
35820
|
+
const hasSign = await hasSwarmSign();
|
|
35821
|
+
if (hasSign) {
|
|
35822
|
+
output.context.push(SWARM_COMPACTION_CONTEXT);
|
|
35823
|
+
}
|
|
35824
|
+
};
|
|
35825
|
+
}
|
|
35826
|
+
|
|
35827
|
+
// src/index.ts
|
|
34879
35828
|
var SwarmPlugin = async (input) => {
|
|
34880
35829
|
const { $, directory } = input;
|
|
34881
|
-
|
|
35830
|
+
setHiveWorkingDirectory(directory);
|
|
34882
35831
|
setSkillsProjectDirectory(directory);
|
|
34883
35832
|
setAgentMailProjectDirectory(directory);
|
|
34884
35833
|
setSwarmMailProjectDirectory(directory);
|
|
@@ -34913,10 +35862,12 @@ var SwarmPlugin = async (input) => {
|
|
|
34913
35862
|
}
|
|
34914
35863
|
return {
|
|
34915
35864
|
tool: {
|
|
34916
|
-
...
|
|
35865
|
+
...hiveTools,
|
|
34917
35866
|
...swarmMailTools,
|
|
34918
35867
|
...structuredTools,
|
|
34919
35868
|
...swarmTools,
|
|
35869
|
+
...worktreeTools,
|
|
35870
|
+
...reviewTools,
|
|
34920
35871
|
...repoCrawlTools,
|
|
34921
35872
|
...skillsTools,
|
|
34922
35873
|
...mandateTools
|
|
@@ -34965,7 +35916,7 @@ var SwarmPlugin = async (input) => {
|
|
|
34965
35916
|
if (toolName === "swarm_complete" && activeAgentMailState) {
|
|
34966
35917
|
await releaseReservations();
|
|
34967
35918
|
}
|
|
34968
|
-
if (toolName === "
|
|
35919
|
+
if (toolName === "hive_close" || toolName === "hive_close") {
|
|
34969
35920
|
$`bd sync`.quiet().nothrow();
|
|
34970
35921
|
}
|
|
34971
35922
|
}
|
|
@@ -34973,10 +35924,12 @@ var SwarmPlugin = async (input) => {
|
|
|
34973
35924
|
};
|
|
34974
35925
|
var src_default = SwarmPlugin;
|
|
34975
35926
|
var allTools = {
|
|
34976
|
-
...
|
|
35927
|
+
...hiveTools,
|
|
34977
35928
|
...swarmMailTools,
|
|
34978
35929
|
...structuredTools,
|
|
34979
35930
|
...swarmTools,
|
|
35931
|
+
...worktreeTools,
|
|
35932
|
+
...reviewTools,
|
|
34980
35933
|
...repoCrawlTools,
|
|
34981
35934
|
...skillsTools,
|
|
34982
35935
|
...mandateTools
|
|
@@ -34996,6 +35949,7 @@ export {
|
|
|
34996
35949
|
setStorage,
|
|
34997
35950
|
setSkillsProjectDirectory,
|
|
34998
35951
|
setMandateStorage,
|
|
35952
|
+
setHiveWorkingDirectory,
|
|
34999
35953
|
setBeadsWorkingDirectory,
|
|
35000
35954
|
setAgentMailProjectDirectory,
|
|
35001
35955
|
selectStrategy,
|
|
@@ -35014,11 +35968,22 @@ export {
|
|
|
35014
35968
|
isSemanticMemoryAvailable,
|
|
35015
35969
|
isProjectNotFoundError,
|
|
35016
35970
|
isEpicEvent,
|
|
35971
|
+
isCellEventType,
|
|
35017
35972
|
isBeadEventType,
|
|
35018
35973
|
isAgentNotFoundError,
|
|
35019
35974
|
isAgentEvent,
|
|
35020
35975
|
invalidateSkillsCache,
|
|
35021
35976
|
ifToolAvailable,
|
|
35977
|
+
hive_update,
|
|
35978
|
+
hive_sync,
|
|
35979
|
+
hive_start,
|
|
35980
|
+
hive_ready,
|
|
35981
|
+
hive_query,
|
|
35982
|
+
hive_link_thread,
|
|
35983
|
+
hive_create_epic,
|
|
35984
|
+
hive_create,
|
|
35985
|
+
hive_close,
|
|
35986
|
+
hiveTools,
|
|
35022
35987
|
guardrailOutput,
|
|
35023
35988
|
groupByTransition,
|
|
35024
35989
|
getToolAvailability,
|
|
@@ -35029,6 +35994,9 @@ export {
|
|
|
35029
35994
|
getSkill,
|
|
35030
35995
|
getSchemaByName,
|
|
35031
35996
|
getMandateStorage,
|
|
35997
|
+
getHiveWorkingDirectory,
|
|
35998
|
+
getHiveAdapter,
|
|
35999
|
+
getCellIdFromEvent,
|
|
35032
36000
|
getBeadsWorkingDirectory,
|
|
35033
36001
|
getBeadsAdapter,
|
|
35034
36002
|
getBeadIdFromEvent,
|
|
@@ -35050,6 +36018,8 @@ export {
|
|
|
35050
36018
|
createStorage,
|
|
35051
36019
|
createMetrics,
|
|
35052
36020
|
createMandateStorage,
|
|
36021
|
+
createCompactionHook,
|
|
36022
|
+
createCellEvent,
|
|
35053
36023
|
createBeadEvent,
|
|
35054
36024
|
createAgentMailError,
|
|
35055
36025
|
clearSessionState,
|
|
@@ -35089,6 +36059,7 @@ export {
|
|
|
35089
36059
|
SemanticMemoryStorage,
|
|
35090
36060
|
SemanticMemoryMandateStorage,
|
|
35091
36061
|
ScoreCalculationResultSchema,
|
|
36062
|
+
SWARM_COMPACTION_CONTEXT,
|
|
35092
36063
|
SUBTASK_PROMPT_V2,
|
|
35093
36064
|
STRATEGIES,
|
|
35094
36065
|
RepoCrawlError,
|
|
@@ -35101,6 +36072,8 @@ export {
|
|
|
35101
36072
|
MandateContentTypeSchema,
|
|
35102
36073
|
InMemoryStorage,
|
|
35103
36074
|
InMemoryMandateStorage,
|
|
36075
|
+
HiveValidationError,
|
|
36076
|
+
HiveError,
|
|
35104
36077
|
FileReservationConflictError,
|
|
35105
36078
|
EvaluationSchema,
|
|
35106
36079
|
EvaluationRequestSchema,
|
|
@@ -35119,6 +36092,35 @@ export {
|
|
|
35119
36092
|
CriterionEvaluationSchema,
|
|
35120
36093
|
CreateSwarmContextArgsSchema,
|
|
35121
36094
|
CreateMandateArgsSchema,
|
|
36095
|
+
CellWorkStartedEventSchema,
|
|
36096
|
+
CellUpdatedEventSchema,
|
|
36097
|
+
CellUpdateArgsSchema,
|
|
36098
|
+
CellTypeSchema,
|
|
36099
|
+
CellTreeSchema,
|
|
36100
|
+
CellStatusSchema,
|
|
36101
|
+
CellStatusChangedEventSchema,
|
|
36102
|
+
CellSchema,
|
|
36103
|
+
CellReopenedEventSchema,
|
|
36104
|
+
CellQueryArgsSchema,
|
|
36105
|
+
CellLabelRemovedEventSchema,
|
|
36106
|
+
CellLabelAddedEventSchema,
|
|
36107
|
+
CellEventSchema,
|
|
36108
|
+
CellEpicClosureEligibleEventSchema,
|
|
36109
|
+
CellEpicChildRemovedEventSchema,
|
|
36110
|
+
CellEpicChildAddedEventSchema,
|
|
36111
|
+
CellDependencySchema,
|
|
36112
|
+
CellDependencyRemovedEventSchema,
|
|
36113
|
+
CellDependencyAddedEventSchema,
|
|
36114
|
+
CellDeletedEventSchema,
|
|
36115
|
+
CellCreatedEventSchema,
|
|
36116
|
+
CellCreateArgsSchema,
|
|
36117
|
+
CellCompactedEventSchema,
|
|
36118
|
+
CellCommentUpdatedEventSchema,
|
|
36119
|
+
CellCommentDeletedEventSchema,
|
|
36120
|
+
CellCommentAddedEventSchema,
|
|
36121
|
+
CellClosedEventSchema,
|
|
36122
|
+
CellCloseArgsSchema,
|
|
36123
|
+
CellAssignedEventSchema,
|
|
35122
36124
|
CastVoteArgsSchema,
|
|
35123
36125
|
BeadWorkStartedEventSchema,
|
|
35124
36126
|
BeadValidationError,
|
|
@@ -35151,6 +36153,7 @@ export {
|
|
|
35151
36153
|
BeadClosedEventSchema,
|
|
35152
36154
|
BeadCloseArgsSchema,
|
|
35153
36155
|
BeadAssignedEventSchema,
|
|
36156
|
+
BaseCellEventSchema,
|
|
35154
36157
|
BaseBeadEventSchema,
|
|
35155
36158
|
AgentProgressSchema,
|
|
35156
36159
|
AgentMailNotInitializedError,
|