opencode-swarm-plugin 0.48.1 → 0.49.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/README.md +10 -7
- package/bin/swarm-setup-consolidate.test.ts +84 -0
- package/bin/swarm.test.ts +170 -0
- package/bin/swarm.ts +300 -2
- package/bin/test-setup-manual.md +67 -0
- package/dist/bin/swarm.js +1035 -184
- package/dist/coordinator-guard.d.ts +79 -0
- package/dist/coordinator-guard.d.ts.map +1 -0
- package/dist/examples/plugin-wrapper-template.ts +13 -2
- package/dist/hive.d.ts.map +1 -1
- package/dist/hive.js +5 -4
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +376 -16
- package/dist/memory.d.ts.map +1 -1
- package/dist/plugin.js +373 -16
- package/dist/query-tools.d.ts +5 -0
- package/dist/query-tools.d.ts.map +1 -1
- package/dist/schemas/cell.d.ts +12 -0
- package/dist/schemas/cell.d.ts.map +1 -1
- package/dist/swarm-insights.d.ts +158 -0
- package/dist/swarm-insights.d.ts.map +1 -1
- package/dist/swarm-orchestrate.d.ts +4 -4
- package/dist/swarm-prompts.d.ts +1 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm-prompts.js +335 -16
- package/dist/swarm-strategies.d.ts +1 -1
- package/dist/swarm.d.ts +2 -2
- package/examples/plugin-wrapper-template.ts +13 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -27872,11 +27872,16 @@ echo "Project directory: $1"
|
|
|
27872
27872
|
// src/swarm-insights.ts
|
|
27873
27873
|
var exports_swarm_insights = {};
|
|
27874
27874
|
__export(exports_swarm_insights, {
|
|
27875
|
+
trackCoordinatorViolation: () => trackCoordinatorViolation,
|
|
27876
|
+
getViolationAnalytics: () => getViolationAnalytics,
|
|
27875
27877
|
getStrategyInsights: () => getStrategyInsights,
|
|
27878
|
+
getRejectionAnalytics: () => getRejectionAnalytics,
|
|
27876
27879
|
getPatternInsights: () => getPatternInsights,
|
|
27877
27880
|
getFileInsights: () => getFileInsights,
|
|
27881
|
+
getFileFailureHistory: () => getFileFailureHistory,
|
|
27878
27882
|
getCachedInsights: () => getCachedInsights,
|
|
27879
27883
|
formatInsightsForPrompt: () => formatInsightsForPrompt,
|
|
27884
|
+
formatFileHistoryWarnings: () => formatFileHistoryWarnings,
|
|
27880
27885
|
clearInsightsCache: () => clearInsightsCache
|
|
27881
27886
|
});
|
|
27882
27887
|
async function getStrategyInsights(swarmMail, _task) {
|
|
@@ -27948,6 +27953,136 @@ async function getFileInsights(swarmMail, files) {
|
|
|
27948
27953
|
async function getFileGotchas(_swarmMail, _file2) {
|
|
27949
27954
|
return [];
|
|
27950
27955
|
}
|
|
27956
|
+
async function getFileFailureHistory(swarmMail, files) {
|
|
27957
|
+
if (files.length === 0)
|
|
27958
|
+
return [];
|
|
27959
|
+
const db = await swarmMail.getDatabase();
|
|
27960
|
+
const histories = [];
|
|
27961
|
+
for (const file2 of files) {
|
|
27962
|
+
const query = `
|
|
27963
|
+
SELECT data
|
|
27964
|
+
FROM events
|
|
27965
|
+
WHERE type = 'review_feedback'
|
|
27966
|
+
AND json_extract(data, '$.status') = 'needs_changes'
|
|
27967
|
+
AND json_extract(data, '$.issues') LIKE ?
|
|
27968
|
+
`;
|
|
27969
|
+
const result = await db.query(query, [`%${file2}%`]);
|
|
27970
|
+
if (!result.rows || result.rows.length === 0) {
|
|
27971
|
+
continue;
|
|
27972
|
+
}
|
|
27973
|
+
const issueTexts = [];
|
|
27974
|
+
for (const row of result.rows) {
|
|
27975
|
+
try {
|
|
27976
|
+
const data = JSON.parse(row.data);
|
|
27977
|
+
const issuesStr = data.issues;
|
|
27978
|
+
if (!issuesStr)
|
|
27979
|
+
continue;
|
|
27980
|
+
const issues = JSON.parse(issuesStr);
|
|
27981
|
+
for (const issue2 of issues) {
|
|
27982
|
+
if (issue2.file === file2) {
|
|
27983
|
+
issueTexts.push(issue2.issue);
|
|
27984
|
+
}
|
|
27985
|
+
}
|
|
27986
|
+
} catch (e) {
|
|
27987
|
+
continue;
|
|
27988
|
+
}
|
|
27989
|
+
}
|
|
27990
|
+
if (issueTexts.length === 0) {
|
|
27991
|
+
continue;
|
|
27992
|
+
}
|
|
27993
|
+
const issueCounts = new Map;
|
|
27994
|
+
for (const text of issueTexts) {
|
|
27995
|
+
issueCounts.set(text, (issueCounts.get(text) || 0) + 1);
|
|
27996
|
+
}
|
|
27997
|
+
const topIssues = Array.from(issueCounts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([text]) => text);
|
|
27998
|
+
histories.push({
|
|
27999
|
+
file: file2,
|
|
28000
|
+
rejectionCount: issueTexts.length,
|
|
28001
|
+
topIssues
|
|
28002
|
+
});
|
|
28003
|
+
}
|
|
28004
|
+
return histories;
|
|
28005
|
+
}
|
|
28006
|
+
async function getRejectionAnalytics(swarmMail) {
|
|
28007
|
+
const db = await swarmMail.getDatabase();
|
|
28008
|
+
const query = `
|
|
28009
|
+
SELECT data
|
|
28010
|
+
FROM events
|
|
28011
|
+
WHERE type = 'review_feedback'
|
|
28012
|
+
ORDER BY timestamp DESC
|
|
28013
|
+
`;
|
|
28014
|
+
const result = await db.query(query, []);
|
|
28015
|
+
if (!result.rows || result.rows.length === 0) {
|
|
28016
|
+
return {
|
|
28017
|
+
totalReviews: 0,
|
|
28018
|
+
approved: 0,
|
|
28019
|
+
rejected: 0,
|
|
28020
|
+
approvalRate: 0,
|
|
28021
|
+
topReasons: []
|
|
28022
|
+
};
|
|
28023
|
+
}
|
|
28024
|
+
let approved = 0;
|
|
28025
|
+
let rejected = 0;
|
|
28026
|
+
const reasonCounts = new Map;
|
|
28027
|
+
for (const row of result.rows) {
|
|
28028
|
+
try {
|
|
28029
|
+
const data = JSON.parse(row.data);
|
|
28030
|
+
if (data.status === "approved") {
|
|
28031
|
+
approved++;
|
|
28032
|
+
} else if (data.status === "needs_changes") {
|
|
28033
|
+
rejected++;
|
|
28034
|
+
if (data.issues) {
|
|
28035
|
+
const issues = JSON.parse(data.issues);
|
|
28036
|
+
for (const issue2 of issues) {
|
|
28037
|
+
const category = categorizeRejectionReason(issue2.issue);
|
|
28038
|
+
reasonCounts.set(category, (reasonCounts.get(category) || 0) + 1);
|
|
28039
|
+
}
|
|
28040
|
+
}
|
|
28041
|
+
}
|
|
28042
|
+
} catch (e) {
|
|
28043
|
+
continue;
|
|
28044
|
+
}
|
|
28045
|
+
}
|
|
28046
|
+
const totalReviews = approved + rejected;
|
|
28047
|
+
const approvalRate = totalReviews > 0 ? approved / totalReviews * 100 : 0;
|
|
28048
|
+
const topReasons = Array.from(reasonCounts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 5).map(([category, count]) => ({
|
|
28049
|
+
category,
|
|
28050
|
+
count,
|
|
28051
|
+
percentage: rejected > 0 ? count / rejected * 100 : 0
|
|
28052
|
+
}));
|
|
28053
|
+
return {
|
|
28054
|
+
totalReviews,
|
|
28055
|
+
approved,
|
|
28056
|
+
rejected,
|
|
28057
|
+
approvalRate,
|
|
28058
|
+
topReasons
|
|
28059
|
+
};
|
|
28060
|
+
}
|
|
28061
|
+
function categorizeRejectionReason(reason) {
|
|
28062
|
+
const lowerReason = reason.toLowerCase();
|
|
28063
|
+
if (lowerReason.includes("test") || lowerReason.includes("spec") || lowerReason.includes("coverage")) {
|
|
28064
|
+
return "Missing tests";
|
|
28065
|
+
}
|
|
28066
|
+
if (lowerReason.includes("type") || lowerReason.includes("undefined") || lowerReason.includes("null") || lowerReason.includes("assignable")) {
|
|
28067
|
+
return "Type errors";
|
|
28068
|
+
}
|
|
28069
|
+
if (lowerReason.includes("incomplete") || lowerReason.includes("missing") || lowerReason.includes("forgot") || lowerReason.includes("didn't implement")) {
|
|
28070
|
+
return "Incomplete implementation";
|
|
28071
|
+
}
|
|
28072
|
+
if (lowerReason.includes("wrong file") || lowerReason.includes("modified incorrect") || lowerReason.includes("shouldn't have changed")) {
|
|
28073
|
+
return "Wrong file modified";
|
|
28074
|
+
}
|
|
28075
|
+
if (lowerReason.includes("performance") || lowerReason.includes("slow") || lowerReason.includes("inefficient")) {
|
|
28076
|
+
return "Performance issue";
|
|
28077
|
+
}
|
|
28078
|
+
if (lowerReason.includes("security") || lowerReason.includes("vulnerability") || lowerReason.includes("unsafe")) {
|
|
28079
|
+
return "Security vulnerability";
|
|
28080
|
+
}
|
|
28081
|
+
if (lowerReason.includes("error handling") || lowerReason.includes("try/catch") || lowerReason.includes("exception")) {
|
|
28082
|
+
return "Missing error handling";
|
|
28083
|
+
}
|
|
28084
|
+
return "Other";
|
|
28085
|
+
}
|
|
27951
28086
|
async function getPatternInsights(swarmMail) {
|
|
27952
28087
|
const db = await swarmMail.getDatabase();
|
|
27953
28088
|
const patterns = [];
|
|
@@ -28035,6 +28170,107 @@ async function getCachedInsights(_swarmMail, cacheKey, computeFn) {
|
|
|
28035
28170
|
function clearInsightsCache() {
|
|
28036
28171
|
insightsCache.clear();
|
|
28037
28172
|
}
|
|
28173
|
+
async function trackCoordinatorViolation(swarmMail, violation) {
|
|
28174
|
+
const db = await swarmMail.getDatabase();
|
|
28175
|
+
const query = `
|
|
28176
|
+
INSERT INTO events (type, project_key, timestamp, data)
|
|
28177
|
+
VALUES (?, ?, ?, ?)
|
|
28178
|
+
RETURNING id
|
|
28179
|
+
`;
|
|
28180
|
+
const data = JSON.stringify({
|
|
28181
|
+
session_id: violation.session_id,
|
|
28182
|
+
epic_id: violation.epic_id,
|
|
28183
|
+
event_type: "VIOLATION",
|
|
28184
|
+
violation_type: violation.violation_type,
|
|
28185
|
+
payload: violation.payload
|
|
28186
|
+
});
|
|
28187
|
+
const result = await db.query(query, [
|
|
28188
|
+
"coordinator_violation",
|
|
28189
|
+
violation.project_key,
|
|
28190
|
+
Date.now(),
|
|
28191
|
+
data
|
|
28192
|
+
]);
|
|
28193
|
+
return result.rows[0].id;
|
|
28194
|
+
}
|
|
28195
|
+
async function getViolationAnalytics(swarmMail, projectKey) {
|
|
28196
|
+
const db = await swarmMail.getDatabase();
|
|
28197
|
+
const violationsQuery = projectKey ? `
|
|
28198
|
+
SELECT data
|
|
28199
|
+
FROM events
|
|
28200
|
+
WHERE type = 'coordinator_violation'
|
|
28201
|
+
AND project_key = ?
|
|
28202
|
+
ORDER BY timestamp DESC
|
|
28203
|
+
` : `
|
|
28204
|
+
SELECT data
|
|
28205
|
+
FROM events
|
|
28206
|
+
WHERE type = 'coordinator_violation'
|
|
28207
|
+
ORDER BY timestamp DESC
|
|
28208
|
+
`;
|
|
28209
|
+
const params = projectKey ? [projectKey] : [];
|
|
28210
|
+
const result = await db.query(violationsQuery, params);
|
|
28211
|
+
if (!result.rows || result.rows.length === 0) {
|
|
28212
|
+
return {
|
|
28213
|
+
totalViolations: 0,
|
|
28214
|
+
byType: [],
|
|
28215
|
+
violationRate: 0
|
|
28216
|
+
};
|
|
28217
|
+
}
|
|
28218
|
+
const violationCounts = new Map;
|
|
28219
|
+
let totalViolations = 0;
|
|
28220
|
+
for (const row of result.rows) {
|
|
28221
|
+
try {
|
|
28222
|
+
const data = JSON.parse(row.data);
|
|
28223
|
+
const violationType = data.violation_type;
|
|
28224
|
+
if (violationType) {
|
|
28225
|
+
violationCounts.set(violationType, (violationCounts.get(violationType) || 0) + 1);
|
|
28226
|
+
totalViolations++;
|
|
28227
|
+
}
|
|
28228
|
+
} catch (e) {
|
|
28229
|
+
continue;
|
|
28230
|
+
}
|
|
28231
|
+
}
|
|
28232
|
+
const byType = Array.from(violationCounts.entries()).sort((a, b) => b[1] - a[1]).map(([violationType, count]) => ({
|
|
28233
|
+
violationType,
|
|
28234
|
+
count,
|
|
28235
|
+
percentage: count / totalViolations * 100
|
|
28236
|
+
}));
|
|
28237
|
+
const coordinationQuery = projectKey ? `
|
|
28238
|
+
SELECT COUNT(*) as count
|
|
28239
|
+
FROM events
|
|
28240
|
+
WHERE type IN ('worker_spawned', 'review_feedback', 'message_sent')
|
|
28241
|
+
AND project_key = ?
|
|
28242
|
+
` : `
|
|
28243
|
+
SELECT COUNT(*) as count
|
|
28244
|
+
FROM events
|
|
28245
|
+
WHERE type IN ('worker_spawned', 'review_feedback', 'message_sent')
|
|
28246
|
+
`;
|
|
28247
|
+
const coordResult = await db.query(coordinationQuery, params);
|
|
28248
|
+
const coordinationCount = coordResult.rows[0]?.count || 0;
|
|
28249
|
+
const violationRate = coordinationCount > 0 ? totalViolations / coordinationCount * 100 : 0;
|
|
28250
|
+
return {
|
|
28251
|
+
totalViolations,
|
|
28252
|
+
byType,
|
|
28253
|
+
violationRate
|
|
28254
|
+
};
|
|
28255
|
+
}
|
|
28256
|
+
function formatFileHistoryWarnings(histories) {
|
|
28257
|
+
if (histories.length === 0) {
|
|
28258
|
+
return "";
|
|
28259
|
+
}
|
|
28260
|
+
const lines = ["⚠️ FILE HISTORY WARNINGS:"];
|
|
28261
|
+
for (const history of histories) {
|
|
28262
|
+
const workerText = history.rejectionCount === 1 ? "1 previous worker rejected" : `${history.rejectionCount} previous workers rejected`;
|
|
28263
|
+
const issuesText = history.topIssues.join(", ");
|
|
28264
|
+
lines.push(`- ${history.file}: ${workerText} for ${issuesText}`);
|
|
28265
|
+
}
|
|
28266
|
+
let result = lines.join(`
|
|
28267
|
+
`);
|
|
28268
|
+
const maxChars = 300 * 4;
|
|
28269
|
+
if (result.length > maxChars) {
|
|
28270
|
+
result = result.slice(0, maxChars - 3) + "...";
|
|
28271
|
+
}
|
|
28272
|
+
return result;
|
|
28273
|
+
}
|
|
28038
28274
|
var insightsCache, CACHE_TTL_MS;
|
|
28039
28275
|
var init_swarm_insights = __esm(() => {
|
|
28040
28276
|
insightsCache = new Map;
|
|
@@ -39248,7 +39484,8 @@ var CellTreeSchema = exports_external.object({
|
|
|
39248
39484
|
title: exports_external.string().min(1),
|
|
39249
39485
|
description: exports_external.string().optional().default("")
|
|
39250
39486
|
}),
|
|
39251
|
-
subtasks: exports_external.array(SubtaskSpecSchema).min(1)
|
|
39487
|
+
subtasks: exports_external.array(SubtaskSpecSchema).min(1),
|
|
39488
|
+
strategy: exports_external.enum(["file-based", "feature-based", "risk-based", "research-based"]).optional().describe("Decomposition strategy from swarm_select_strategy. If not provided, defaults to feature-based.")
|
|
39252
39489
|
});
|
|
39253
39490
|
var EpicCreateArgsSchema = exports_external.object({
|
|
39254
39491
|
epic_title: exports_external.string().min(1),
|
|
@@ -40086,13 +40323,13 @@ async function autoMigrateFromJSONL(adapter, projectKey) {
|
|
|
40086
40323
|
skipExisting: true
|
|
40087
40324
|
});
|
|
40088
40325
|
if (result.created > 0 || result.updated > 0) {
|
|
40089
|
-
console.
|
|
40326
|
+
console.error(`[hive] Auto-migrated ${result.created} cells from ${jsonlPath} (${result.skipped} skipped, ${result.errors.length} errors)`);
|
|
40090
40327
|
}
|
|
40091
40328
|
if (result.errors.length > 0) {
|
|
40092
|
-
console.
|
|
40329
|
+
console.error(`[hive] Migration errors:`, result.errors.slice(0, 5).map((e) => `${e.cellId}: ${e.error}`));
|
|
40093
40330
|
}
|
|
40094
40331
|
} catch (error45) {
|
|
40095
|
-
console.
|
|
40332
|
+
console.error(`[hive] Failed to auto-migrate from ${jsonlPath}:`, error45 instanceof Error ? error45.message : String(error45));
|
|
40096
40333
|
}
|
|
40097
40334
|
}
|
|
40098
40335
|
function formatCellForOutput(adapterCell) {
|
|
@@ -46880,7 +47117,7 @@ var swarm_complete = tool({
|
|
|
46880
47117
|
files_touched: tool.schema.array(tool.schema.string()).optional().describe("Files modified - will be verified (typecheck, tests)"),
|
|
46881
47118
|
skip_verification: tool.schema.boolean().optional().describe("Skip ALL verification (typecheck, tests). Use sparingly! (default: false)"),
|
|
46882
47119
|
planned_files: tool.schema.array(tool.schema.string()).optional().describe("Files that were originally planned to be modified"),
|
|
46883
|
-
start_time: tool.schema.number().
|
|
47120
|
+
start_time: tool.schema.number().describe("Task start timestamp (Unix ms) for duration calculation - REQUIRED for accurate analytics"),
|
|
46884
47121
|
error_count: tool.schema.number().optional().describe("Number of errors encountered during task"),
|
|
46885
47122
|
retry_count: tool.schema.number().optional().describe("Number of retry attempts during task"),
|
|
46886
47123
|
skip_review: tool.schema.boolean().optional().describe("Skip review gate check (default: false). Use only for tasks that don't require coordinator review.")
|
|
@@ -47084,7 +47321,7 @@ This will be recorded as a negative learning signal.`;
|
|
|
47084
47321
|
syncError = error45 instanceof Error ? error45.message : String(error45);
|
|
47085
47322
|
console.warn(`[swarm_complete] Auto-sync failed (non-fatal): ${syncError}`);
|
|
47086
47323
|
}
|
|
47087
|
-
const completionDurationMs =
|
|
47324
|
+
const completionDurationMs = Date.now() - args.start_time;
|
|
47088
47325
|
const eventEpicId = cell.parent_id || (args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id);
|
|
47089
47326
|
try {
|
|
47090
47327
|
const event = createEvent3("subtask_outcome", {
|
|
@@ -61425,14 +61662,14 @@ async function maybeAutoMigrate(db) {
|
|
|
61425
61662
|
if (memoryCount > 0) {
|
|
61426
61663
|
return;
|
|
61427
61664
|
}
|
|
61428
|
-
console.
|
|
61665
|
+
console.error("[memory] Legacy database detected, starting auto-migration...");
|
|
61429
61666
|
const result = await migrateLegacyMemories({
|
|
61430
61667
|
targetDb: db,
|
|
61431
61668
|
dryRun: false,
|
|
61432
|
-
onProgress: console.
|
|
61669
|
+
onProgress: (msg) => console.error(msg)
|
|
61433
61670
|
});
|
|
61434
61671
|
if (result.migrated > 0) {
|
|
61435
|
-
console.
|
|
61672
|
+
console.error(`[memory] Auto-migrated ${result.migrated} memories from legacy database`);
|
|
61436
61673
|
}
|
|
61437
61674
|
if (result.failed > 0) {
|
|
61438
61675
|
console.warn(`[memory] ${result.failed} memories failed to migrate. See errors above.`);
|
|
@@ -61501,6 +61738,7 @@ Linked to ${result.links.length} related memor${result.links.length === 1 ? "y"
|
|
|
61501
61738
|
async find(args2) {
|
|
61502
61739
|
const limit = args2.limit ?? 10;
|
|
61503
61740
|
let results;
|
|
61741
|
+
let usedFallback = false;
|
|
61504
61742
|
if (args2.fts) {
|
|
61505
61743
|
results = await store.ftsSearch(args2.query, {
|
|
61506
61744
|
limit,
|
|
@@ -61511,14 +61749,23 @@ Linked to ${result.links.length} related memor${result.links.length === 1 ? "y"
|
|
|
61511
61749
|
const ollama = yield* Ollama;
|
|
61512
61750
|
return yield* ollama.embed(args2.query);
|
|
61513
61751
|
});
|
|
61514
|
-
|
|
61515
|
-
|
|
61516
|
-
|
|
61517
|
-
|
|
61518
|
-
|
|
61519
|
-
|
|
61752
|
+
try {
|
|
61753
|
+
const queryEmbedding = await exports_Effect.runPromise(program.pipe(exports_Effect.provide(ollamaLayer)));
|
|
61754
|
+
results = await store.search(queryEmbedding, {
|
|
61755
|
+
limit,
|
|
61756
|
+
threshold: 0.3,
|
|
61757
|
+
collection: args2.collection
|
|
61758
|
+
});
|
|
61759
|
+
} catch (e) {
|
|
61760
|
+
console.warn("[hivemind] Ollama unavailable, falling back to full-text search");
|
|
61761
|
+
usedFallback = true;
|
|
61762
|
+
results = await store.ftsSearch(args2.query, {
|
|
61763
|
+
limit,
|
|
61764
|
+
collection: args2.collection
|
|
61765
|
+
});
|
|
61766
|
+
}
|
|
61520
61767
|
}
|
|
61521
|
-
|
|
61768
|
+
const response = {
|
|
61522
61769
|
results: results.map((r) => ({
|
|
61523
61770
|
id: r.memory.id,
|
|
61524
61771
|
content: args2.expand ? r.memory.content : truncateContent(r.memory.content),
|
|
@@ -61529,6 +61776,10 @@ Linked to ${result.links.length} related memor${result.links.length === 1 ? "y"
|
|
|
61529
61776
|
})),
|
|
61530
61777
|
count: results.length
|
|
61531
61778
|
};
|
|
61779
|
+
if (usedFallback) {
|
|
61780
|
+
response.fallback_used = true;
|
|
61781
|
+
}
|
|
61782
|
+
return response;
|
|
61532
61783
|
},
|
|
61533
61784
|
async get(args2) {
|
|
61534
61785
|
return store.get(args2.id);
|
|
@@ -65621,6 +65872,104 @@ function isInCoordinatorContext(sessionId) {
|
|
|
65621
65872
|
return true;
|
|
65622
65873
|
}
|
|
65623
65874
|
|
|
65875
|
+
// src/coordinator-guard.ts
|
|
65876
|
+
class CoordinatorGuardError extends Error {
|
|
65877
|
+
violationType;
|
|
65878
|
+
payload;
|
|
65879
|
+
suggestion;
|
|
65880
|
+
constructor(message, violationType, payload = {}, suggestion) {
|
|
65881
|
+
super(message);
|
|
65882
|
+
this.name = "CoordinatorGuardError";
|
|
65883
|
+
this.violationType = violationType;
|
|
65884
|
+
this.payload = payload;
|
|
65885
|
+
this.suggestion = suggestion;
|
|
65886
|
+
}
|
|
65887
|
+
}
|
|
65888
|
+
var FILE_MODIFICATION_TOOLS = ["edit", "write"];
|
|
65889
|
+
var RESERVATION_TOOLS = ["swarmmail_reserve", "agentmail_reserve"];
|
|
65890
|
+
var TEST_EXECUTION_PATTERNS = [
|
|
65891
|
+
/\bbun\s+test\b/i,
|
|
65892
|
+
/\bnpm\s+(run\s+)?test/i,
|
|
65893
|
+
/\byarn\s+(run\s+)?test/i,
|
|
65894
|
+
/\bpnpm\s+(run\s+)?test/i,
|
|
65895
|
+
/\bjest\b/i,
|
|
65896
|
+
/\bvitest\b/i,
|
|
65897
|
+
/\bmocha\b/i,
|
|
65898
|
+
/\bava\b/i,
|
|
65899
|
+
/\btape\b/i,
|
|
65900
|
+
/\.test\.(ts|js|tsx|jsx)\b/i,
|
|
65901
|
+
/\.spec\.(ts|js|tsx|jsx)\b/i
|
|
65902
|
+
];
|
|
65903
|
+
function isCoordinator(agentContext) {
|
|
65904
|
+
return agentContext === "coordinator";
|
|
65905
|
+
}
|
|
65906
|
+
function checkCoordinatorGuard(params) {
|
|
65907
|
+
const { agentContext, toolName, toolArgs } = params;
|
|
65908
|
+
if (!isCoordinator(agentContext)) {
|
|
65909
|
+
return { blocked: false };
|
|
65910
|
+
}
|
|
65911
|
+
if (FILE_MODIFICATION_TOOLS.includes(toolName)) {
|
|
65912
|
+
const file2 = toolArgs.filePath || "unknown";
|
|
65913
|
+
return {
|
|
65914
|
+
blocked: true,
|
|
65915
|
+
error: new CoordinatorGuardError(`❌ COORDINATOR VIOLATION: Coordinators must spawn a worker to edit files.
|
|
65916
|
+
|
|
65917
|
+
You attempted to ${toolName}: ${file2}
|
|
65918
|
+
|
|
65919
|
+
Coordinators orchestrate work, they don't implement it.
|
|
65920
|
+
|
|
65921
|
+
Instead:
|
|
65922
|
+
1. Use swarm_spawn_subtask to spawn a worker for this file
|
|
65923
|
+
2. Let the worker reserve the file and make edits
|
|
65924
|
+
3. Review the worker's output when complete
|
|
65925
|
+
|
|
65926
|
+
This guard exists to prevent the #1 coordinator anti-pattern.`, "coordinator_edited_file", { tool: toolName, file: file2 }, "Use swarm_spawn_subtask to spawn a worker, then let the worker edit the file")
|
|
65927
|
+
};
|
|
65928
|
+
}
|
|
65929
|
+
if (toolName === "bash") {
|
|
65930
|
+
const command = toolArgs.command || "";
|
|
65931
|
+
const isTestCommand = TEST_EXECUTION_PATTERNS.some((pattern) => pattern.test(command));
|
|
65932
|
+
if (isTestCommand) {
|
|
65933
|
+
return {
|
|
65934
|
+
blocked: true,
|
|
65935
|
+
error: new CoordinatorGuardError(`❌ COORDINATOR VIOLATION: Coordinators must not run tests.
|
|
65936
|
+
|
|
65937
|
+
You attempted to run: ${command}
|
|
65938
|
+
|
|
65939
|
+
Workers run tests as part of their implementation verification.
|
|
65940
|
+
Coordinators review the test results.
|
|
65941
|
+
|
|
65942
|
+
Instead:
|
|
65943
|
+
1. Let workers run tests in their implementation workflow
|
|
65944
|
+
2. Workers call swarm_complete which runs tests automatically
|
|
65945
|
+
3. Review test results from worker output
|
|
65946
|
+
|
|
65947
|
+
This guard prevents coordinators from doing workers' verification work.`, "coordinator_ran_tests", { tool: toolName, command }, "Let workers run tests via swarm_complete")
|
|
65948
|
+
};
|
|
65949
|
+
}
|
|
65950
|
+
}
|
|
65951
|
+
if (RESERVATION_TOOLS.includes(toolName)) {
|
|
65952
|
+
const paths = toolArgs.paths || [];
|
|
65953
|
+
return {
|
|
65954
|
+
blocked: true,
|
|
65955
|
+
error: new CoordinatorGuardError(`❌ COORDINATOR VIOLATION: Coordinators must not reserve files.
|
|
65956
|
+
|
|
65957
|
+
You attempted to reserve: ${paths.join(", ")}
|
|
65958
|
+
|
|
65959
|
+
Workers reserve files before editing to prevent conflicts.
|
|
65960
|
+
Coordinators don't edit files, so they don't reserve them.
|
|
65961
|
+
|
|
65962
|
+
Instead:
|
|
65963
|
+
1. Spawn workers via swarm_spawn_subtask
|
|
65964
|
+
2. Workers will reserve files they need to modify
|
|
65965
|
+
3. Coordinate if multiple workers need the same files
|
|
65966
|
+
|
|
65967
|
+
This guard prevents coordinators from performing worker setup steps.`, "coordinator_reserved_files", { tool: toolName, paths }, "Spawn workers who will reserve files themselves")
|
|
65968
|
+
};
|
|
65969
|
+
}
|
|
65970
|
+
return { blocked: false };
|
|
65971
|
+
}
|
|
65972
|
+
|
|
65624
65973
|
// src/compaction-hook.ts
|
|
65625
65974
|
import { checkSwarmHealth as checkSwarmHealth3 } from "swarm-mail";
|
|
65626
65975
|
|
|
@@ -67785,6 +68134,14 @@ var SwarmPlugin = async (input) => {
|
|
|
67785
68134
|
}
|
|
67786
68135
|
if (isInCoordinatorContext(sessionId)) {
|
|
67787
68136
|
const ctx = getCoordinatorContext(sessionId);
|
|
68137
|
+
const guardResult = checkCoordinatorGuard({
|
|
68138
|
+
agentContext: "coordinator",
|
|
68139
|
+
toolName,
|
|
68140
|
+
toolArgs: output.args
|
|
68141
|
+
});
|
|
68142
|
+
if (guardResult.blocked && guardResult.error) {
|
|
68143
|
+
throw guardResult.error;
|
|
68144
|
+
}
|
|
67788
68145
|
const violation = detectCoordinatorViolation({
|
|
67789
68146
|
sessionId,
|
|
67790
68147
|
epicId: ctx.epicId || "unknown",
|
|
@@ -68016,6 +68373,7 @@ export {
|
|
|
68016
68373
|
isSemanticMemoryAvailable,
|
|
68017
68374
|
isProjectNotFoundError,
|
|
68018
68375
|
isEpicEvent,
|
|
68376
|
+
isCoordinator,
|
|
68019
68377
|
isCellEventType,
|
|
68020
68378
|
isBeadEventType,
|
|
68021
68379
|
isAgentNotFoundError,
|
|
@@ -68090,6 +68448,7 @@ export {
|
|
|
68090
68448
|
clearHiveAdapterCache,
|
|
68091
68449
|
checkTool,
|
|
68092
68450
|
checkGate,
|
|
68451
|
+
checkCoordinatorGuard,
|
|
68093
68452
|
checkBeadsMigrationNeeded,
|
|
68094
68453
|
checkAllTools,
|
|
68095
68454
|
cassTools,
|
|
@@ -68171,6 +68530,7 @@ export {
|
|
|
68171
68530
|
CriterionEvaluationSchema,
|
|
68172
68531
|
CreateSwarmContextArgsSchema,
|
|
68173
68532
|
CreateMandateArgsSchema,
|
|
68533
|
+
CoordinatorGuardError,
|
|
68174
68534
|
CompactionPhase,
|
|
68175
68535
|
CellWorkStartedEventSchema,
|
|
68176
68536
|
CellUpdatedEventSchema,
|
package/dist/memory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|