opencode-swarm 7.24.0 → 7.25.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/dist/cli/index.js +343 -65
- package/dist/hooks/hive-promoter.d.ts +12 -0
- package/dist/index.js +391 -107
- package/dist/mutation/engine.d.ts +4 -0
- package/dist/tools/knowledge-query.d.ts +6 -0
- package/dist/tools/test-runner.d.ts +10 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.
|
|
36
|
+
version: "7.25.0",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -42694,6 +42694,20 @@ function normalizeEntry(raw) {
|
|
|
42694
42694
|
ro.failed_after_shown_count = typeof ro.failed_after_count === "number" ? ro.failed_after_count : 0;
|
|
42695
42695
|
}
|
|
42696
42696
|
}
|
|
42697
|
+
try {
|
|
42698
|
+
if (typeof obj.encounter_score !== "number" || Number.isNaN(obj.encounter_score)) {
|
|
42699
|
+
obj.encounter_score = 0;
|
|
42700
|
+
}
|
|
42701
|
+
} catch {
|
|
42702
|
+
try {
|
|
42703
|
+
Object.defineProperty(obj, "encounter_score", {
|
|
42704
|
+
value: 0,
|
|
42705
|
+
writable: true,
|
|
42706
|
+
configurable: true,
|
|
42707
|
+
enumerable: true
|
|
42708
|
+
});
|
|
42709
|
+
} catch {}
|
|
42710
|
+
}
|
|
42697
42711
|
const arrayFields = [
|
|
42698
42712
|
"triggers",
|
|
42699
42713
|
"required_actions",
|
|
@@ -44618,12 +44632,26 @@ import path19 from "node:path";
|
|
|
44618
44632
|
function isAlreadyInHive(entry, hiveEntries, threshold) {
|
|
44619
44633
|
return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
|
|
44620
44634
|
}
|
|
44621
|
-
function
|
|
44635
|
+
function isHiveEligible(entry, autoPromoteDays) {
|
|
44622
44636
|
const phaseNumbers = new Set;
|
|
44623
|
-
for (const record3 of
|
|
44624
|
-
|
|
44637
|
+
for (const record3 of entry.confirmed_by ?? []) {
|
|
44638
|
+
if (record3 && typeof record3.phase_number === "number") {
|
|
44639
|
+
phaseNumbers.add(record3.phase_number);
|
|
44640
|
+
}
|
|
44641
|
+
}
|
|
44642
|
+
if (entry.hive_eligible === true && phaseNumbers.size >= 3) {
|
|
44643
|
+
return true;
|
|
44644
|
+
}
|
|
44645
|
+
if ((entry.tags ?? []).includes("hive-fast-track")) {
|
|
44646
|
+
return true;
|
|
44625
44647
|
}
|
|
44626
|
-
|
|
44648
|
+
const createdMs = Date.parse(entry.created_at);
|
|
44649
|
+
const ageMs = Number.isFinite(createdMs) ? Date.now() - createdMs : 0;
|
|
44650
|
+
const ageThresholdMs = autoPromoteDays * 86400000;
|
|
44651
|
+
if (ageMs >= ageThresholdMs) {
|
|
44652
|
+
return true;
|
|
44653
|
+
}
|
|
44654
|
+
return false;
|
|
44627
44655
|
}
|
|
44628
44656
|
function countDistinctProjects(confirmedBy) {
|
|
44629
44657
|
const projectNames = new Set;
|
|
@@ -44641,12 +44669,6 @@ function calculateEncounterScore(currentScore, isSameProject, config3) {
|
|
|
44641
44669
|
const newScore = currentScore + increment;
|
|
44642
44670
|
return Math.min(Math.max(newScore, config3.min_encounter_score), config3.max_encounter_score);
|
|
44643
44671
|
}
|
|
44644
|
-
function getEntryAgeMs(createdAt) {
|
|
44645
|
-
const createdTime = new Date(createdAt).getTime();
|
|
44646
|
-
if (Number.isNaN(createdTime))
|
|
44647
|
-
return 0;
|
|
44648
|
-
return Date.now() - createdTime;
|
|
44649
|
-
}
|
|
44650
44672
|
async function checkHivePromotions(swarmEntries, config3) {
|
|
44651
44673
|
let newPromotions = 0;
|
|
44652
44674
|
let encountersIncremented = 0;
|
|
@@ -44665,19 +44687,7 @@ async function checkHivePromotions(swarmEntries, config3) {
|
|
|
44665
44687
|
if (isAlreadyInHive(swarmEntry, hiveEntries, config3.dedup_threshold)) {
|
|
44666
44688
|
continue;
|
|
44667
44689
|
}
|
|
44668
|
-
|
|
44669
|
-
if (swarmEntry.hive_eligible === true && countDistinctPhases(swarmEntry.confirmed_by) >= 3) {
|
|
44670
|
-
shouldPromote = true;
|
|
44671
|
-
}
|
|
44672
|
-
if (swarmEntry.tags.includes("hive-fast-track")) {
|
|
44673
|
-
shouldPromote = true;
|
|
44674
|
-
}
|
|
44675
|
-
const ageMs = getEntryAgeMs(swarmEntry.created_at);
|
|
44676
|
-
const ageThresholdMs = config3.auto_promote_days * 86400000;
|
|
44677
|
-
if (ageMs >= ageThresholdMs) {
|
|
44678
|
-
shouldPromote = true;
|
|
44679
|
-
}
|
|
44680
|
-
if (!shouldPromote) {
|
|
44690
|
+
if (!isHiveEligible(swarmEntry, config3.auto_promote_days)) {
|
|
44681
44691
|
continue;
|
|
44682
44692
|
}
|
|
44683
44693
|
const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
|
|
@@ -46554,12 +46564,14 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
46554
46564
|
if (planExists) {
|
|
46555
46565
|
planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
|
|
46556
46566
|
}
|
|
46557
|
-
const
|
|
46567
|
+
const { config: loadedConfig } = loadPluginConfigWithMeta(directory);
|
|
46568
|
+
const config3 = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
|
|
46558
46569
|
const projectName = planData.title ?? "Unknown Project";
|
|
46559
46570
|
const closedPhases = [];
|
|
46560
46571
|
const closedTasks = [];
|
|
46561
46572
|
const warnings = [];
|
|
46562
46573
|
let hivePromoted = 0;
|
|
46574
|
+
let hiveSkipped = 0;
|
|
46563
46575
|
if (!planAlreadyDone) {
|
|
46564
46576
|
for (const phase of inProgressPhases) {
|
|
46565
46577
|
closedPhases.push(phase.id);
|
|
@@ -46682,23 +46694,35 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
46682
46694
|
await fs13.unlink(lessonsFilePath).catch(() => {});
|
|
46683
46695
|
}
|
|
46684
46696
|
if (curationSucceeded) {
|
|
46685
|
-
|
|
46686
|
-
|
|
46687
|
-
|
|
46688
|
-
|
|
46689
|
-
|
|
46690
|
-
|
|
46691
|
-
|
|
46692
|
-
|
|
46693
|
-
|
|
46694
|
-
|
|
46695
|
-
|
|
46697
|
+
if (config3.hive_enabled === false) {} else {
|
|
46698
|
+
try {
|
|
46699
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
46700
|
+
const entries = await readKnowledge(knowledgePath);
|
|
46701
|
+
const autoPromoteDays = config3.auto_promote_days;
|
|
46702
|
+
if (entries.length > 0) {
|
|
46703
|
+
for (const entry of entries) {
|
|
46704
|
+
if (!isHiveEligible(entry, autoPromoteDays)) {
|
|
46705
|
+
hiveSkipped++;
|
|
46706
|
+
continue;
|
|
46707
|
+
}
|
|
46708
|
+
try {
|
|
46709
|
+
const result = await promoteToHive(directory, entry.lesson, entry.category);
|
|
46710
|
+
if (!result.includes("already exists")) {
|
|
46711
|
+
hivePromoted++;
|
|
46712
|
+
}
|
|
46713
|
+
} catch (promotionErr) {
|
|
46714
|
+
const msg = promotionErr instanceof Error ? promotionErr.message : String(promotionErr);
|
|
46715
|
+
warnings.push(`Hive promotion skipped for lesson: ${msg}`);
|
|
46716
|
+
}
|
|
46717
|
+
}
|
|
46718
|
+
if (hiveSkipped > 0) {
|
|
46719
|
+
warnings.push(`${hiveSkipped} swarm knowledge entr${hiveSkipped === 1 ? "y" : "ies"} not eligible for hive promotion`);
|
|
46696
46720
|
}
|
|
46697
46721
|
}
|
|
46722
|
+
} catch (hiveErr) {
|
|
46723
|
+
const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
|
|
46724
|
+
warnings.push(`Hive promotion failed: ${msg}`);
|
|
46698
46725
|
}
|
|
46699
|
-
} catch (hiveErr) {
|
|
46700
|
-
const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
|
|
46701
|
-
warnings.push(`Hive promotion failed: ${msg}`);
|
|
46702
46726
|
}
|
|
46703
46727
|
}
|
|
46704
46728
|
const fallbackKnowledgeCreated = curationResult?.stored ?? 0;
|
|
@@ -46715,8 +46739,8 @@ async function handleCloseCommand(directory, args2, options = {}) {
|
|
|
46715
46739
|
let skillReviewSummary = "";
|
|
46716
46740
|
if (runSkillReview) {
|
|
46717
46741
|
try {
|
|
46718
|
-
const { config:
|
|
46719
|
-
const skillImproverConfig = SkillImproverConfigSchema.parse(
|
|
46742
|
+
const { config: loadedConfig2 } = loadPluginConfigWithMeta(directory);
|
|
46743
|
+
const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig2.skill_improver ?? {});
|
|
46720
46744
|
const skillReviewResult = await runAbortableSkillReview({
|
|
46721
46745
|
directory,
|
|
46722
46746
|
config: skillImproverConfig,
|
|
@@ -47081,7 +47105,6 @@ var init_close = __esm(() => {
|
|
|
47081
47105
|
"handoff-prompt.md",
|
|
47082
47106
|
"handoff-consumed.md",
|
|
47083
47107
|
"escalation-report.md",
|
|
47084
|
-
"knowledge.jsonl",
|
|
47085
47108
|
"knowledge-rejected.jsonl",
|
|
47086
47109
|
"repo-graph.json",
|
|
47087
47110
|
"doc-manifest.json",
|
|
@@ -54967,7 +54990,14 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
54967
54990
|
return args2;
|
|
54968
54991
|
}
|
|
54969
54992
|
case "vitest": {
|
|
54970
|
-
const args2 = [
|
|
54993
|
+
const args2 = [
|
|
54994
|
+
"npx",
|
|
54995
|
+
"vitest",
|
|
54996
|
+
"run",
|
|
54997
|
+
"--reporter=json",
|
|
54998
|
+
"--outputFile",
|
|
54999
|
+
".swarm/cache/test-runner-vitest.json"
|
|
55000
|
+
];
|
|
54971
55001
|
if (coverage)
|
|
54972
55002
|
args2.push("--coverage");
|
|
54973
55003
|
if (scope !== "all" && files.length > 0)
|
|
@@ -54975,7 +55005,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
54975
55005
|
return args2;
|
|
54976
55006
|
}
|
|
54977
55007
|
case "jest": {
|
|
54978
|
-
const args2 = ["npx", "jest"];
|
|
55008
|
+
const args2 = ["npx", "jest", "--json"];
|
|
54979
55009
|
if (coverage)
|
|
54980
55010
|
args2.push("--coverage");
|
|
54981
55011
|
if (scope !== "all" && files.length > 0)
|
|
@@ -56210,6 +56240,42 @@ function sanitizeChangedFiles(changedFiles) {
|
|
|
56210
56240
|
const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !DANGEROUS_PROPERTY_NAMES.has(f));
|
|
56211
56241
|
return validFiles.slice(0, MAX_CHANGED_FILES);
|
|
56212
56242
|
}
|
|
56243
|
+
function isTestRunResult(value) {
|
|
56244
|
+
return value === "pass" || value === "fail" || value === "skip";
|
|
56245
|
+
}
|
|
56246
|
+
function parseStoredRecord(value) {
|
|
56247
|
+
if (typeof value !== "object" || value === null)
|
|
56248
|
+
return null;
|
|
56249
|
+
const record3 = value;
|
|
56250
|
+
if (typeof record3.testFile !== "string" || record3.testFile.length === 0) {
|
|
56251
|
+
return null;
|
|
56252
|
+
}
|
|
56253
|
+
if (typeof record3.testName !== "string" || record3.testName.length === 0) {
|
|
56254
|
+
return null;
|
|
56255
|
+
}
|
|
56256
|
+
if (typeof record3.taskId !== "string" || record3.taskId.length === 0) {
|
|
56257
|
+
return null;
|
|
56258
|
+
}
|
|
56259
|
+
if (!isTestRunResult(record3.result))
|
|
56260
|
+
return null;
|
|
56261
|
+
if (typeof record3.durationMs !== "number" || !Number.isFinite(record3.durationMs)) {
|
|
56262
|
+
return null;
|
|
56263
|
+
}
|
|
56264
|
+
if (typeof record3.timestamp !== "string" || Number.isNaN(Date.parse(record3.timestamp))) {
|
|
56265
|
+
return null;
|
|
56266
|
+
}
|
|
56267
|
+
return {
|
|
56268
|
+
timestamp: record3.timestamp,
|
|
56269
|
+
taskId: record3.taskId,
|
|
56270
|
+
testFile: record3.testFile,
|
|
56271
|
+
testName: record3.testName,
|
|
56272
|
+
result: record3.result,
|
|
56273
|
+
durationMs: Math.max(0, record3.durationMs),
|
|
56274
|
+
errorMessage: typeof record3.errorMessage === "string" ? sanitizeErrorMessage(record3.errorMessage) : undefined,
|
|
56275
|
+
stackPrefix: typeof record3.stackPrefix === "string" ? sanitizeStackPrefix(record3.stackPrefix) : undefined,
|
|
56276
|
+
changedFiles: sanitizeChangedFiles(Array.isArray(record3.changedFiles) ? record3.changedFiles : [])
|
|
56277
|
+
};
|
|
56278
|
+
}
|
|
56213
56279
|
function appendTestRun(record3, workingDir) {
|
|
56214
56280
|
if (typeof record3.testFile !== "string" || record3.testFile.length === 0) {
|
|
56215
56281
|
throw new TypeError("testFile must be a non-empty string");
|
|
@@ -56247,16 +56313,16 @@ function appendTestRun(record3, workingDir) {
|
|
|
56247
56313
|
}
|
|
56248
56314
|
const existingRecords = readAllRecords(historyPath);
|
|
56249
56315
|
existingRecords.push(sanitizedRecord);
|
|
56250
|
-
const
|
|
56316
|
+
const recordsByTest = new Map;
|
|
56251
56317
|
for (const rec of existingRecords) {
|
|
56252
|
-
const
|
|
56253
|
-
if (!
|
|
56254
|
-
|
|
56318
|
+
const normalizedKey = `${rec.testFile.toLowerCase()}|${rec.testName.toLowerCase()}`;
|
|
56319
|
+
if (!recordsByTest.has(normalizedKey)) {
|
|
56320
|
+
recordsByTest.set(normalizedKey, []);
|
|
56255
56321
|
}
|
|
56256
|
-
|
|
56322
|
+
recordsByTest.get(normalizedKey).push(rec);
|
|
56257
56323
|
}
|
|
56258
56324
|
const prunedRecords = [];
|
|
56259
|
-
for (const [, records] of
|
|
56325
|
+
for (const [, records] of recordsByTest) {
|
|
56260
56326
|
records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
56261
56327
|
const toKeep = records.slice(-MAX_HISTORY_PER_TEST);
|
|
56262
56328
|
prunedRecords.push(...toKeep);
|
|
@@ -56296,8 +56362,9 @@ function readAllRecords(historyPath) {
|
|
|
56296
56362
|
}
|
|
56297
56363
|
try {
|
|
56298
56364
|
const parsed = JSON.parse(trimmed);
|
|
56299
|
-
|
|
56300
|
-
|
|
56365
|
+
const record3 = parseStoredRecord(parsed);
|
|
56366
|
+
if (record3) {
|
|
56367
|
+
records.push(record3);
|
|
56301
56368
|
}
|
|
56302
56369
|
} catch {}
|
|
56303
56370
|
}
|
|
@@ -57336,7 +57403,14 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
57336
57403
|
return args2;
|
|
57337
57404
|
}
|
|
57338
57405
|
case "vitest": {
|
|
57339
|
-
const args2 = [
|
|
57406
|
+
const args2 = [
|
|
57407
|
+
"npx",
|
|
57408
|
+
"vitest",
|
|
57409
|
+
"run",
|
|
57410
|
+
"--reporter=json",
|
|
57411
|
+
"--outputFile",
|
|
57412
|
+
VITEST_JSON_OUTPUT_RELATIVE_PATH
|
|
57413
|
+
];
|
|
57340
57414
|
if (coverage)
|
|
57341
57415
|
args2.push("--coverage");
|
|
57342
57416
|
if (scope !== "all" && files.length > 0) {
|
|
@@ -57345,7 +57419,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
57345
57419
|
return args2;
|
|
57346
57420
|
}
|
|
57347
57421
|
case "jest": {
|
|
57348
|
-
const args2 = ["npx", "jest"];
|
|
57422
|
+
const args2 = ["npx", "jest", "--json"];
|
|
57349
57423
|
if (coverage)
|
|
57350
57424
|
args2.push("--coverage");
|
|
57351
57425
|
if (scope !== "all" && files.length > 0) {
|
|
@@ -57441,6 +57515,122 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
57441
57515
|
return null;
|
|
57442
57516
|
}
|
|
57443
57517
|
}
|
|
57518
|
+
function mapFrameworkStatusToResult(status) {
|
|
57519
|
+
if (typeof status !== "string")
|
|
57520
|
+
return null;
|
|
57521
|
+
const normalized = status.toLowerCase();
|
|
57522
|
+
if (normalized === "pass" || normalized === "passed")
|
|
57523
|
+
return "pass";
|
|
57524
|
+
if (normalized === "fail" || normalized === "failed")
|
|
57525
|
+
return "fail";
|
|
57526
|
+
if (normalized === "skip" || normalized === "skipped" || normalized === "pending" || normalized === "todo") {
|
|
57527
|
+
return "skip";
|
|
57528
|
+
}
|
|
57529
|
+
return null;
|
|
57530
|
+
}
|
|
57531
|
+
function firstLine(value) {
|
|
57532
|
+
if (typeof value !== "string")
|
|
57533
|
+
return;
|
|
57534
|
+
const line = value.split(`
|
|
57535
|
+
`).find((part) => part.trim().length > 0)?.trim();
|
|
57536
|
+
return line && line.length > 0 ? line : undefined;
|
|
57537
|
+
}
|
|
57538
|
+
function parseJestLikeJsonTestResults(payload) {
|
|
57539
|
+
if (typeof payload !== "object" || payload === null)
|
|
57540
|
+
return [];
|
|
57541
|
+
const rawSuites = payload.testResults;
|
|
57542
|
+
if (!Array.isArray(rawSuites))
|
|
57543
|
+
return [];
|
|
57544
|
+
const parsed = [];
|
|
57545
|
+
for (const suite of rawSuites) {
|
|
57546
|
+
if (typeof suite !== "object" || suite === null)
|
|
57547
|
+
continue;
|
|
57548
|
+
const suiteObj = suite;
|
|
57549
|
+
const rawFile = typeof suiteObj.name === "string" ? suiteObj.name : typeof suiteObj.testFilePath === "string" ? suiteObj.testFilePath : undefined;
|
|
57550
|
+
if (!rawFile)
|
|
57551
|
+
continue;
|
|
57552
|
+
const testFile = rawFile.replace(/\\/g, "/");
|
|
57553
|
+
const assertionResults = suiteObj.assertionResults;
|
|
57554
|
+
if (!Array.isArray(assertionResults))
|
|
57555
|
+
continue;
|
|
57556
|
+
for (const assertion of assertionResults) {
|
|
57557
|
+
if (typeof assertion !== "object" || assertion === null)
|
|
57558
|
+
continue;
|
|
57559
|
+
const assertionObj = assertion;
|
|
57560
|
+
const result = mapFrameworkStatusToResult(assertionObj.status);
|
|
57561
|
+
const testName = typeof assertionObj.fullName === "string" ? assertionObj.fullName : typeof assertionObj.title === "string" ? assertionObj.title : undefined;
|
|
57562
|
+
if (!result || !testName || testName.length === 0)
|
|
57563
|
+
continue;
|
|
57564
|
+
const failureMessages = Array.isArray(assertionObj.failureMessages) ? assertionObj.failureMessages : [];
|
|
57565
|
+
const firstFailure = failureMessages.find((entry) => typeof entry === "string" && entry.length > 0);
|
|
57566
|
+
const durationMs = typeof assertionObj.duration === "number" && Number.isFinite(assertionObj.duration) ? Math.max(assertionObj.duration, 0) : 0;
|
|
57567
|
+
parsed.push({
|
|
57568
|
+
testFile,
|
|
57569
|
+
testName,
|
|
57570
|
+
result,
|
|
57571
|
+
durationMs,
|
|
57572
|
+
errorMessage: firstLine(firstFailure),
|
|
57573
|
+
stackPrefix: firstLine(firstFailure)
|
|
57574
|
+
});
|
|
57575
|
+
}
|
|
57576
|
+
}
|
|
57577
|
+
return parsed;
|
|
57578
|
+
}
|
|
57579
|
+
function parseBunJsonLines(output) {
|
|
57580
|
+
const parsed = [];
|
|
57581
|
+
for (const line of output.split(`
|
|
57582
|
+
`)) {
|
|
57583
|
+
const trimmed = line.trim();
|
|
57584
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
|
|
57585
|
+
continue;
|
|
57586
|
+
try {
|
|
57587
|
+
const obj = JSON.parse(trimmed);
|
|
57588
|
+
const rawFile = typeof obj.file === "string" ? obj.file : typeof obj.testFile === "string" ? obj.testFile : typeof obj.path === "string" ? obj.path : undefined;
|
|
57589
|
+
const rawName = typeof obj.testName === "string" ? obj.testName : typeof obj.fullName === "string" ? obj.fullName : typeof obj.name === "string" ? obj.name : undefined;
|
|
57590
|
+
const result = mapFrameworkStatusToResult(typeof obj.status === "string" ? obj.status : obj.result);
|
|
57591
|
+
if (!rawFile || !rawName || !result)
|
|
57592
|
+
continue;
|
|
57593
|
+
const errorObj = typeof obj.error === "object" && obj.error !== null ? obj.error : undefined;
|
|
57594
|
+
const durationMs = typeof obj.durationMs === "number" && Number.isFinite(obj.durationMs) ? Math.max(obj.durationMs, 0) : typeof obj.duration === "number" && Number.isFinite(obj.duration) ? Math.max(obj.duration, 0) : 0;
|
|
57595
|
+
parsed.push({
|
|
57596
|
+
testFile: rawFile.replace(/\\/g, "/"),
|
|
57597
|
+
testName: rawName,
|
|
57598
|
+
result,
|
|
57599
|
+
durationMs,
|
|
57600
|
+
errorMessage: firstLine(errorObj?.message ?? obj.errorMessage),
|
|
57601
|
+
stackPrefix: firstLine(errorObj?.stack)
|
|
57602
|
+
});
|
|
57603
|
+
} catch {}
|
|
57604
|
+
}
|
|
57605
|
+
return parsed;
|
|
57606
|
+
}
|
|
57607
|
+
function parseFrameworkJsonTestResults(framework, output) {
|
|
57608
|
+
const jsonMatch = output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);
|
|
57609
|
+
if (jsonMatch) {
|
|
57610
|
+
try {
|
|
57611
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
57612
|
+
const testResults = parseJestLikeJsonTestResults(parsed);
|
|
57613
|
+
if (testResults.length > 0)
|
|
57614
|
+
return testResults;
|
|
57615
|
+
} catch {}
|
|
57616
|
+
}
|
|
57617
|
+
for (const line of output.split(`
|
|
57618
|
+
`)) {
|
|
57619
|
+
const trimmed = line.trim();
|
|
57620
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
|
|
57621
|
+
continue;
|
|
57622
|
+
try {
|
|
57623
|
+
const parsed = JSON.parse(trimmed);
|
|
57624
|
+
const testResults = parseJestLikeJsonTestResults(parsed);
|
|
57625
|
+
if (testResults.length > 0)
|
|
57626
|
+
return testResults;
|
|
57627
|
+
} catch {}
|
|
57628
|
+
}
|
|
57629
|
+
if (framework === "bun") {
|
|
57630
|
+
return parseBunJsonLines(output);
|
|
57631
|
+
}
|
|
57632
|
+
return [];
|
|
57633
|
+
}
|
|
57444
57634
|
function parseTestOutput2(framework, output) {
|
|
57445
57635
|
const totals = {
|
|
57446
57636
|
passed: 0,
|
|
@@ -57728,7 +57918,16 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
57728
57918
|
};
|
|
57729
57919
|
}
|
|
57730
57920
|
const startTime = Date.now();
|
|
57921
|
+
const vitestJsonOutputPath = framework === "vitest" ? path46.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
57731
57922
|
try {
|
|
57923
|
+
if (vitestJsonOutputPath) {
|
|
57924
|
+
try {
|
|
57925
|
+
fs29.mkdirSync(path46.dirname(vitestJsonOutputPath), { recursive: true });
|
|
57926
|
+
if (fs29.existsSync(vitestJsonOutputPath)) {
|
|
57927
|
+
fs29.unlinkSync(vitestJsonOutputPath);
|
|
57928
|
+
}
|
|
57929
|
+
} catch {}
|
|
57930
|
+
}
|
|
57732
57931
|
const proc = bunSpawn(command, {
|
|
57733
57932
|
stdout: "pipe",
|
|
57734
57933
|
stderr: "pipe",
|
|
@@ -57749,13 +57948,37 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
57749
57948
|
output += (output ? `
|
|
57750
57949
|
` : "") + stderrResult.text;
|
|
57751
57950
|
}
|
|
57951
|
+
if (vitestJsonOutputPath) {
|
|
57952
|
+
try {
|
|
57953
|
+
if (fs29.existsSync(vitestJsonOutputPath)) {
|
|
57954
|
+
const vitestJsonOutput = fs29.readFileSync(vitestJsonOutputPath, "utf-8");
|
|
57955
|
+
if (vitestJsonOutput.trim().length > 0) {
|
|
57956
|
+
output += (output ? `
|
|
57957
|
+
` : "") + vitestJsonOutput;
|
|
57958
|
+
}
|
|
57959
|
+
}
|
|
57960
|
+
} catch {}
|
|
57961
|
+
}
|
|
57752
57962
|
if (stdoutResult.truncated || stderrResult.truncated) {
|
|
57753
57963
|
output += `
|
|
57754
57964
|
... (output truncated at stream read limit)`;
|
|
57755
57965
|
}
|
|
57756
57966
|
const useDispatchParse = process.env.SWARM_LANG_BACKEND !== "legacy";
|
|
57757
57967
|
const parsed = useDispatchParse ? await parseTestOutputViaDispatch(framework, output, cwd) ?? parseTestOutput2(framework, output) : parseTestOutput2(framework, output);
|
|
57758
|
-
const
|
|
57968
|
+
const parsedTestCases = parseFrameworkJsonTestResults(framework, output);
|
|
57969
|
+
const totals = { ...parsed.totals };
|
|
57970
|
+
const { coveragePercent } = parsed;
|
|
57971
|
+
if (totals.total === 0 && parsedTestCases.length > 0) {
|
|
57972
|
+
for (const entry of parsedTestCases) {
|
|
57973
|
+
if (entry.result === "pass")
|
|
57974
|
+
totals.passed++;
|
|
57975
|
+
else if (entry.result === "fail")
|
|
57976
|
+
totals.failed++;
|
|
57977
|
+
else
|
|
57978
|
+
totals.skipped++;
|
|
57979
|
+
}
|
|
57980
|
+
totals.total = parsedTestCases.length;
|
|
57981
|
+
}
|
|
57759
57982
|
const isTimeout = exitCode === -1;
|
|
57760
57983
|
const testPassed = exitCode === 0 && totals.failed === 0;
|
|
57761
57984
|
if (testPassed) {
|
|
@@ -57768,7 +57991,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
57768
57991
|
duration_ms,
|
|
57769
57992
|
totals,
|
|
57770
57993
|
rawOutput: output,
|
|
57771
|
-
outcome: "pass"
|
|
57994
|
+
outcome: "pass",
|
|
57995
|
+
testCases: parsedTestCases
|
|
57772
57996
|
};
|
|
57773
57997
|
if (coveragePercent !== undefined) {
|
|
57774
57998
|
result.coveragePercent = coveragePercent;
|
|
@@ -57790,7 +58014,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
57790
58014
|
rawOutput: output,
|
|
57791
58015
|
error: isTimeout ? `Tests timed out after ${timeout_ms}ms` : `Tests failed with ${totals.failed} failures`,
|
|
57792
58016
|
message: isTimeout ? `${framework} tests timed out after ${timeout_ms}ms` : `${framework} tests failed (${totals.failed}/${totals.total} failed)`,
|
|
57793
|
-
outcome: isTimeout ? "error" : "regression"
|
|
58017
|
+
outcome: isTimeout ? "error" : "regression",
|
|
58018
|
+
testCases: parsedTestCases
|
|
57794
58019
|
};
|
|
57795
58020
|
if (coveragePercent !== undefined) {
|
|
57796
58021
|
result.coveragePercent = coveragePercent;
|
|
@@ -57811,25 +58036,78 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
57811
58036
|
};
|
|
57812
58037
|
}
|
|
57813
58038
|
}
|
|
57814
|
-
function
|
|
58039
|
+
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
58040
|
+
const normalized = testFile.replace(/\\/g, "/");
|
|
58041
|
+
if (!path46.isAbsolute(testFile))
|
|
58042
|
+
return normalized;
|
|
58043
|
+
const relative9 = path46.relative(workingDir, testFile);
|
|
58044
|
+
if (relative9.startsWith("..") || path46.isAbsolute(relative9)) {
|
|
58045
|
+
return normalized;
|
|
58046
|
+
}
|
|
58047
|
+
return relative9.replace(/\\/g, "/");
|
|
58048
|
+
}
|
|
58049
|
+
function combineAggregateResult(current, next) {
|
|
58050
|
+
if (current === "fail" || next === "fail")
|
|
58051
|
+
return "fail";
|
|
58052
|
+
if (current === "pass" || next === "pass")
|
|
58053
|
+
return "pass";
|
|
58054
|
+
return "skip";
|
|
58055
|
+
}
|
|
58056
|
+
function recordAndAnalyzeResults(result, testFiles, workingDir, sourceFiles, parsedTestCases) {
|
|
57815
58057
|
if (!result.totals || result.totals.total === 0)
|
|
57816
58058
|
return;
|
|
57817
58059
|
const now = new Date().toISOString();
|
|
57818
58060
|
const changedFiles = (sourceFiles && sourceFiles.length > 0 ? sourceFiles : testFiles).map((f) => f.replace(/\\/g, "/"));
|
|
57819
|
-
|
|
58061
|
+
const aggregateResultsByFile = new Map;
|
|
58062
|
+
const validParsedCases = parsedTestCases?.filter((parsedCase) => parsedCase.testFile.length > 0 && parsedCase.testName.length > 0) ?? [];
|
|
58063
|
+
for (const parsedCase of validParsedCases) {
|
|
58064
|
+
const normalizedTestFile = normalizeHistoryTestFile(parsedCase.testFile, workingDir);
|
|
57820
58065
|
try {
|
|
57821
58066
|
appendTestRun({
|
|
57822
58067
|
timestamp: now,
|
|
57823
58068
|
taskId: "auto",
|
|
57824
|
-
testFile:
|
|
57825
|
-
testName:
|
|
57826
|
-
result: result
|
|
58069
|
+
testFile: normalizedTestFile,
|
|
58070
|
+
testName: parsedCase.testName,
|
|
58071
|
+
result: parsedCase.result,
|
|
58072
|
+
durationMs: parsedCase.durationMs,
|
|
58073
|
+
errorMessage: parsedCase.errorMessage,
|
|
58074
|
+
stackPrefix: parsedCase.stackPrefix,
|
|
58075
|
+
changedFiles
|
|
58076
|
+
}, workingDir);
|
|
58077
|
+
} catch {}
|
|
58078
|
+
aggregateResultsByFile.set(normalizedTestFile, combineAggregateResult(aggregateResultsByFile.get(normalizedTestFile), parsedCase.result));
|
|
58079
|
+
}
|
|
58080
|
+
if (aggregateResultsByFile.size === 0) {
|
|
58081
|
+
const aggregateResult = result.success ? "pass" : "fail";
|
|
58082
|
+
for (const testFile of testFiles) {
|
|
58083
|
+
aggregateResultsByFile.set(testFile.replace(/\\/g, "/"), aggregateResult);
|
|
58084
|
+
}
|
|
58085
|
+
}
|
|
58086
|
+
for (const [testFile, aggregateResult] of aggregateResultsByFile) {
|
|
58087
|
+
try {
|
|
58088
|
+
appendTestRun({
|
|
58089
|
+
timestamp: now,
|
|
58090
|
+
taskId: "auto",
|
|
58091
|
+
testFile,
|
|
58092
|
+
testName: AGGREGATE_TEST_NAME,
|
|
58093
|
+
result: aggregateResult,
|
|
57827
58094
|
durationMs: result.duration_ms || 0,
|
|
57828
58095
|
changedFiles
|
|
57829
58096
|
}, workingDir);
|
|
57830
58097
|
} catch {}
|
|
57831
58098
|
}
|
|
57832
58099
|
}
|
|
58100
|
+
function selectHistoryForAnalysis(history) {
|
|
58101
|
+
const filesWithIndividualRecords = new Set;
|
|
58102
|
+
for (const record3 of history) {
|
|
58103
|
+
if (record3.testName !== AGGREGATE_TEST_NAME) {
|
|
58104
|
+
filesWithIndividualRecords.add(record3.testFile.toLowerCase());
|
|
58105
|
+
}
|
|
58106
|
+
}
|
|
58107
|
+
if (filesWithIndividualRecords.size === 0)
|
|
58108
|
+
return history;
|
|
58109
|
+
return history.filter((record3) => record3.testName !== AGGREGATE_TEST_NAME || !filesWithIndividualRecords.has(record3.testFile.toLowerCase()));
|
|
58110
|
+
}
|
|
57833
58111
|
function analyzeFailures(workingDir) {
|
|
57834
58112
|
const report = {
|
|
57835
58113
|
flakyTests: [],
|
|
@@ -57837,7 +58115,7 @@ function analyzeFailures(workingDir) {
|
|
|
57837
58115
|
quarantinedFailures: []
|
|
57838
58116
|
};
|
|
57839
58117
|
try {
|
|
57840
|
-
const history = getAllHistory(workingDir);
|
|
58118
|
+
const history = selectHistoryForAnalysis(getAllHistory(workingDir));
|
|
57841
58119
|
if (history.length === 0)
|
|
57842
58120
|
return report;
|
|
57843
58121
|
report.flakyTests = detectFlakyTests(history);
|
|
@@ -57858,7 +58136,7 @@ function analyzeFailures(workingDir) {
|
|
|
57858
58136
|
} catch {}
|
|
57859
58137
|
return report;
|
|
57860
58138
|
}
|
|
57861
|
-
var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, MAX_SAFE_SOURCE_FILES = 1, POWERSHELL_METACHARACTERS, DISPATCH_FRAMEWORK_MAP, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
|
|
58139
|
+
var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, MAX_SAFE_SOURCE_FILES = 1, AGGREGATE_TEST_NAME = "(aggregate)", VITEST_JSON_OUTPUT_RELATIVE_PATH = ".swarm/cache/test-runner-vitest.json", POWERSHELL_METACHARACTERS, DISPATCH_FRAMEWORK_MAP, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
|
|
57862
58140
|
var init_test_runner = __esm(() => {
|
|
57863
58141
|
init_zod();
|
|
57864
58142
|
init_discovery();
|
|
@@ -58304,7 +58582,7 @@ var init_test_runner = __esm(() => {
|
|
|
58304
58582
|
return JSON.stringify(errorResult, null, 2);
|
|
58305
58583
|
}
|
|
58306
58584
|
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir);
|
|
58307
|
-
recordAndAnalyzeResults(result, testFiles, workingDir, _files.length > 0 ? _files : undefined);
|
|
58585
|
+
recordAndAnalyzeResults(result, testFiles, workingDir, _files.length > 0 ? _files : undefined, result.testCases);
|
|
58308
58586
|
let historyReport;
|
|
58309
58587
|
if (!result.success && result.totals && result.totals.failed > 0) {
|
|
58310
58588
|
historyReport = analyzeFailures(workingDir);
|
|
@@ -59981,7 +60259,7 @@ var init_reset_session = __esm(() => {
|
|
|
59981
60259
|
});
|
|
59982
60260
|
|
|
59983
60261
|
// src/summaries/manager.ts
|
|
59984
|
-
import { mkdirSync as
|
|
60262
|
+
import { mkdirSync as mkdirSync15, readdirSync as readdirSync13, renameSync as renameSync11, rmSync as rmSync4, statSync as statSync12 } from "node:fs";
|
|
59985
60263
|
import * as path50 from "node:path";
|
|
59986
60264
|
function sanitizeSummaryId(id) {
|
|
59987
60265
|
if (!id || id.length === 0) {
|
|
@@ -60027,7 +60305,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
60027
60305
|
originalBytes: Buffer.byteLength(fullOutput, "utf8")
|
|
60028
60306
|
};
|
|
60029
60307
|
const entryJson = JSON.stringify(entry);
|
|
60030
|
-
|
|
60308
|
+
mkdirSync15(summaryDir, { recursive: true });
|
|
60031
60309
|
const tempPath = path50.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
|
|
60032
60310
|
try {
|
|
60033
60311
|
await bunWrite(tempPath, entryJson);
|
|
@@ -67144,12 +67422,12 @@ __export(exports_evidence_summary_integration, {
|
|
|
67144
67422
|
createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
|
|
67145
67423
|
EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
|
|
67146
67424
|
});
|
|
67147
|
-
import { existsSync as existsSync32, mkdirSync as
|
|
67425
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync17, writeFileSync as writeFileSync8 } from "node:fs";
|
|
67148
67426
|
import * as path57 from "node:path";
|
|
67149
67427
|
function persistSummary(projectDir, artifact, filename) {
|
|
67150
67428
|
const swarmPath = path57.join(projectDir, ".swarm");
|
|
67151
67429
|
if (!existsSync32(swarmPath)) {
|
|
67152
|
-
|
|
67430
|
+
mkdirSync17(swarmPath, { recursive: true });
|
|
67153
67431
|
}
|
|
67154
67432
|
const artifactPath = path57.join(swarmPath, filename);
|
|
67155
67433
|
const content = JSON.stringify(artifact, null, 2);
|
|
@@ -72079,7 +72357,7 @@ var init_curator_drift = __esm(() => {
|
|
|
72079
72357
|
var exports_project_context = {};
|
|
72080
72358
|
__export(exports_project_context, {
|
|
72081
72359
|
buildProjectContext: () => buildProjectContext,
|
|
72082
|
-
_internals: () =>
|
|
72360
|
+
_internals: () => _internals56,
|
|
72083
72361
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
72084
72362
|
});
|
|
72085
72363
|
import * as fs112 from "node:fs";
|
|
@@ -72163,7 +72441,7 @@ function selectLintCommand(backend, directory) {
|
|
|
72163
72441
|
return null;
|
|
72164
72442
|
}
|
|
72165
72443
|
async function buildProjectContext(directory) {
|
|
72166
|
-
const backend = await
|
|
72444
|
+
const backend = await _internals56.pickBackend(directory);
|
|
72167
72445
|
if (!backend)
|
|
72168
72446
|
return null;
|
|
72169
72447
|
const ctx = emptyProjectContext();
|
|
@@ -72194,16 +72472,16 @@ async function buildProjectContext(directory) {
|
|
|
72194
72472
|
if (backend.prompts.reviewerChecklist.length > 0) {
|
|
72195
72473
|
ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
|
|
72196
72474
|
}
|
|
72197
|
-
const profiles =
|
|
72475
|
+
const profiles = _internals56.pickedProfiles(directory);
|
|
72198
72476
|
if (profiles.length > 1) {
|
|
72199
72477
|
ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
|
|
72200
72478
|
}
|
|
72201
72479
|
return ctx;
|
|
72202
72480
|
}
|
|
72203
|
-
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300,
|
|
72481
|
+
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals56;
|
|
72204
72482
|
var init_project_context = __esm(() => {
|
|
72205
72483
|
init_dispatch();
|
|
72206
|
-
|
|
72484
|
+
_internals56 = {
|
|
72207
72485
|
pickBackend,
|
|
72208
72486
|
pickedProfiles
|
|
72209
72487
|
};
|
|
@@ -73096,7 +73374,7 @@ init_state();
|
|
|
73096
73374
|
init_utils();
|
|
73097
73375
|
init_bun_compat();
|
|
73098
73376
|
init_utils2();
|
|
73099
|
-
import { renameSync as renameSync13, unlinkSync as
|
|
73377
|
+
import { renameSync as renameSync13, unlinkSync as unlinkSync11 } from "node:fs";
|
|
73100
73378
|
import * as nodePath2 from "node:path";
|
|
73101
73379
|
function createAgentActivityHooks(config3, directory) {
|
|
73102
73380
|
if (config3.hooks?.agent_activity === false) {
|
|
@@ -73174,7 +73452,7 @@ async function doFlush(directory) {
|
|
|
73174
73452
|
renameSync13(tempPath, path62);
|
|
73175
73453
|
} catch (writeError) {
|
|
73176
73454
|
try {
|
|
73177
|
-
|
|
73455
|
+
unlinkSync11(tempPath);
|
|
73178
73456
|
} catch {}
|
|
73179
73457
|
throw writeError;
|
|
73180
73458
|
}
|
|
@@ -87150,7 +87428,7 @@ ${body2}`);
|
|
|
87150
87428
|
import {
|
|
87151
87429
|
appendFileSync as appendFileSync12,
|
|
87152
87430
|
existsSync as existsSync53,
|
|
87153
|
-
mkdirSync as
|
|
87431
|
+
mkdirSync as mkdirSync25,
|
|
87154
87432
|
readFileSync as readFileSync44,
|
|
87155
87433
|
writeFileSync as writeFileSync17
|
|
87156
87434
|
} from "node:fs";
|
|
@@ -87189,7 +87467,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
87189
87467
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
87190
87468
|
}
|
|
87191
87469
|
const dir = join83(workingDir, EVIDENCE_DIR2);
|
|
87192
|
-
|
|
87470
|
+
mkdirSync25(dir, { recursive: true });
|
|
87193
87471
|
const filePath = join83(dir, `${synthesis.taskId}.json`);
|
|
87194
87472
|
const existingRoot = Object.create(null);
|
|
87195
87473
|
if (existsSync53(filePath)) {
|
|
@@ -87225,7 +87503,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
87225
87503
|
writeFileSync17(filePath, JSON.stringify(updated, null, 2));
|
|
87226
87504
|
try {
|
|
87227
87505
|
const councilDir = join83(workingDir, ".swarm", "council");
|
|
87228
|
-
|
|
87506
|
+
mkdirSync25(councilDir, { recursive: true });
|
|
87229
87507
|
const auditLine = JSON.stringify({
|
|
87230
87508
|
round: synthesis.roundNumber,
|
|
87231
87509
|
verdict: synthesis.overallVerdict,
|
|
@@ -87554,12 +87832,12 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
|
|
|
87554
87832
|
}
|
|
87555
87833
|
|
|
87556
87834
|
// src/council/criteria-store.ts
|
|
87557
|
-
import { existsSync as existsSync54, mkdirSync as
|
|
87835
|
+
import { existsSync as existsSync54, mkdirSync as mkdirSync26, readFileSync as readFileSync45, writeFileSync as writeFileSync18 } from "node:fs";
|
|
87558
87836
|
import { join as join84 } from "node:path";
|
|
87559
87837
|
var COUNCIL_DIR = ".swarm/council";
|
|
87560
87838
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
87561
87839
|
const dir = join84(workingDir, COUNCIL_DIR);
|
|
87562
|
-
|
|
87840
|
+
mkdirSync26(dir, { recursive: true });
|
|
87563
87841
|
const payload = {
|
|
87564
87842
|
taskId,
|
|
87565
87843
|
criteria,
|
|
@@ -89413,12 +89691,12 @@ function extractFilename(code, language, index) {
|
|
|
89413
89691
|
`);
|
|
89414
89692
|
const ext = EXT_MAP[language.toLowerCase()] ?? ".txt";
|
|
89415
89693
|
if (lines.length > 0) {
|
|
89416
|
-
const
|
|
89417
|
-
const filenameMatch =
|
|
89694
|
+
const firstLine2 = lines[0].trim();
|
|
89695
|
+
const filenameMatch = firstLine2.match(/^[#/]+\s*filename[:\s]+(\S+\.\w+)/i);
|
|
89418
89696
|
if (filenameMatch) {
|
|
89419
89697
|
return filenameMatch[1];
|
|
89420
89698
|
}
|
|
89421
|
-
const bareMatch =
|
|
89699
|
+
const bareMatch = firstLine2.match(/^[#/]+\s*(\w+\.\w+)\s*$/);
|
|
89422
89700
|
if (bareMatch) {
|
|
89423
89701
|
return bareMatch[1];
|
|
89424
89702
|
}
|
|
@@ -90429,7 +90707,7 @@ function formatHiveEntry(entry) {
|
|
|
90429
90707
|
lines.push(` Category: ${entry.category}`);
|
|
90430
90708
|
lines.push(` Status: ${entry.status}`);
|
|
90431
90709
|
lines.push(` Confidence: ${entry.confidence.toFixed(2)}`);
|
|
90432
|
-
lines.push(` Encounter Score: ${entry.encounter_score
|
|
90710
|
+
lines.push(` Encounter Score: ${entry.encounter_score?.toFixed(2) ?? "N/A"}`);
|
|
90433
90711
|
lines.push(` Source Project: ${entry.source_project}`);
|
|
90434
90712
|
lines.push(` Confirmed by: ${entry.confirmed_by.length} project(s)`);
|
|
90435
90713
|
return lines.join(`
|
|
@@ -99907,10 +100185,10 @@ init_zod();
|
|
|
99907
100185
|
init_loader();
|
|
99908
100186
|
import {
|
|
99909
100187
|
existsSync as existsSync72,
|
|
99910
|
-
mkdirSync as
|
|
100188
|
+
mkdirSync as mkdirSync32,
|
|
99911
100189
|
readFileSync as readFileSync63,
|
|
99912
100190
|
renameSync as renameSync20,
|
|
99913
|
-
unlinkSync as
|
|
100191
|
+
unlinkSync as unlinkSync16,
|
|
99914
100192
|
writeFileSync as writeFileSync25
|
|
99915
100193
|
} from "node:fs";
|
|
99916
100194
|
import path124 from "node:path";
|
|
@@ -100106,7 +100384,7 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
100106
100384
|
}
|
|
100107
100385
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
100108
100386
|
const evidenceDir = path124.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
100109
|
-
|
|
100387
|
+
mkdirSync32(evidenceDir, { recursive: true });
|
|
100110
100388
|
const evidenceFile = path124.join(evidenceDir, "phase-council.json");
|
|
100111
100389
|
const evidenceBundle = {
|
|
100112
100390
|
entries: [
|
|
@@ -100144,7 +100422,7 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
|
100144
100422
|
renameSync20(tempFile, evidenceFile);
|
|
100145
100423
|
} finally {
|
|
100146
100424
|
if (existsSync72(tempFile)) {
|
|
100147
|
-
|
|
100425
|
+
unlinkSync16(tempFile);
|
|
100148
100426
|
}
|
|
100149
100427
|
}
|
|
100150
100428
|
}
|
|
@@ -102351,7 +102629,7 @@ import * as path131 from "node:path";
|
|
|
102351
102629
|
|
|
102352
102630
|
// src/mutation/engine.ts
|
|
102353
102631
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
102354
|
-
import { unlinkSync as
|
|
102632
|
+
import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync26 } from "node:fs";
|
|
102355
102633
|
import * as path130 from "node:path";
|
|
102356
102634
|
|
|
102357
102635
|
// src/mutation/equivalence.ts
|
|
@@ -102483,6 +102761,12 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
102483
102761
|
var MUTATION_TIMEOUT_MS = 30000;
|
|
102484
102762
|
var TOTAL_BUDGET_MS = 300000;
|
|
102485
102763
|
var GIT_APPLY_TIMEOUT_MS = 5000;
|
|
102764
|
+
var _internals51 = {
|
|
102765
|
+
executeMutation,
|
|
102766
|
+
computeReport,
|
|
102767
|
+
executeMutationSuite,
|
|
102768
|
+
spawnSync: spawnSync3
|
|
102769
|
+
};
|
|
102486
102770
|
async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
102487
102771
|
const startTime = Date.now();
|
|
102488
102772
|
let outcome = "survived";
|
|
@@ -102509,7 +102793,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
102509
102793
|
};
|
|
102510
102794
|
}
|
|
102511
102795
|
try {
|
|
102512
|
-
const applyResult =
|
|
102796
|
+
const applyResult = _internals51.spawnSync("git", ["apply", "--", patchFile], {
|
|
102513
102797
|
cwd: workingDir,
|
|
102514
102798
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
102515
102799
|
stdio: "pipe"
|
|
@@ -102538,7 +102822,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
102538
102822
|
}
|
|
102539
102823
|
let testPassed = false;
|
|
102540
102824
|
try {
|
|
102541
|
-
const spawnResult =
|
|
102825
|
+
const spawnResult = _internals51.spawnSync(testCommand[0], testCommand.slice(1), {
|
|
102542
102826
|
cwd: workingDir,
|
|
102543
102827
|
timeout: MUTATION_TIMEOUT_MS,
|
|
102544
102828
|
stdio: "pipe"
|
|
@@ -102571,7 +102855,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
102571
102855
|
} finally {
|
|
102572
102856
|
if (patchFile) {
|
|
102573
102857
|
try {
|
|
102574
|
-
const revertResult =
|
|
102858
|
+
const revertResult = _internals51.spawnSync("git", ["apply", "-R", "--", patchFile], {
|
|
102575
102859
|
cwd: workingDir,
|
|
102576
102860
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
102577
102861
|
stdio: "pipe"
|
|
@@ -102590,7 +102874,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
102590
102874
|
revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
|
|
102591
102875
|
}
|
|
102592
102876
|
try {
|
|
102593
|
-
|
|
102877
|
+
unlinkSync17(patchFile);
|
|
102594
102878
|
} catch (_unlinkErr) {}
|
|
102595
102879
|
}
|
|
102596
102880
|
}
|
|
@@ -102764,7 +103048,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
|
|
|
102764
103048
|
}
|
|
102765
103049
|
|
|
102766
103050
|
// src/mutation/gate.ts
|
|
102767
|
-
var
|
|
103051
|
+
var _internals52 = {
|
|
102768
103052
|
evaluateMutationGate,
|
|
102769
103053
|
buildTestImprovementPrompt,
|
|
102770
103054
|
buildMessage
|
|
@@ -102785,8 +103069,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
|
|
|
102785
103069
|
} else {
|
|
102786
103070
|
verdict = "fail";
|
|
102787
103071
|
}
|
|
102788
|
-
const testImprovementPrompt =
|
|
102789
|
-
const message =
|
|
103072
|
+
const testImprovementPrompt = _internals52.buildTestImprovementPrompt(report, passThreshold, verdict);
|
|
103073
|
+
const message = _internals52.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
|
|
102790
103074
|
return {
|
|
102791
103075
|
verdict,
|
|
102792
103076
|
killRate: report.killRate,
|
|
@@ -103403,7 +103687,7 @@ import * as path135 from "node:path";
|
|
|
103403
103687
|
init_bun_compat();
|
|
103404
103688
|
import * as fs104 from "node:fs";
|
|
103405
103689
|
import * as path134 from "node:path";
|
|
103406
|
-
var
|
|
103690
|
+
var _internals53 = { bunSpawn };
|
|
103407
103691
|
var _swarmGitExcludedChecked = false;
|
|
103408
103692
|
function fileCoversSwarm(content) {
|
|
103409
103693
|
for (const rawLine of content.split(`
|
|
@@ -103436,7 +103720,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
103436
103720
|
checkIgnoreExitCode
|
|
103437
103721
|
] = await Promise.all([
|
|
103438
103722
|
(async () => {
|
|
103439
|
-
const proc =
|
|
103723
|
+
const proc = _internals53.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
|
|
103440
103724
|
try {
|
|
103441
103725
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
103442
103726
|
} finally {
|
|
@@ -103446,7 +103730,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
103446
103730
|
}
|
|
103447
103731
|
})(),
|
|
103448
103732
|
(async () => {
|
|
103449
|
-
const proc =
|
|
103733
|
+
const proc = _internals53.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
|
|
103450
103734
|
try {
|
|
103451
103735
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
103452
103736
|
} finally {
|
|
@@ -103456,7 +103740,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
103456
103740
|
}
|
|
103457
103741
|
})(),
|
|
103458
103742
|
(async () => {
|
|
103459
|
-
const proc =
|
|
103743
|
+
const proc = _internals53.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
|
|
103460
103744
|
try {
|
|
103461
103745
|
return await proc.exited;
|
|
103462
103746
|
} finally {
|
|
@@ -103495,7 +103779,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
103495
103779
|
}
|
|
103496
103780
|
} catch {}
|
|
103497
103781
|
}
|
|
103498
|
-
const trackedProc =
|
|
103782
|
+
const trackedProc = _internals53.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
|
|
103499
103783
|
let trackedExitCode;
|
|
103500
103784
|
let trackedOutput;
|
|
103501
103785
|
try {
|
|
@@ -103520,7 +103804,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
103520
103804
|
}
|
|
103521
103805
|
|
|
103522
103806
|
// src/hooks/diff-scope.ts
|
|
103523
|
-
var
|
|
103807
|
+
var _internals54 = { bunSpawn };
|
|
103524
103808
|
function getDeclaredScope(taskId, directory) {
|
|
103525
103809
|
try {
|
|
103526
103810
|
const planPath = path135.join(directory, ".swarm", "plan.json");
|
|
@@ -103555,7 +103839,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
|
|
|
103555
103839
|
};
|
|
103556
103840
|
async function getChangedFiles(directory) {
|
|
103557
103841
|
try {
|
|
103558
|
-
const proc =
|
|
103842
|
+
const proc = _internals54.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
|
|
103559
103843
|
cwd: directory,
|
|
103560
103844
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
103561
103845
|
});
|
|
@@ -103572,7 +103856,7 @@ async function getChangedFiles(directory) {
|
|
|
103572
103856
|
return stdout.trim().split(`
|
|
103573
103857
|
`).map((f) => f.trim()).filter((f) => f.length > 0);
|
|
103574
103858
|
}
|
|
103575
|
-
const proc2 =
|
|
103859
|
+
const proc2 = _internals54.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
|
|
103576
103860
|
cwd: directory,
|
|
103577
103861
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
103578
103862
|
});
|
|
@@ -103630,7 +103914,7 @@ init_telemetry();
|
|
|
103630
103914
|
init_file_locks();
|
|
103631
103915
|
import * as fs106 from "node:fs";
|
|
103632
103916
|
import * as path136 from "node:path";
|
|
103633
|
-
var
|
|
103917
|
+
var _internals55 = {
|
|
103634
103918
|
listActiveLocks,
|
|
103635
103919
|
verifyLeanTurboTaskCompletion
|
|
103636
103920
|
};
|
|
@@ -103772,7 +104056,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
103772
104056
|
}
|
|
103773
104057
|
};
|
|
103774
104058
|
}
|
|
103775
|
-
const activeLocks =
|
|
104059
|
+
const activeLocks = _internals55.listActiveLocks(directory);
|
|
103776
104060
|
const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
|
|
103777
104061
|
if (laneLocks.length > 0) {
|
|
103778
104062
|
return {
|