opencode-swarm-plugin 0.37.0 → 0.39.1
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/.env +2 -0
- package/.hive/eval-results.json +26 -0
- package/.hive/issues.jsonl +20 -5
- package/.hive/memories.jsonl +35 -1
- package/.opencode/eval-history.jsonl +12 -0
- package/.turbo/turbo-build.log +4 -4
- package/.turbo/turbo-test.log +319 -319
- package/CHANGELOG.md +258 -0
- package/README.md +50 -0
- package/bin/swarm.test.ts +475 -0
- package/bin/swarm.ts +385 -208
- package/dist/compaction-hook.d.ts +1 -1
- package/dist/compaction-hook.d.ts.map +1 -1
- package/dist/compaction-prompt-scoring.d.ts +124 -0
- package/dist/compaction-prompt-scoring.d.ts.map +1 -0
- package/dist/eval-capture.d.ts +81 -1
- package/dist/eval-capture.d.ts.map +1 -1
- package/dist/eval-gates.d.ts +84 -0
- package/dist/eval-gates.d.ts.map +1 -0
- package/dist/eval-history.d.ts +117 -0
- package/dist/eval-history.d.ts.map +1 -0
- package/dist/eval-learning.d.ts +216 -0
- package/dist/eval-learning.d.ts.map +1 -0
- package/dist/hive.d.ts +59 -0
- package/dist/hive.d.ts.map +1 -1
- package/dist/index.d.ts +87 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +823 -131
- package/dist/plugin.js +655 -131
- package/dist/post-compaction-tracker.d.ts +133 -0
- package/dist/post-compaction-tracker.d.ts.map +1 -0
- package/dist/swarm-decompose.d.ts +30 -0
- package/dist/swarm-decompose.d.ts.map +1 -1
- package/dist/swarm-orchestrate.d.ts +23 -0
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +25 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm.d.ts +19 -0
- package/dist/swarm.d.ts.map +1 -1
- package/evals/README.md +595 -94
- package/evals/compaction-prompt.eval.ts +149 -0
- package/evals/coordinator-behavior.eval.ts +8 -8
- package/evals/fixtures/compaction-prompt-cases.ts +305 -0
- package/evals/lib/compaction-loader.test.ts +248 -0
- package/evals/lib/compaction-loader.ts +320 -0
- package/evals/lib/data-loader.test.ts +345 -0
- package/evals/lib/data-loader.ts +107 -6
- package/evals/scorers/compaction-prompt-scorers.ts +145 -0
- package/evals/scorers/compaction-scorers.ts +13 -13
- package/evals/scorers/coordinator-discipline.evalite-test.ts +3 -2
- package/evals/scorers/coordinator-discipline.ts +13 -13
- package/examples/plugin-wrapper-template.ts +177 -8
- package/package.json +7 -2
- package/scripts/migrate-unknown-sessions.ts +349 -0
- package/src/compaction-capture.integration.test.ts +257 -0
- package/src/compaction-hook.test.ts +139 -2
- package/src/compaction-hook.ts +113 -2
- package/src/compaction-prompt-scorers.test.ts +299 -0
- package/src/compaction-prompt-scoring.ts +298 -0
- package/src/eval-capture.test.ts +422 -0
- package/src/eval-capture.ts +94 -2
- package/src/eval-gates.test.ts +306 -0
- package/src/eval-gates.ts +218 -0
- package/src/eval-history.test.ts +508 -0
- package/src/eval-history.ts +214 -0
- package/src/eval-learning.test.ts +378 -0
- package/src/eval-learning.ts +360 -0
- package/src/index.ts +61 -1
- package/src/post-compaction-tracker.test.ts +251 -0
- package/src/post-compaction-tracker.ts +237 -0
- package/src/swarm-decompose.test.ts +40 -47
- package/src/swarm-decompose.ts +2 -2
- package/src/swarm-orchestrate.test.ts +270 -7
- package/src/swarm-orchestrate.ts +100 -13
- package/src/swarm-prompts.test.ts +121 -0
- package/src/swarm-prompts.ts +297 -4
- package/src/swarm-research.integration.test.ts +157 -0
- package/src/swarm-review.ts +3 -3
- /package/evals/{evalite.config.ts → evalite.config.ts.bak} +0 -0
package/dist/plugin.js
CHANGED
|
@@ -22178,6 +22178,383 @@ Codebase context considered: ${args.codebase_context.slice(0, 200)}...`;
|
|
|
22178
22178
|
};
|
|
22179
22179
|
});
|
|
22180
22180
|
|
|
22181
|
+
// src/eval-capture.ts
|
|
22182
|
+
var exports_eval_capture = {};
|
|
22183
|
+
__export(exports_eval_capture, {
|
|
22184
|
+
updateEvalRecord: () => updateEvalRecord,
|
|
22185
|
+
saveSession: () => saveSession,
|
|
22186
|
+
readSessionEvents: () => readSessionEvents,
|
|
22187
|
+
readPartialRecords: () => readPartialRecords,
|
|
22188
|
+
readEvalRecords: () => readEvalRecords,
|
|
22189
|
+
getSessionPath: () => getSessionPath,
|
|
22190
|
+
getSessionDir: () => getSessionDir,
|
|
22191
|
+
getEvalDataStats: () => getEvalDataStats,
|
|
22192
|
+
getEvalDataPath: () => getEvalDataPath,
|
|
22193
|
+
finalizeEvalRecord: () => finalizeEvalRecord,
|
|
22194
|
+
exportForEvalite: () => exportForEvalite,
|
|
22195
|
+
ensureSessionDir: () => ensureSessionDir,
|
|
22196
|
+
ensureEvalDataDir: () => ensureEvalDataDir,
|
|
22197
|
+
captureSubtaskOutcome: () => captureSubtaskOutcome,
|
|
22198
|
+
captureHumanFeedback: () => captureHumanFeedback,
|
|
22199
|
+
captureDecomposition: () => captureDecomposition,
|
|
22200
|
+
captureCoordinatorEvent: () => captureCoordinatorEvent,
|
|
22201
|
+
captureCompactionEvent: () => captureCompactionEvent,
|
|
22202
|
+
appendEvalRecord: () => appendEvalRecord,
|
|
22203
|
+
SubtaskOutcomeSchema: () => SubtaskOutcomeSchema,
|
|
22204
|
+
EvalRecordSchema: () => EvalRecordSchema,
|
|
22205
|
+
DEFAULT_EVAL_DATA_PATH: () => DEFAULT_EVAL_DATA_PATH,
|
|
22206
|
+
CoordinatorSessionSchema: () => CoordinatorSessionSchema,
|
|
22207
|
+
CoordinatorEventSchema: () => CoordinatorEventSchema
|
|
22208
|
+
});
|
|
22209
|
+
import * as fs from "node:fs";
|
|
22210
|
+
import * as os from "node:os";
|
|
22211
|
+
import * as path from "node:path";
|
|
22212
|
+
function getEvalDataPath(projectPath) {
|
|
22213
|
+
return path.join(projectPath, DEFAULT_EVAL_DATA_PATH);
|
|
22214
|
+
}
|
|
22215
|
+
function ensureEvalDataDir(projectPath) {
|
|
22216
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22217
|
+
const dir = path.dirname(evalPath);
|
|
22218
|
+
if (!fs.existsSync(dir)) {
|
|
22219
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
22220
|
+
}
|
|
22221
|
+
}
|
|
22222
|
+
function appendEvalRecord(projectPath, record2) {
|
|
22223
|
+
ensureEvalDataDir(projectPath);
|
|
22224
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22225
|
+
const line = `${JSON.stringify(record2)}
|
|
22226
|
+
`;
|
|
22227
|
+
fs.appendFileSync(evalPath, line, "utf-8");
|
|
22228
|
+
}
|
|
22229
|
+
function readEvalRecords(projectPath) {
|
|
22230
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22231
|
+
if (!fs.existsSync(evalPath)) {
|
|
22232
|
+
return [];
|
|
22233
|
+
}
|
|
22234
|
+
const content = fs.readFileSync(evalPath, "utf-8");
|
|
22235
|
+
const lines = content.trim().split(`
|
|
22236
|
+
`).filter(Boolean);
|
|
22237
|
+
return lines.map((line) => {
|
|
22238
|
+
const parsed = JSON.parse(line);
|
|
22239
|
+
return EvalRecordSchema.parse(parsed);
|
|
22240
|
+
});
|
|
22241
|
+
}
|
|
22242
|
+
function readPartialRecords(projectPath) {
|
|
22243
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22244
|
+
if (!fs.existsSync(evalPath)) {
|
|
22245
|
+
return [];
|
|
22246
|
+
}
|
|
22247
|
+
const content = fs.readFileSync(evalPath, "utf-8");
|
|
22248
|
+
const lines = content.trim().split(`
|
|
22249
|
+
`).filter(Boolean);
|
|
22250
|
+
return lines.map((line) => JSON.parse(line));
|
|
22251
|
+
}
|
|
22252
|
+
function updateEvalRecord(projectPath, id, updates) {
|
|
22253
|
+
const records = readPartialRecords(projectPath);
|
|
22254
|
+
const index = records.findIndex((r) => r.id === id);
|
|
22255
|
+
if (index === -1) {
|
|
22256
|
+
return false;
|
|
22257
|
+
}
|
|
22258
|
+
records[index] = { ...records[index], ...updates };
|
|
22259
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22260
|
+
const content = `${records.map((r) => JSON.stringify(r)).join(`
|
|
22261
|
+
`)}
|
|
22262
|
+
`;
|
|
22263
|
+
fs.writeFileSync(evalPath, content, "utf-8");
|
|
22264
|
+
return true;
|
|
22265
|
+
}
|
|
22266
|
+
function captureDecomposition(params) {
|
|
22267
|
+
const record2 = {
|
|
22268
|
+
id: params.epicId,
|
|
22269
|
+
timestamp: new Date().toISOString(),
|
|
22270
|
+
project_path: params.projectPath,
|
|
22271
|
+
task: params.task,
|
|
22272
|
+
context: params.context,
|
|
22273
|
+
strategy: params.strategy,
|
|
22274
|
+
subtask_count: params.subtasks.length,
|
|
22275
|
+
epic_title: params.epicTitle,
|
|
22276
|
+
epic_description: params.epicDescription,
|
|
22277
|
+
subtasks: params.subtasks,
|
|
22278
|
+
outcomes: []
|
|
22279
|
+
};
|
|
22280
|
+
inProgressRecords.set(params.epicId, record2);
|
|
22281
|
+
appendEvalRecord(params.projectPath, record2);
|
|
22282
|
+
return record2;
|
|
22283
|
+
}
|
|
22284
|
+
function captureSubtaskOutcome(params) {
|
|
22285
|
+
const outcome = {
|
|
22286
|
+
bead_id: params.beadId,
|
|
22287
|
+
title: params.title,
|
|
22288
|
+
planned_files: params.plannedFiles,
|
|
22289
|
+
actual_files: params.actualFiles,
|
|
22290
|
+
duration_ms: params.durationMs,
|
|
22291
|
+
error_count: params.errorCount,
|
|
22292
|
+
retry_count: params.retryCount,
|
|
22293
|
+
success: params.success,
|
|
22294
|
+
failure_mode: params.failureMode
|
|
22295
|
+
};
|
|
22296
|
+
const record2 = inProgressRecords.get(params.epicId);
|
|
22297
|
+
if (record2) {
|
|
22298
|
+
record2.outcomes = record2.outcomes || [];
|
|
22299
|
+
record2.outcomes.push(outcome);
|
|
22300
|
+
}
|
|
22301
|
+
updateEvalRecord(params.projectPath, params.epicId, {
|
|
22302
|
+
outcomes: record2?.outcomes
|
|
22303
|
+
});
|
|
22304
|
+
}
|
|
22305
|
+
function finalizeEvalRecord(params) {
|
|
22306
|
+
const record2 = inProgressRecords.get(params.epicId);
|
|
22307
|
+
if (!record2 || !record2.outcomes || record2.outcomes.length === 0) {
|
|
22308
|
+
return null;
|
|
22309
|
+
}
|
|
22310
|
+
const outcomes = record2.outcomes;
|
|
22311
|
+
const overallSuccess = outcomes.every((o) => o.success);
|
|
22312
|
+
const totalDurationMs = outcomes.reduce((sum, o) => sum + o.duration_ms, 0);
|
|
22313
|
+
const totalErrors = outcomes.reduce((sum, o) => sum + o.error_count, 0);
|
|
22314
|
+
const allPlannedFiles = record2.subtasks?.flatMap((s) => s.files) || [];
|
|
22315
|
+
const fileOccurrences = new Map;
|
|
22316
|
+
for (const file2 of allPlannedFiles) {
|
|
22317
|
+
fileOccurrences.set(file2, (fileOccurrences.get(file2) || 0) + 1);
|
|
22318
|
+
}
|
|
22319
|
+
const fileOverlapCount = Array.from(fileOccurrences.values()).filter((count) => count > 1).length;
|
|
22320
|
+
const plannedFileSet = new Set(allPlannedFiles);
|
|
22321
|
+
const actualFileSet = new Set(outcomes.flatMap((o) => o.actual_files));
|
|
22322
|
+
const scopeAccuracy = plannedFileSet.size > 0 ? actualFileSet.size / plannedFileSet.size : 1;
|
|
22323
|
+
const durations = outcomes.map((o) => o.duration_ms).filter((d) => d > 0);
|
|
22324
|
+
const timeBalanceRatio = durations.length > 1 ? Math.max(...durations) / Math.min(...durations) : 1;
|
|
22325
|
+
const finalRecord = {
|
|
22326
|
+
...record2,
|
|
22327
|
+
overall_success: overallSuccess,
|
|
22328
|
+
total_duration_ms: totalDurationMs,
|
|
22329
|
+
total_errors: totalErrors,
|
|
22330
|
+
file_overlap_count: fileOverlapCount,
|
|
22331
|
+
scope_accuracy: scopeAccuracy,
|
|
22332
|
+
time_balance_ratio: timeBalanceRatio
|
|
22333
|
+
};
|
|
22334
|
+
updateEvalRecord(params.projectPath, params.epicId, finalRecord);
|
|
22335
|
+
inProgressRecords.delete(params.epicId);
|
|
22336
|
+
return finalRecord;
|
|
22337
|
+
}
|
|
22338
|
+
function captureHumanFeedback(params) {
|
|
22339
|
+
updateEvalRecord(params.projectPath, params.epicId, {
|
|
22340
|
+
human_accepted: params.accepted,
|
|
22341
|
+
human_modified: params.modified,
|
|
22342
|
+
human_notes: params.notes
|
|
22343
|
+
});
|
|
22344
|
+
}
|
|
22345
|
+
function exportForEvalite(projectPath) {
|
|
22346
|
+
const records = readEvalRecords(projectPath);
|
|
22347
|
+
return records.filter((r) => r.outcomes && r.outcomes.length > 0).map((record2) => ({
|
|
22348
|
+
input: {
|
|
22349
|
+
task: record2.task,
|
|
22350
|
+
context: record2.context
|
|
22351
|
+
},
|
|
22352
|
+
expected: {
|
|
22353
|
+
minSubtasks: 2,
|
|
22354
|
+
subtaskCount: record2.subtask_count,
|
|
22355
|
+
requiredFiles: record2.subtasks.flatMap((s) => s.files),
|
|
22356
|
+
overallSuccess: record2.overall_success
|
|
22357
|
+
},
|
|
22358
|
+
actual: record2
|
|
22359
|
+
}));
|
|
22360
|
+
}
|
|
22361
|
+
function getEvalDataStats(projectPath) {
|
|
22362
|
+
const records = readEvalRecords(projectPath);
|
|
22363
|
+
const complete = records.filter((r) => r.outcomes && r.outcomes.length > 0);
|
|
22364
|
+
if (complete.length === 0) {
|
|
22365
|
+
return {
|
|
22366
|
+
totalRecords: records.length,
|
|
22367
|
+
completeRecords: 0,
|
|
22368
|
+
successRate: 0,
|
|
22369
|
+
avgSubtasks: 0,
|
|
22370
|
+
avgDurationMs: 0,
|
|
22371
|
+
avgScopeAccuracy: 0,
|
|
22372
|
+
avgTimeBalance: 0
|
|
22373
|
+
};
|
|
22374
|
+
}
|
|
22375
|
+
const successCount = complete.filter((r) => r.overall_success).length;
|
|
22376
|
+
const avgSubtasks = complete.reduce((sum, r) => sum + (r.outcomes?.length || 0), 0) / complete.length;
|
|
22377
|
+
const avgDurationMs = complete.reduce((sum, r) => sum + (r.total_duration_ms || 0), 0) / complete.length;
|
|
22378
|
+
const avgScopeAccuracy = complete.reduce((sum, r) => sum + (r.scope_accuracy || 1), 0) / complete.length;
|
|
22379
|
+
const avgTimeBalance = complete.reduce((sum, r) => sum + (r.time_balance_ratio || 1), 0) / complete.length;
|
|
22380
|
+
return {
|
|
22381
|
+
totalRecords: records.length,
|
|
22382
|
+
completeRecords: complete.length,
|
|
22383
|
+
successRate: successCount / complete.length,
|
|
22384
|
+
avgSubtasks,
|
|
22385
|
+
avgDurationMs,
|
|
22386
|
+
avgScopeAccuracy,
|
|
22387
|
+
avgTimeBalance
|
|
22388
|
+
};
|
|
22389
|
+
}
|
|
22390
|
+
function getSessionDir() {
|
|
22391
|
+
return path.join(os.homedir(), ".config", "swarm-tools", "sessions");
|
|
22392
|
+
}
|
|
22393
|
+
function getSessionPath(sessionId) {
|
|
22394
|
+
return path.join(getSessionDir(), `${sessionId}.jsonl`);
|
|
22395
|
+
}
|
|
22396
|
+
function ensureSessionDir() {
|
|
22397
|
+
const sessionDir = getSessionDir();
|
|
22398
|
+
if (!fs.existsSync(sessionDir)) {
|
|
22399
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
22400
|
+
}
|
|
22401
|
+
}
|
|
22402
|
+
function captureCoordinatorEvent(event) {
|
|
22403
|
+
CoordinatorEventSchema.parse(event);
|
|
22404
|
+
ensureSessionDir();
|
|
22405
|
+
const sessionPath = getSessionPath(event.session_id);
|
|
22406
|
+
const line = `${JSON.stringify(event)}
|
|
22407
|
+
`;
|
|
22408
|
+
fs.appendFileSync(sessionPath, line, "utf-8");
|
|
22409
|
+
}
|
|
22410
|
+
function captureCompactionEvent(params) {
|
|
22411
|
+
const event = {
|
|
22412
|
+
session_id: params.session_id,
|
|
22413
|
+
epic_id: params.epic_id,
|
|
22414
|
+
timestamp: new Date().toISOString(),
|
|
22415
|
+
event_type: "COMPACTION",
|
|
22416
|
+
compaction_type: params.compaction_type,
|
|
22417
|
+
payload: params.payload
|
|
22418
|
+
};
|
|
22419
|
+
captureCoordinatorEvent(event);
|
|
22420
|
+
}
|
|
22421
|
+
function readSessionEvents(sessionId) {
|
|
22422
|
+
const sessionPath = getSessionPath(sessionId);
|
|
22423
|
+
if (!fs.existsSync(sessionPath)) {
|
|
22424
|
+
return [];
|
|
22425
|
+
}
|
|
22426
|
+
const content = fs.readFileSync(sessionPath, "utf-8");
|
|
22427
|
+
const lines = content.trim().split(`
|
|
22428
|
+
`).filter(Boolean);
|
|
22429
|
+
return lines.map((line) => {
|
|
22430
|
+
const parsed = JSON.parse(line);
|
|
22431
|
+
return CoordinatorEventSchema.parse(parsed);
|
|
22432
|
+
});
|
|
22433
|
+
}
|
|
22434
|
+
function saveSession(params) {
|
|
22435
|
+
const events = readSessionEvents(params.session_id);
|
|
22436
|
+
if (events.length === 0) {
|
|
22437
|
+
return null;
|
|
22438
|
+
}
|
|
22439
|
+
const timestamps = events.map((e) => new Date(e.timestamp).getTime());
|
|
22440
|
+
const startTime = new Date(Math.min(...timestamps)).toISOString();
|
|
22441
|
+
const endTime = new Date(Math.max(...timestamps)).toISOString();
|
|
22442
|
+
const session = {
|
|
22443
|
+
session_id: params.session_id,
|
|
22444
|
+
epic_id: params.epic_id,
|
|
22445
|
+
start_time: startTime,
|
|
22446
|
+
end_time: endTime,
|
|
22447
|
+
events
|
|
22448
|
+
};
|
|
22449
|
+
return session;
|
|
22450
|
+
}
|
|
22451
|
+
var SubtaskOutcomeSchema, EvalRecordSchema, CoordinatorEventSchema, CoordinatorSessionSchema, DEFAULT_EVAL_DATA_PATH = ".opencode/eval-data.jsonl", inProgressRecords;
|
|
22452
|
+
var init_eval_capture = __esm(() => {
|
|
22453
|
+
init_zod();
|
|
22454
|
+
SubtaskOutcomeSchema = exports_external.object({
|
|
22455
|
+
bead_id: exports_external.string(),
|
|
22456
|
+
title: exports_external.string(),
|
|
22457
|
+
planned_files: exports_external.array(exports_external.string()),
|
|
22458
|
+
actual_files: exports_external.array(exports_external.string()),
|
|
22459
|
+
duration_ms: exports_external.number().int().min(0),
|
|
22460
|
+
error_count: exports_external.number().int().min(0),
|
|
22461
|
+
retry_count: exports_external.number().int().min(0),
|
|
22462
|
+
success: exports_external.boolean(),
|
|
22463
|
+
failure_mode: exports_external.string().optional()
|
|
22464
|
+
});
|
|
22465
|
+
EvalRecordSchema = exports_external.object({
|
|
22466
|
+
id: exports_external.string(),
|
|
22467
|
+
timestamp: exports_external.string(),
|
|
22468
|
+
project_path: exports_external.string(),
|
|
22469
|
+
task: exports_external.string(),
|
|
22470
|
+
context: exports_external.string().optional(),
|
|
22471
|
+
strategy: exports_external.enum(["file-based", "feature-based", "risk-based", "auto"]),
|
|
22472
|
+
subtask_count: exports_external.number().int().min(1),
|
|
22473
|
+
epic_title: exports_external.string(),
|
|
22474
|
+
epic_description: exports_external.string().optional(),
|
|
22475
|
+
subtasks: exports_external.array(exports_external.object({
|
|
22476
|
+
title: exports_external.string(),
|
|
22477
|
+
description: exports_external.string().optional(),
|
|
22478
|
+
files: exports_external.array(exports_external.string()),
|
|
22479
|
+
dependencies: exports_external.array(exports_external.number()).optional(),
|
|
22480
|
+
estimated_complexity: exports_external.number().int().min(1).max(5).optional()
|
|
22481
|
+
})),
|
|
22482
|
+
outcomes: exports_external.array(SubtaskOutcomeSchema).optional(),
|
|
22483
|
+
overall_success: exports_external.boolean().optional(),
|
|
22484
|
+
total_duration_ms: exports_external.number().int().min(0).optional(),
|
|
22485
|
+
total_errors: exports_external.number().int().min(0).optional(),
|
|
22486
|
+
human_accepted: exports_external.boolean().optional(),
|
|
22487
|
+
human_modified: exports_external.boolean().optional(),
|
|
22488
|
+
human_notes: exports_external.string().optional(),
|
|
22489
|
+
file_overlap_count: exports_external.number().int().min(0).optional(),
|
|
22490
|
+
scope_accuracy: exports_external.number().min(0).max(2).optional(),
|
|
22491
|
+
time_balance_ratio: exports_external.number().min(1).optional()
|
|
22492
|
+
});
|
|
22493
|
+
CoordinatorEventSchema = exports_external.discriminatedUnion("event_type", [
|
|
22494
|
+
exports_external.object({
|
|
22495
|
+
session_id: exports_external.string(),
|
|
22496
|
+
epic_id: exports_external.string(),
|
|
22497
|
+
timestamp: exports_external.string(),
|
|
22498
|
+
event_type: exports_external.literal("DECISION"),
|
|
22499
|
+
decision_type: exports_external.enum([
|
|
22500
|
+
"strategy_selected",
|
|
22501
|
+
"worker_spawned",
|
|
22502
|
+
"review_completed",
|
|
22503
|
+
"decomposition_complete"
|
|
22504
|
+
]),
|
|
22505
|
+
payload: exports_external.any()
|
|
22506
|
+
}),
|
|
22507
|
+
exports_external.object({
|
|
22508
|
+
session_id: exports_external.string(),
|
|
22509
|
+
epic_id: exports_external.string(),
|
|
22510
|
+
timestamp: exports_external.string(),
|
|
22511
|
+
event_type: exports_external.literal("VIOLATION"),
|
|
22512
|
+
violation_type: exports_external.enum([
|
|
22513
|
+
"coordinator_edited_file",
|
|
22514
|
+
"coordinator_ran_tests",
|
|
22515
|
+
"coordinator_reserved_files",
|
|
22516
|
+
"no_worker_spawned"
|
|
22517
|
+
]),
|
|
22518
|
+
payload: exports_external.any()
|
|
22519
|
+
}),
|
|
22520
|
+
exports_external.object({
|
|
22521
|
+
session_id: exports_external.string(),
|
|
22522
|
+
epic_id: exports_external.string(),
|
|
22523
|
+
timestamp: exports_external.string(),
|
|
22524
|
+
event_type: exports_external.literal("OUTCOME"),
|
|
22525
|
+
outcome_type: exports_external.enum([
|
|
22526
|
+
"subtask_success",
|
|
22527
|
+
"subtask_retry",
|
|
22528
|
+
"subtask_failed",
|
|
22529
|
+
"epic_complete"
|
|
22530
|
+
]),
|
|
22531
|
+
payload: exports_external.any()
|
|
22532
|
+
}),
|
|
22533
|
+
exports_external.object({
|
|
22534
|
+
session_id: exports_external.string(),
|
|
22535
|
+
epic_id: exports_external.string(),
|
|
22536
|
+
timestamp: exports_external.string(),
|
|
22537
|
+
event_type: exports_external.literal("COMPACTION"),
|
|
22538
|
+
compaction_type: exports_external.enum([
|
|
22539
|
+
"detection_complete",
|
|
22540
|
+
"prompt_generated",
|
|
22541
|
+
"context_injected",
|
|
22542
|
+
"resumption_started",
|
|
22543
|
+
"tool_call_tracked"
|
|
22544
|
+
]),
|
|
22545
|
+
payload: exports_external.any()
|
|
22546
|
+
})
|
|
22547
|
+
]);
|
|
22548
|
+
CoordinatorSessionSchema = exports_external.object({
|
|
22549
|
+
session_id: exports_external.string(),
|
|
22550
|
+
epic_id: exports_external.string(),
|
|
22551
|
+
start_time: exports_external.string(),
|
|
22552
|
+
end_time: exports_external.string().optional(),
|
|
22553
|
+
events: exports_external.array(CoordinatorEventSchema)
|
|
22554
|
+
});
|
|
22555
|
+
inProgressRecords = new Map;
|
|
22556
|
+
});
|
|
22557
|
+
|
|
22181
22558
|
// src/learning.ts
|
|
22182
22559
|
var exports_learning = {};
|
|
22183
22560
|
__export(exports_learning, {
|
|
@@ -39165,6 +39542,71 @@ var hive_ready = tool({
|
|
|
39165
39542
|
}
|
|
39166
39543
|
}
|
|
39167
39544
|
});
|
|
39545
|
+
var hive_cells = tool({
|
|
39546
|
+
description: `Query cells from the hive database with flexible filtering.
|
|
39547
|
+
|
|
39548
|
+
USE THIS TOOL TO:
|
|
39549
|
+
- List all open cells: hive_cells()
|
|
39550
|
+
- Find cells by status: hive_cells({ status: "in_progress" })
|
|
39551
|
+
- Find cells by type: hive_cells({ type: "bug" })
|
|
39552
|
+
- Get a specific cell by partial ID: hive_cells({ id: "mjkmd" })
|
|
39553
|
+
- Get the next ready (unblocked) cell: hive_cells({ ready: true })
|
|
39554
|
+
- Combine filters: hive_cells({ status: "open", type: "task" })
|
|
39555
|
+
|
|
39556
|
+
RETURNS: Array of cells with id, title, status, priority, type, parent_id, created_at, updated_at
|
|
39557
|
+
|
|
39558
|
+
PREFER THIS OVER hive_query when you need to:
|
|
39559
|
+
- See what work is available
|
|
39560
|
+
- Check status of multiple cells
|
|
39561
|
+
- Find cells matching criteria
|
|
39562
|
+
- Look up a cell by partial ID`,
|
|
39563
|
+
args: {
|
|
39564
|
+
id: tool.schema.string().optional().describe("Partial or full cell ID to look up"),
|
|
39565
|
+
status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("Filter by status"),
|
|
39566
|
+
type: tool.schema.enum(["task", "bug", "feature", "epic", "chore"]).optional().describe("Filter by type"),
|
|
39567
|
+
ready: tool.schema.boolean().optional().describe("If true, return only the next unblocked cell"),
|
|
39568
|
+
limit: tool.schema.number().optional().describe("Max cells to return (default 20)")
|
|
39569
|
+
},
|
|
39570
|
+
async execute(args, ctx) {
|
|
39571
|
+
const projectKey = getHiveWorkingDirectory();
|
|
39572
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
39573
|
+
try {
|
|
39574
|
+
if (args.id) {
|
|
39575
|
+
const fullId = await resolvePartialId(adapter, projectKey, args.id) || args.id;
|
|
39576
|
+
const cell = await adapter.getCell(projectKey, fullId);
|
|
39577
|
+
if (!cell) {
|
|
39578
|
+
throw new HiveError(`No cell found matching ID '${args.id}'`, "hive_cells");
|
|
39579
|
+
}
|
|
39580
|
+
const formatted2 = formatCellForOutput(cell);
|
|
39581
|
+
return JSON.stringify([formatted2], null, 2);
|
|
39582
|
+
}
|
|
39583
|
+
if (args.ready) {
|
|
39584
|
+
const ready = await adapter.getNextReadyCell(projectKey);
|
|
39585
|
+
if (!ready) {
|
|
39586
|
+
return JSON.stringify([], null, 2);
|
|
39587
|
+
}
|
|
39588
|
+
const formatted2 = formatCellForOutput(ready);
|
|
39589
|
+
return JSON.stringify([formatted2], null, 2);
|
|
39590
|
+
}
|
|
39591
|
+
const cells = await adapter.queryCells(projectKey, {
|
|
39592
|
+
status: args.status,
|
|
39593
|
+
type: args.type,
|
|
39594
|
+
limit: args.limit || 20
|
|
39595
|
+
});
|
|
39596
|
+
const formatted = cells.map((c) => formatCellForOutput(c));
|
|
39597
|
+
return JSON.stringify(formatted, null, 2);
|
|
39598
|
+
} catch (error45) {
|
|
39599
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
39600
|
+
if (message.includes("Ambiguous hash")) {
|
|
39601
|
+
throw new HiveError(`Ambiguous ID '${args.id}': multiple cells match. Please provide more characters.`, "hive_cells");
|
|
39602
|
+
}
|
|
39603
|
+
if (message.includes("Bead not found") || message.includes("Cell not found")) {
|
|
39604
|
+
throw new HiveError(`No cell found matching ID '${args.id || "unknown"}'`, "hive_cells");
|
|
39605
|
+
}
|
|
39606
|
+
throw new HiveError(`Failed to query cells: ${message}`, "hive_cells");
|
|
39607
|
+
}
|
|
39608
|
+
}
|
|
39609
|
+
});
|
|
39168
39610
|
var hive_sync = tool({
|
|
39169
39611
|
description: "Sync hive to git and push (MANDATORY at session end)",
|
|
39170
39612
|
args: {
|
|
@@ -39306,6 +39748,7 @@ var hiveTools = {
|
|
|
39306
39748
|
hive_close,
|
|
39307
39749
|
hive_start,
|
|
39308
39750
|
hive_ready,
|
|
39751
|
+
hive_cells,
|
|
39309
39752
|
hive_sync,
|
|
39310
39753
|
hive_link_thread
|
|
39311
39754
|
};
|
|
@@ -41464,122 +41907,7 @@ init_swarm_strategies();
|
|
|
41464
41907
|
init_dist();
|
|
41465
41908
|
init_zod();
|
|
41466
41909
|
init_swarm_strategies();
|
|
41467
|
-
|
|
41468
|
-
// src/eval-capture.ts
|
|
41469
|
-
init_zod();
|
|
41470
|
-
import * as fs from "node:fs";
|
|
41471
|
-
import * as os from "node:os";
|
|
41472
|
-
import * as path from "node:path";
|
|
41473
|
-
var SubtaskOutcomeSchema = exports_external.object({
|
|
41474
|
-
bead_id: exports_external.string(),
|
|
41475
|
-
title: exports_external.string(),
|
|
41476
|
-
planned_files: exports_external.array(exports_external.string()),
|
|
41477
|
-
actual_files: exports_external.array(exports_external.string()),
|
|
41478
|
-
duration_ms: exports_external.number().int().min(0),
|
|
41479
|
-
error_count: exports_external.number().int().min(0),
|
|
41480
|
-
retry_count: exports_external.number().int().min(0),
|
|
41481
|
-
success: exports_external.boolean(),
|
|
41482
|
-
failure_mode: exports_external.string().optional()
|
|
41483
|
-
});
|
|
41484
|
-
var EvalRecordSchema = exports_external.object({
|
|
41485
|
-
id: exports_external.string(),
|
|
41486
|
-
timestamp: exports_external.string(),
|
|
41487
|
-
project_path: exports_external.string(),
|
|
41488
|
-
task: exports_external.string(),
|
|
41489
|
-
context: exports_external.string().optional(),
|
|
41490
|
-
strategy: exports_external.enum(["file-based", "feature-based", "risk-based", "auto"]),
|
|
41491
|
-
subtask_count: exports_external.number().int().min(1),
|
|
41492
|
-
epic_title: exports_external.string(),
|
|
41493
|
-
epic_description: exports_external.string().optional(),
|
|
41494
|
-
subtasks: exports_external.array(exports_external.object({
|
|
41495
|
-
title: exports_external.string(),
|
|
41496
|
-
description: exports_external.string().optional(),
|
|
41497
|
-
files: exports_external.array(exports_external.string()),
|
|
41498
|
-
dependencies: exports_external.array(exports_external.number()).optional(),
|
|
41499
|
-
estimated_complexity: exports_external.number().int().min(1).max(5).optional()
|
|
41500
|
-
})),
|
|
41501
|
-
outcomes: exports_external.array(SubtaskOutcomeSchema).optional(),
|
|
41502
|
-
overall_success: exports_external.boolean().optional(),
|
|
41503
|
-
total_duration_ms: exports_external.number().int().min(0).optional(),
|
|
41504
|
-
total_errors: exports_external.number().int().min(0).optional(),
|
|
41505
|
-
human_accepted: exports_external.boolean().optional(),
|
|
41506
|
-
human_modified: exports_external.boolean().optional(),
|
|
41507
|
-
human_notes: exports_external.string().optional(),
|
|
41508
|
-
file_overlap_count: exports_external.number().int().min(0).optional(),
|
|
41509
|
-
scope_accuracy: exports_external.number().min(0).max(2).optional(),
|
|
41510
|
-
time_balance_ratio: exports_external.number().min(1).optional()
|
|
41511
|
-
});
|
|
41512
|
-
var CoordinatorEventSchema = exports_external.discriminatedUnion("event_type", [
|
|
41513
|
-
exports_external.object({
|
|
41514
|
-
session_id: exports_external.string(),
|
|
41515
|
-
epic_id: exports_external.string(),
|
|
41516
|
-
timestamp: exports_external.string(),
|
|
41517
|
-
event_type: exports_external.literal("DECISION"),
|
|
41518
|
-
decision_type: exports_external.enum([
|
|
41519
|
-
"strategy_selected",
|
|
41520
|
-
"worker_spawned",
|
|
41521
|
-
"review_completed",
|
|
41522
|
-
"decomposition_complete"
|
|
41523
|
-
]),
|
|
41524
|
-
payload: exports_external.any()
|
|
41525
|
-
}),
|
|
41526
|
-
exports_external.object({
|
|
41527
|
-
session_id: exports_external.string(),
|
|
41528
|
-
epic_id: exports_external.string(),
|
|
41529
|
-
timestamp: exports_external.string(),
|
|
41530
|
-
event_type: exports_external.literal("VIOLATION"),
|
|
41531
|
-
violation_type: exports_external.enum([
|
|
41532
|
-
"coordinator_edited_file",
|
|
41533
|
-
"coordinator_ran_tests",
|
|
41534
|
-
"coordinator_reserved_files",
|
|
41535
|
-
"no_worker_spawned"
|
|
41536
|
-
]),
|
|
41537
|
-
payload: exports_external.any()
|
|
41538
|
-
}),
|
|
41539
|
-
exports_external.object({
|
|
41540
|
-
session_id: exports_external.string(),
|
|
41541
|
-
epic_id: exports_external.string(),
|
|
41542
|
-
timestamp: exports_external.string(),
|
|
41543
|
-
event_type: exports_external.literal("OUTCOME"),
|
|
41544
|
-
outcome_type: exports_external.enum([
|
|
41545
|
-
"subtask_success",
|
|
41546
|
-
"subtask_retry",
|
|
41547
|
-
"subtask_failed",
|
|
41548
|
-
"epic_complete"
|
|
41549
|
-
]),
|
|
41550
|
-
payload: exports_external.any()
|
|
41551
|
-
})
|
|
41552
|
-
]);
|
|
41553
|
-
var CoordinatorSessionSchema = exports_external.object({
|
|
41554
|
-
session_id: exports_external.string(),
|
|
41555
|
-
epic_id: exports_external.string(),
|
|
41556
|
-
start_time: exports_external.string(),
|
|
41557
|
-
end_time: exports_external.string().optional(),
|
|
41558
|
-
events: exports_external.array(CoordinatorEventSchema)
|
|
41559
|
-
});
|
|
41560
|
-
var inProgressRecords = new Map;
|
|
41561
|
-
function getSessionDir() {
|
|
41562
|
-
return path.join(os.homedir(), ".config", "swarm-tools", "sessions");
|
|
41563
|
-
}
|
|
41564
|
-
function getSessionPath(sessionId) {
|
|
41565
|
-
return path.join(getSessionDir(), `${sessionId}.jsonl`);
|
|
41566
|
-
}
|
|
41567
|
-
function ensureSessionDir() {
|
|
41568
|
-
const sessionDir = getSessionDir();
|
|
41569
|
-
if (!fs.existsSync(sessionDir)) {
|
|
41570
|
-
fs.mkdirSync(sessionDir, { recursive: true });
|
|
41571
|
-
}
|
|
41572
|
-
}
|
|
41573
|
-
function captureCoordinatorEvent(event) {
|
|
41574
|
-
CoordinatorEventSchema.parse(event);
|
|
41575
|
-
ensureSessionDir();
|
|
41576
|
-
const sessionPath = getSessionPath(event.session_id);
|
|
41577
|
-
const line = `${JSON.stringify(event)}
|
|
41578
|
-
`;
|
|
41579
|
-
fs.appendFileSync(sessionPath, line, "utf-8");
|
|
41580
|
-
}
|
|
41581
|
-
|
|
41582
|
-
// src/swarm-decompose.ts
|
|
41910
|
+
init_eval_capture();
|
|
41583
41911
|
var DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
|
|
41584
41912
|
|
|
41585
41913
|
## Task
|
|
@@ -41897,9 +42225,14 @@ ${fullContext}` : `## Additional Context
|
|
|
41897
42225
|
}
|
|
41898
42226
|
});
|
|
41899
42227
|
var swarm_validate_decomposition = tool({
|
|
41900
|
-
description: "Validate a decomposition response against CellTreeSchema",
|
|
42228
|
+
description: "Validate a decomposition response against CellTreeSchema and capture for eval",
|
|
41901
42229
|
args: {
|
|
41902
|
-
response: tool.schema.string().describe("JSON response from agent (CellTree format)")
|
|
42230
|
+
response: tool.schema.string().describe("JSON response from agent (CellTree format)"),
|
|
42231
|
+
project_path: tool.schema.string().optional().describe("Project path for eval capture"),
|
|
42232
|
+
task: tool.schema.string().optional().describe("Original task description for eval capture"),
|
|
42233
|
+
context: tool.schema.string().optional().describe("Context provided for decomposition"),
|
|
42234
|
+
strategy: tool.schema.enum(["file-based", "feature-based", "risk-based", "auto"]).optional().describe("Decomposition strategy used"),
|
|
42235
|
+
epic_id: tool.schema.string().optional().describe("Epic ID for eval capture")
|
|
41903
42236
|
},
|
|
41904
42237
|
async execute(args) {
|
|
41905
42238
|
try {
|
|
@@ -41933,6 +42266,29 @@ var swarm_validate_decomposition = tool({
|
|
|
41933
42266
|
}
|
|
41934
42267
|
}
|
|
41935
42268
|
const instructionConflicts = detectInstructionConflicts(validated.subtasks);
|
|
42269
|
+
if (args.project_path && args.task && args.strategy && args.epic_id) {
|
|
42270
|
+
try {
|
|
42271
|
+
const { captureDecomposition: captureDecomposition2 } = await Promise.resolve().then(() => (init_eval_capture(), exports_eval_capture));
|
|
42272
|
+
captureDecomposition2({
|
|
42273
|
+
epicId: args.epic_id,
|
|
42274
|
+
projectPath: args.project_path,
|
|
42275
|
+
task: args.task,
|
|
42276
|
+
context: args.context,
|
|
42277
|
+
strategy: args.strategy,
|
|
42278
|
+
epicTitle: validated.epic.title,
|
|
42279
|
+
epicDescription: validated.epic.description,
|
|
42280
|
+
subtasks: validated.subtasks.map((s) => ({
|
|
42281
|
+
title: s.title,
|
|
42282
|
+
description: s.description,
|
|
42283
|
+
files: s.files,
|
|
42284
|
+
dependencies: s.dependencies,
|
|
42285
|
+
estimated_complexity: s.estimated_complexity
|
|
42286
|
+
}))
|
|
42287
|
+
});
|
|
42288
|
+
} catch (error45) {
|
|
42289
|
+
console.warn("[swarm_validate_decomposition] Failed to capture decomposition:", error45);
|
|
42290
|
+
}
|
|
42291
|
+
}
|
|
41936
42292
|
return JSON.stringify({
|
|
41937
42293
|
valid: true,
|
|
41938
42294
|
cell_tree: validated,
|
|
@@ -41973,7 +42329,7 @@ var swarm_delegate_planning = tool({
|
|
|
41973
42329
|
strategy: tool.schema.enum(["auto", "file-based", "feature-based", "risk-based"]).optional().default("auto").describe("Decomposition strategy (default: auto-detect)"),
|
|
41974
42330
|
query_cass: tool.schema.boolean().optional().default(true).describe("Query CASS for similar past tasks (default: true)")
|
|
41975
42331
|
},
|
|
41976
|
-
async execute(args) {
|
|
42332
|
+
async execute(args, _ctx) {
|
|
41977
42333
|
const { selectStrategy: selectStrategy2, formatStrategyGuidelines: formatStrategyGuidelines2 } = await Promise.resolve().then(() => (init_swarm_strategies(), exports_swarm_strategies));
|
|
41978
42334
|
const { formatMemoryQueryForDecomposition: formatMemoryQueryForDecomposition2 } = await Promise.resolve().then(() => (init_learning(), exports_learning));
|
|
41979
42335
|
const { listSkills: listSkills2, getSkillsContextForSwarm: getSkillsContextForSwarm2, findRelevantSkills: findRelevantSkills2 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
|
|
@@ -41989,7 +42345,7 @@ var swarm_delegate_planning = tool({
|
|
|
41989
42345
|
}
|
|
41990
42346
|
try {
|
|
41991
42347
|
captureCoordinatorEvent({
|
|
41992
|
-
session_id:
|
|
42348
|
+
session_id: _ctx.sessionID || "unknown",
|
|
41993
42349
|
epic_id: "planning",
|
|
41994
42350
|
timestamp: new Date().toISOString(),
|
|
41995
42351
|
event_type: "DECISION",
|
|
@@ -44080,6 +44436,7 @@ var worktreeTools = {
|
|
|
44080
44436
|
init_dist();
|
|
44081
44437
|
init_zod();
|
|
44082
44438
|
import { sendSwarmMessage as sendSwarmMessage2 } from "swarm-mail";
|
|
44439
|
+
init_eval_capture();
|
|
44083
44440
|
var ReviewIssueSchema = exports_external.object({
|
|
44084
44441
|
file: exports_external.string(),
|
|
44085
44442
|
line: exports_external.number().optional(),
|
|
@@ -44304,7 +44661,7 @@ var swarm_review_feedback = tool({
|
|
|
44304
44661
|
summary: exports_external.string().optional().describe("Review summary"),
|
|
44305
44662
|
issues: exports_external.string().optional().describe("JSON array of ReviewIssue objects (for needs_changes)")
|
|
44306
44663
|
},
|
|
44307
|
-
async execute(args) {
|
|
44664
|
+
async execute(args, _ctx) {
|
|
44308
44665
|
let parsedIssues = [];
|
|
44309
44666
|
if (args.issues) {
|
|
44310
44667
|
try {
|
|
@@ -44327,7 +44684,7 @@ var swarm_review_feedback = tool({
|
|
|
44327
44684
|
markReviewApproved(args.task_id);
|
|
44328
44685
|
try {
|
|
44329
44686
|
captureCoordinatorEvent({
|
|
44330
|
-
session_id:
|
|
44687
|
+
session_id: _ctx.sessionID || "unknown",
|
|
44331
44688
|
epic_id: epicId,
|
|
44332
44689
|
timestamp: new Date().toISOString(),
|
|
44333
44690
|
event_type: "DECISION",
|
|
@@ -44365,7 +44722,7 @@ You may now complete the task with \`swarm_complete\`.`,
|
|
|
44365
44722
|
const remaining = MAX_REVIEW_ATTEMPTS - attemptNumber;
|
|
44366
44723
|
try {
|
|
44367
44724
|
captureCoordinatorEvent({
|
|
44368
|
-
session_id:
|
|
44725
|
+
session_id: _ctx.sessionID || "unknown",
|
|
44369
44726
|
epic_id: epicId,
|
|
44370
44727
|
timestamp: new Date().toISOString(),
|
|
44371
44728
|
event_type: "DECISION",
|
|
@@ -44436,6 +44793,7 @@ var reviewTools = {
|
|
|
44436
44793
|
};
|
|
44437
44794
|
|
|
44438
44795
|
// src/swarm-orchestrate.ts
|
|
44796
|
+
init_eval_capture();
|
|
44439
44797
|
function generateWorkerHandoff(params) {
|
|
44440
44798
|
const handoff = {
|
|
44441
44799
|
contract: {
|
|
@@ -45336,10 +45694,29 @@ Files touched: ${args.files_touched?.join(", ") || "none recorded"}`,
|
|
|
45336
45694
|
reason: "No files_owned contract found (non-epic subtask or decomposition event missing)"
|
|
45337
45695
|
}
|
|
45338
45696
|
};
|
|
45697
|
+
try {
|
|
45698
|
+
const { captureSubtaskOutcome: captureSubtaskOutcome2 } = await Promise.resolve().then(() => (init_eval_capture(), exports_eval_capture));
|
|
45699
|
+
const durationMs2 = args.start_time ? Date.now() - args.start_time : 0;
|
|
45700
|
+
const evalEpicId = cell.parent_id || epicId2;
|
|
45701
|
+
captureSubtaskOutcome2({
|
|
45702
|
+
epicId: evalEpicId,
|
|
45703
|
+
projectPath: args.project_key,
|
|
45704
|
+
beadId: args.bead_id,
|
|
45705
|
+
title: cell.title,
|
|
45706
|
+
plannedFiles: args.planned_files || [],
|
|
45707
|
+
actualFiles: args.files_touched || [],
|
|
45708
|
+
durationMs: durationMs2,
|
|
45709
|
+
errorCount: args.error_count || 0,
|
|
45710
|
+
retryCount: args.retry_count || 0,
|
|
45711
|
+
success: true
|
|
45712
|
+
});
|
|
45713
|
+
} catch (error45) {
|
|
45714
|
+
console.warn("[swarm_complete] Failed to capture subtask outcome:", error45);
|
|
45715
|
+
}
|
|
45339
45716
|
try {
|
|
45340
45717
|
const durationMs2 = args.start_time ? Date.now() - args.start_time : 0;
|
|
45341
45718
|
captureCoordinatorEvent({
|
|
45342
|
-
session_id:
|
|
45719
|
+
session_id: _ctx.sessionID || "unknown",
|
|
45343
45720
|
epic_id: epicId2,
|
|
45344
45721
|
timestamp: new Date().toISOString(),
|
|
45345
45722
|
event_type: "OUTCOME",
|
|
@@ -45421,7 +45798,7 @@ ${errorStack.slice(0, 1000)}
|
|
|
45421
45798
|
try {
|
|
45422
45799
|
const durationMs = args.start_time ? Date.now() - args.start_time : 0;
|
|
45423
45800
|
captureCoordinatorEvent({
|
|
45424
|
-
session_id:
|
|
45801
|
+
session_id: _ctx.sessionID || "unknown",
|
|
45425
45802
|
epic_id: epicId,
|
|
45426
45803
|
timestamp: new Date().toISOString(),
|
|
45427
45804
|
event_type: "OUTCOME",
|
|
@@ -45488,7 +45865,9 @@ var swarm_record_outcome = tool({
|
|
|
45488
45865
|
"user_cancelled",
|
|
45489
45866
|
"unknown"
|
|
45490
45867
|
]).optional().describe("Failure classification (only when success=false). Auto-classified if not provided."),
|
|
45491
|
-
failure_details: tool.schema.string().optional().describe("Detailed failure context (error message, stack trace, etc.)")
|
|
45868
|
+
failure_details: tool.schema.string().optional().describe("Detailed failure context (error message, stack trace, etc.)"),
|
|
45869
|
+
project_path: tool.schema.string().optional().describe("Project path (for finalizing eval records when all subtasks complete)"),
|
|
45870
|
+
epic_id: tool.schema.string().optional().describe("Epic ID (for finalizing eval records when all subtasks complete)")
|
|
45492
45871
|
},
|
|
45493
45872
|
async execute(args) {
|
|
45494
45873
|
const signals = {
|
|
@@ -45510,6 +45889,18 @@ var swarm_record_outcome = tool({
|
|
|
45510
45889
|
const validated = OutcomeSignalsSchema.parse(signals);
|
|
45511
45890
|
const scored = scoreImplicitFeedback(validated, DEFAULT_LEARNING_CONFIG);
|
|
45512
45891
|
const errorStats = await globalErrorAccumulator.getErrorStats(args.bead_id);
|
|
45892
|
+
let finalizedRecord = null;
|
|
45893
|
+
if (args.project_path && args.epic_id) {
|
|
45894
|
+
try {
|
|
45895
|
+
const { finalizeEvalRecord: finalizeEvalRecord2 } = await Promise.resolve().then(() => (init_eval_capture(), exports_eval_capture));
|
|
45896
|
+
finalizedRecord = finalizeEvalRecord2({
|
|
45897
|
+
epicId: args.epic_id,
|
|
45898
|
+
projectPath: args.project_path
|
|
45899
|
+
});
|
|
45900
|
+
} catch (error45) {
|
|
45901
|
+
console.warn("[swarm_record_outcome] Failed to finalize eval record:", error45);
|
|
45902
|
+
}
|
|
45903
|
+
}
|
|
45513
45904
|
const criteriaToScore = args.criteria ?? [
|
|
45514
45905
|
"type_safe",
|
|
45515
45906
|
"no_bugs",
|
|
@@ -45551,6 +45942,7 @@ var swarm_record_outcome = tool({
|
|
|
45551
45942
|
accumulated_errors: errorStats.total,
|
|
45552
45943
|
unresolved_errors: errorStats.unresolved
|
|
45553
45944
|
},
|
|
45945
|
+
finalized_eval_record: finalizedRecord || undefined,
|
|
45554
45946
|
note: "Feedback events should be stored for criterion weight calculation. Use learning.ts functions to apply weights."
|
|
45555
45947
|
}, null, 2);
|
|
45556
45948
|
}
|
|
@@ -45582,12 +45974,31 @@ async function runResearchPhase(task, projectPath, options2) {
|
|
|
45582
45974
|
if (techStack.length === 0) {
|
|
45583
45975
|
return {
|
|
45584
45976
|
tech_stack: [],
|
|
45977
|
+
spawn_instructions: [],
|
|
45585
45978
|
summaries: {},
|
|
45586
45979
|
memory_ids: []
|
|
45587
45980
|
};
|
|
45588
45981
|
}
|
|
45982
|
+
const spawnInstructions = [];
|
|
45983
|
+
for (const tech of techStack) {
|
|
45984
|
+
const researchId = `research-${tech}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
45985
|
+
const prompt = formatResearcherPrompt({
|
|
45986
|
+
research_id: researchId,
|
|
45987
|
+
epic_id: "standalone-research",
|
|
45988
|
+
tech_stack: [tech],
|
|
45989
|
+
project_path: projectPath,
|
|
45990
|
+
check_upgrades: options2?.checkUpgrades ?? false
|
|
45991
|
+
});
|
|
45992
|
+
spawnInstructions.push({
|
|
45993
|
+
research_id: researchId,
|
|
45994
|
+
tech,
|
|
45995
|
+
prompt,
|
|
45996
|
+
subagent_type: "swarm/researcher"
|
|
45997
|
+
});
|
|
45998
|
+
}
|
|
45589
45999
|
return {
|
|
45590
46000
|
tech_stack: techStack,
|
|
46001
|
+
spawn_instructions: spawnInstructions,
|
|
45591
46002
|
summaries: {},
|
|
45592
46003
|
memory_ids: []
|
|
45593
46004
|
};
|
|
@@ -46024,6 +46435,7 @@ var orchestrateTools = {
|
|
|
46024
46435
|
};
|
|
46025
46436
|
|
|
46026
46437
|
// src/swarm-prompts.ts
|
|
46438
|
+
init_eval_capture();
|
|
46027
46439
|
var STRATEGY_DECOMPOSITION_PROMPT2 = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
|
|
46028
46440
|
|
|
46029
46441
|
## Task
|
|
@@ -46820,7 +47232,7 @@ var swarm_spawn_subtask = tool({
|
|
|
46820
47232
|
}).optional().describe("Recovery context from checkpoint compaction"),
|
|
46821
47233
|
model: tool.schema.string().optional().describe("Optional explicit model override (auto-selected if not provided)")
|
|
46822
47234
|
},
|
|
46823
|
-
async execute(args) {
|
|
47235
|
+
async execute(args, _ctx) {
|
|
46824
47236
|
const prompt = formatSubtaskPromptV2({
|
|
46825
47237
|
bead_id: args.bead_id,
|
|
46826
47238
|
epic_id: args.epic_id,
|
|
@@ -46849,7 +47261,7 @@ var swarm_spawn_subtask = tool({
|
|
|
46849
47261
|
const postCompletionInstructions = COORDINATOR_POST_WORKER_CHECKLIST.replace(/{project_key}/g, args.project_path || "$PWD").replace(/{epic_id}/g, args.epic_id).replace(/{task_id}/g, args.bead_id).replace(/{files_touched}/g, filesJoined).replace(/{worker_id}/g, "worker");
|
|
46850
47262
|
try {
|
|
46851
47263
|
captureCoordinatorEvent({
|
|
46852
|
-
session_id:
|
|
47264
|
+
session_id: _ctx.sessionID || "unknown",
|
|
46853
47265
|
epic_id: args.epic_id,
|
|
46854
47266
|
timestamp: new Date().toISOString(),
|
|
46855
47267
|
event_type: "DECISION",
|
|
@@ -62712,6 +63124,7 @@ function guardrailOutput(toolName, output, config2 = DEFAULT_GUARDRAIL_CONFIG) {
|
|
|
62712
63124
|
}
|
|
62713
63125
|
|
|
62714
63126
|
// src/planning-guardrails.ts
|
|
63127
|
+
init_eval_capture();
|
|
62715
63128
|
var FILE_MODIFICATION_PATTERNS = [
|
|
62716
63129
|
/\bimplement\b/i,
|
|
62717
63130
|
/\bcreate\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
@@ -62997,9 +63410,21 @@ function getLog() {
|
|
|
62997
63410
|
}
|
|
62998
63411
|
return _logger;
|
|
62999
63412
|
}
|
|
63000
|
-
var SWARM_COMPACTION_CONTEXT =
|
|
63413
|
+
var SWARM_COMPACTION_CONTEXT = `
|
|
63414
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
63415
|
+
│ │
|
|
63416
|
+
│ \uD83D\uDC1D YOU ARE THE COORDINATOR \uD83D\uDC1D │
|
|
63417
|
+
│ │
|
|
63418
|
+
│ NOT A WORKER. NOT AN IMPLEMENTER. │
|
|
63419
|
+
│ YOU ORCHESTRATE. │
|
|
63420
|
+
│ │
|
|
63421
|
+
└─────────────────────────────────────────────────────────────┘
|
|
63422
|
+
|
|
63423
|
+
## \uD83C\uDFAF NON-NEGOTIABLE: YOU ARE THE COORDINATOR
|
|
63001
63424
|
|
|
63002
|
-
Context was compacted but the swarm is still running.
|
|
63425
|
+
Context was compacted but the swarm is still running. **YOU ARE THE COORDINATOR.**
|
|
63426
|
+
|
|
63427
|
+
Your role is ORCHESTRATION, not implementation. When you catch yourself about to do work directly, STOP.
|
|
63003
63428
|
|
|
63004
63429
|
### ⛔ NEVER DO THESE (Coordinator Anti-Patterns)
|
|
63005
63430
|
|
|
@@ -63010,9 +63435,27 @@ Context was compacted but the swarm is still running. You are the **COORDINATOR*
|
|
|
63010
63435
|
- ❌ **NEVER** implement features yourself - SPAWN A WORKER
|
|
63011
63436
|
- ❌ **NEVER** "just do it myself to save time" - NO. SPAWN A WORKER.
|
|
63012
63437
|
- ❌ **NEVER** reserve files with \`swarmmail_reserve\` - Workers reserve files
|
|
63438
|
+
- ❌ **NEVER** fetch files/docs directly - SPAWN A RESEARCHER
|
|
63013
63439
|
|
|
63014
63440
|
**If you catch yourself about to edit a file, STOP. Use \`swarm_spawn_subtask\` instead.**
|
|
63015
63441
|
|
|
63442
|
+
### \uD83D\uDEAB FORBIDDEN TOOLS (Coordinators MUST delegate these)
|
|
63443
|
+
|
|
63444
|
+
**NEVER use these tools directly. ALWAYS spawn a researcher worker via \`swarm_spawn_researcher\`:**
|
|
63445
|
+
|
|
63446
|
+
**Repository fetching:**
|
|
63447
|
+
- \`repo-crawl_file\`, \`repo-crawl_readme\`, \`repo-crawl_search\`, \`repo-crawl_structure\`, \`repo-crawl_tree\`
|
|
63448
|
+
- \`repo-autopsy_*\` (all repo-autopsy tools)
|
|
63449
|
+
|
|
63450
|
+
**Web/documentation fetching:**
|
|
63451
|
+
- \`webfetch\`, \`fetch_fetch\`
|
|
63452
|
+
- \`context7_resolve-library-id\`, \`context7_get-library-docs\`
|
|
63453
|
+
|
|
63454
|
+
**Knowledge base:**
|
|
63455
|
+
- \`pdf-brain_search\`, \`pdf-brain_read\`
|
|
63456
|
+
|
|
63457
|
+
**If you need external data:** Use \`swarm_spawn_researcher\` with a clear research task. The researcher will fetch, summarize, and return findings.
|
|
63458
|
+
|
|
63016
63459
|
### ✅ ALWAYS DO THESE (Coordinator Checklist)
|
|
63017
63460
|
|
|
63018
63461
|
On resume, execute this checklist IN ORDER:
|
|
@@ -63062,6 +63505,87 @@ Extract from session context:
|
|
|
63062
63505
|
- **Review work** - Use \`swarm_review\` and \`swarm_review_feedback\` for completed work
|
|
63063
63506
|
- **Close the loop** - When all subtasks done, verify and close the epic
|
|
63064
63507
|
|
|
63508
|
+
**You are the COORDINATOR. You orchestrate. You do NOT implement. Spawn workers.**
|
|
63509
|
+
|
|
63510
|
+
---
|
|
63511
|
+
|
|
63512
|
+
## \uD83D\uDCCB FULL COORDINATOR WORKFLOW (Reference)
|
|
63513
|
+
|
|
63514
|
+
You are ALWAYS swarming. Here is the complete workflow for any new work:
|
|
63515
|
+
|
|
63516
|
+
### Phase 1.5: Research Phase (FOR COMPLEX TASKS)
|
|
63517
|
+
|
|
63518
|
+
**If the task requires understanding unfamiliar technologies, spawn a researcher FIRST:**
|
|
63519
|
+
|
|
63520
|
+
\`\`\`
|
|
63521
|
+
swarm_spawn_researcher(
|
|
63522
|
+
research_id="research-<topic>",
|
|
63523
|
+
epic_id="<epic-id>",
|
|
63524
|
+
tech_stack=["<technology>"],
|
|
63525
|
+
project_path="<path>"
|
|
63526
|
+
)
|
|
63527
|
+
// Then spawn with Task(subagent_type="swarm/researcher", prompt="<from above>")
|
|
63528
|
+
\`\`\`
|
|
63529
|
+
|
|
63530
|
+
### Phase 2: Knowledge Gathering
|
|
63531
|
+
|
|
63532
|
+
\`\`\`
|
|
63533
|
+
semantic-memory_find(query="<task keywords>", limit=5) # Past learnings
|
|
63534
|
+
cass_search(query="<task description>", limit=5) # Similar past tasks
|
|
63535
|
+
skills_list() # Available skills
|
|
63536
|
+
\`\`\`
|
|
63537
|
+
|
|
63538
|
+
### Phase 3: Decompose
|
|
63539
|
+
|
|
63540
|
+
\`\`\`
|
|
63541
|
+
swarm_select_strategy(task="<task>")
|
|
63542
|
+
swarm_plan_prompt(task="<task>", context="<synthesized knowledge>")
|
|
63543
|
+
swarm_validate_decomposition(response="<CellTree JSON>")
|
|
63544
|
+
\`\`\`
|
|
63545
|
+
|
|
63546
|
+
### Phase 4: Create Cells
|
|
63547
|
+
|
|
63548
|
+
\`hive_create_epic(epic_title="<task>", subtasks=[...])\`
|
|
63549
|
+
|
|
63550
|
+
### Phase 5: DO NOT Reserve Files
|
|
63551
|
+
|
|
63552
|
+
> **⚠️ Coordinator NEVER reserves files.** Workers reserve their own files.
|
|
63553
|
+
|
|
63554
|
+
### Phase 6: Spawn Workers
|
|
63555
|
+
|
|
63556
|
+
\`\`\`
|
|
63557
|
+
swarm_spawn_subtask(bead_id, epic_id, title, files, shared_context, project_path)
|
|
63558
|
+
Task(subagent_type="swarm/worker", prompt="<from above>")
|
|
63559
|
+
\`\`\`
|
|
63560
|
+
|
|
63561
|
+
### Phase 7: MANDATORY Review Loop
|
|
63562
|
+
|
|
63563
|
+
**AFTER EVERY Task() RETURNS:**
|
|
63564
|
+
|
|
63565
|
+
1. \`swarmmail_inbox()\` - Check for messages
|
|
63566
|
+
2. \`swarm_review(project_key, epic_id, task_id, files_touched)\` - Generate review
|
|
63567
|
+
3. Evaluate against epic goals
|
|
63568
|
+
4. \`swarm_review_feedback(project_key, task_id, worker_id, status, issues)\`
|
|
63569
|
+
|
|
63570
|
+
**If needs_changes:**
|
|
63571
|
+
\`\`\`
|
|
63572
|
+
swarm_spawn_retry(bead_id, epic_id, original_prompt, attempt, issues, diff, files, project_path)
|
|
63573
|
+
// Spawn NEW worker with Task() using retry prompt
|
|
63574
|
+
// Max 3 attempts before marking task blocked
|
|
63575
|
+
\`\`\`
|
|
63576
|
+
|
|
63577
|
+
### Phase 8: Complete
|
|
63578
|
+
|
|
63579
|
+
\`hive_sync()\` - Sync all cells to git
|
|
63580
|
+
|
|
63581
|
+
## Strategy Reference
|
|
63582
|
+
|
|
63583
|
+
| Strategy | Best For | Keywords |
|
|
63584
|
+
| -------------- | ------------------------ | -------------------------------------- |
|
|
63585
|
+
| file-based | Refactoring, migrations | refactor, migrate, rename, update all |
|
|
63586
|
+
| feature-based | New features | add, implement, build, create, feature |
|
|
63587
|
+
| risk-based | Bug fixes, security | fix, bug, security, critical, urgent |
|
|
63588
|
+
|
|
63065
63589
|
**You are the COORDINATOR. You orchestrate. You do NOT implement. Spawn workers.**
|
|
63066
63590
|
`;
|
|
63067
63591
|
var SWARM_DETECTION_FALLBACK = `## \uD83D\uDC1D Swarm Detection - Check Your Context
|
|
@@ -63736,7 +64260,7 @@ var SwarmPlugin = async (input) => {
|
|
|
63736
64260
|
if (isInCoordinatorContext()) {
|
|
63737
64261
|
const ctx = getCoordinatorContext();
|
|
63738
64262
|
const violation = detectCoordinatorViolation({
|
|
63739
|
-
sessionId:
|
|
64263
|
+
sessionId: input2.sessionID || "unknown",
|
|
63740
64264
|
epicId: ctx.epicId || "unknown",
|
|
63741
64265
|
toolName,
|
|
63742
64266
|
toolArgs: output.args,
|