opencode-swarm 7.27.1 → 7.27.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -7
- package/dist/cli/index.js +576 -141
- package/dist/evidence/manager.d.ts +8 -0
- package/dist/index.js +11916 -905
- package/dist/plan/checkpoint.d.ts +0 -10
- package/dist/services/config-doctor.d.ts +33 -0
- package/dist/test-impact/analyzer.d.ts +2 -0
- package/dist/test-impact/failure-classifier.d.ts +1 -1
- package/dist/test-impact/history-store.d.ts +8 -0
- package/dist/tools/pre-check-batch.d.ts +1 -1
- package/dist/tools/resolve-working-directory.d.ts +8 -1
- package/dist/tools/test-runner.d.ts +10 -0
- package/dist/tools/update-task-status.d.ts +3 -2
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.27.
|
|
37
|
+
version: "7.27.2",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -72,7 +72,7 @@ var init_package = __esm(() => {
|
|
|
72
72
|
],
|
|
73
73
|
scripts: {
|
|
74
74
|
clean: `bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,
|
|
75
|
-
build: "bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target node --format esm
|
|
75
|
+
build: "bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target node --format esm && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external bash-parser && bun run scripts/copy-grammars.ts --to-dist && tsc --emitDeclarationOnly",
|
|
76
76
|
typecheck: "tsc --noEmit",
|
|
77
77
|
test: "bun test",
|
|
78
78
|
lint: "biome lint .",
|
|
@@ -19803,13 +19803,47 @@ var init_task_id = __esm(() => {
|
|
|
19803
19803
|
});
|
|
19804
19804
|
|
|
19805
19805
|
// src/evidence/manager.ts
|
|
19806
|
-
import {
|
|
19806
|
+
import {
|
|
19807
|
+
mkdirSync as mkdirSync3,
|
|
19808
|
+
readdirSync as readdirSync3,
|
|
19809
|
+
realpathSync,
|
|
19810
|
+
rmSync,
|
|
19811
|
+
statSync as statSync4
|
|
19812
|
+
} from "fs";
|
|
19807
19813
|
import * as fs4 from "fs/promises";
|
|
19808
19814
|
import * as path7 from "path";
|
|
19809
19815
|
function isValidEvidenceType(type) {
|
|
19810
19816
|
return VALID_EVIDENCE_TYPES.includes(type);
|
|
19811
19817
|
}
|
|
19818
|
+
function validateProjectRoot(directory) {
|
|
19819
|
+
let resolved;
|
|
19820
|
+
try {
|
|
19821
|
+
resolved = realpathSync(directory);
|
|
19822
|
+
} catch {
|
|
19823
|
+
warn(`[evidence] Cannot canonicalize directory "${directory}" \u2014 failing closed`);
|
|
19824
|
+
throw new Error(`Cannot verify project root for "${directory}" \u2014 directory may not exist or is inaccessible`);
|
|
19825
|
+
}
|
|
19826
|
+
let current = resolved;
|
|
19827
|
+
while (true) {
|
|
19828
|
+
const parent = path7.dirname(current);
|
|
19829
|
+
if (parent === current)
|
|
19830
|
+
break;
|
|
19831
|
+
const parentSwarm = path7.join(parent, ".swarm");
|
|
19832
|
+
try {
|
|
19833
|
+
if (statSync4(parentSwarm).isDirectory()) {
|
|
19834
|
+
warn(`[evidence] Rejecting write to subdirectory "${resolved}" \u2014 parent "${parent}" already contains .swarm/`);
|
|
19835
|
+
throw new Error(`Cannot write evidence in "${resolved}" \u2014 parent directory "${parent}" already contains a .swarm/ folder. Evidence must be written to the project root.`);
|
|
19836
|
+
}
|
|
19837
|
+
} catch (error49) {
|
|
19838
|
+
if (error49 instanceof Error && error49.message.startsWith("Cannot write evidence")) {
|
|
19839
|
+
throw error49;
|
|
19840
|
+
}
|
|
19841
|
+
}
|
|
19842
|
+
current = parent;
|
|
19843
|
+
}
|
|
19844
|
+
}
|
|
19812
19845
|
async function saveEvidence(directory, taskId, evidence) {
|
|
19846
|
+
_internals5.validateProjectRoot(directory);
|
|
19813
19847
|
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
19814
19848
|
const relativePath = path7.join("evidence", sanitizedTaskId, "evidence.json");
|
|
19815
19849
|
validateSwarmPath(directory, relativePath);
|
|
@@ -20074,7 +20108,8 @@ var init_manager2 = __esm(() => {
|
|
|
20074
20108
|
_internals5 = {
|
|
20075
20109
|
wrapFlatRetrospective,
|
|
20076
20110
|
loadEvidence,
|
|
20077
|
-
listEvidenceTaskIds
|
|
20111
|
+
listEvidenceTaskIds,
|
|
20112
|
+
validateProjectRoot
|
|
20078
20113
|
};
|
|
20079
20114
|
});
|
|
20080
20115
|
|
|
@@ -40002,7 +40037,9 @@ __export(exports_config_doctor, {
|
|
|
40002
40037
|
runConfigDoctorWithFixes: () => runConfigDoctorWithFixes,
|
|
40003
40038
|
runConfigDoctor: () => runConfigDoctor,
|
|
40004
40039
|
restoreFromBackup: () => restoreFromBackup,
|
|
40040
|
+
removeStraySwarmDir: () => removeStraySwarmDir,
|
|
40005
40041
|
getConfigPaths: () => getConfigPaths,
|
|
40042
|
+
detectStraySwarmDirs: () => detectStraySwarmDirs,
|
|
40006
40043
|
createConfigBackup: () => createConfigBackup,
|
|
40007
40044
|
applySafeAutoFixes: () => applySafeAutoFixes
|
|
40008
40045
|
});
|
|
@@ -40618,6 +40655,114 @@ async function runConfigDoctorWithFixes(directory, config3, autoFix = false) {
|
|
|
40618
40655
|
artifactPath
|
|
40619
40656
|
};
|
|
40620
40657
|
}
|
|
40658
|
+
function detectStraySwarmDirs(projectRoot) {
|
|
40659
|
+
const findings = [];
|
|
40660
|
+
const SKIP_DIRS = new Set([
|
|
40661
|
+
"node_modules",
|
|
40662
|
+
".git",
|
|
40663
|
+
"dist",
|
|
40664
|
+
".cache",
|
|
40665
|
+
".next",
|
|
40666
|
+
"coverage",
|
|
40667
|
+
".turbo",
|
|
40668
|
+
".vercel",
|
|
40669
|
+
".terraform",
|
|
40670
|
+
"__pycache__",
|
|
40671
|
+
".tox"
|
|
40672
|
+
]);
|
|
40673
|
+
const MAX_DEPTH = 10;
|
|
40674
|
+
const MAX_CONTENTS_ENTRIES = 20;
|
|
40675
|
+
function walk(dir, depth) {
|
|
40676
|
+
if (depth > MAX_DEPTH)
|
|
40677
|
+
return;
|
|
40678
|
+
let entries;
|
|
40679
|
+
try {
|
|
40680
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
40681
|
+
} catch {
|
|
40682
|
+
return;
|
|
40683
|
+
}
|
|
40684
|
+
for (const entry of entries) {
|
|
40685
|
+
if (!entry.isDirectory())
|
|
40686
|
+
continue;
|
|
40687
|
+
const name = entry.name;
|
|
40688
|
+
const fullPath = path23.join(dir, name);
|
|
40689
|
+
if (SKIP_DIRS.has(name))
|
|
40690
|
+
continue;
|
|
40691
|
+
const gitPath = path23.join(fullPath, ".git");
|
|
40692
|
+
try {
|
|
40693
|
+
const gitStat = fs8.statSync(gitPath);
|
|
40694
|
+
if (gitStat.isFile() || gitStat.isDirectory())
|
|
40695
|
+
continue;
|
|
40696
|
+
} catch {}
|
|
40697
|
+
if (name === ".swarm") {
|
|
40698
|
+
const parentDir = path23.dirname(fullPath);
|
|
40699
|
+
if (parentDir === projectRoot)
|
|
40700
|
+
continue;
|
|
40701
|
+
let contents = [];
|
|
40702
|
+
try {
|
|
40703
|
+
contents = fs8.readdirSync(fullPath);
|
|
40704
|
+
} catch {
|
|
40705
|
+
contents = ["<unreadable>"];
|
|
40706
|
+
}
|
|
40707
|
+
findings.push({
|
|
40708
|
+
path: path23.relative(projectRoot, fullPath).replace(/\\/g, "/"),
|
|
40709
|
+
absolutePath: fullPath,
|
|
40710
|
+
contents: contents.slice(0, MAX_CONTENTS_ENTRIES),
|
|
40711
|
+
totalEntries: contents.length
|
|
40712
|
+
});
|
|
40713
|
+
continue;
|
|
40714
|
+
}
|
|
40715
|
+
walk(fullPath, depth + 1);
|
|
40716
|
+
}
|
|
40717
|
+
}
|
|
40718
|
+
walk(projectRoot, 0);
|
|
40719
|
+
return findings;
|
|
40720
|
+
}
|
|
40721
|
+
function removeStraySwarmDir(projectRoot, strayPath) {
|
|
40722
|
+
let canonicalRoot;
|
|
40723
|
+
let canonicalStray;
|
|
40724
|
+
try {
|
|
40725
|
+
canonicalRoot = fs8.realpathSync(projectRoot);
|
|
40726
|
+
canonicalStray = fs8.realpathSync(path23.isAbsolute(strayPath) ? strayPath : path23.resolve(projectRoot, strayPath));
|
|
40727
|
+
} catch (err) {
|
|
40728
|
+
return {
|
|
40729
|
+
success: false,
|
|
40730
|
+
message: `Failed to resolve paths: ${err instanceof Error ? err.message : String(err)}`
|
|
40731
|
+
};
|
|
40732
|
+
}
|
|
40733
|
+
const rootSwarm = path23.join(canonicalRoot, ".swarm");
|
|
40734
|
+
if (canonicalStray === rootSwarm || canonicalStray === canonicalRoot) {
|
|
40735
|
+
return {
|
|
40736
|
+
success: false,
|
|
40737
|
+
message: "Refusing to remove root .swarm/ directory"
|
|
40738
|
+
};
|
|
40739
|
+
}
|
|
40740
|
+
if (!canonicalStray.startsWith(canonicalRoot + path23.sep)) {
|
|
40741
|
+
return {
|
|
40742
|
+
success: false,
|
|
40743
|
+
message: "Path is outside project root \u2014 refusing to remove"
|
|
40744
|
+
};
|
|
40745
|
+
}
|
|
40746
|
+
const normalizedStray = canonicalStray.replace(/\\/g, "/");
|
|
40747
|
+
if (!normalizedStray.endsWith("/.swarm")) {
|
|
40748
|
+
return {
|
|
40749
|
+
success: false,
|
|
40750
|
+
message: "Path is not a .swarm directory \u2014 refusing to remove"
|
|
40751
|
+
};
|
|
40752
|
+
}
|
|
40753
|
+
try {
|
|
40754
|
+
fs8.rmSync(canonicalStray, { recursive: true, force: true });
|
|
40755
|
+
return {
|
|
40756
|
+
success: true,
|
|
40757
|
+
message: `Removed stray .swarm directory: ${canonicalStray}`
|
|
40758
|
+
};
|
|
40759
|
+
} catch (err) {
|
|
40760
|
+
return {
|
|
40761
|
+
success: false,
|
|
40762
|
+
message: `Failed to remove: ${err instanceof Error ? err.message : String(err)}`
|
|
40763
|
+
};
|
|
40764
|
+
}
|
|
40765
|
+
}
|
|
40621
40766
|
var VALID_CONFIG_PATTERNS, DANGEROUS_PATH_SEGMENTS;
|
|
40622
40767
|
var init_config_doctor = __esm(() => {
|
|
40623
40768
|
init_utils();
|
|
@@ -42305,12 +42450,62 @@ async function handleDoctorCommand(directory, args) {
|
|
|
42305
42450
|
const enableAutoFix = args.includes("--fix") || args.includes("-f");
|
|
42306
42451
|
const config3 = loadPluginConfig(directory);
|
|
42307
42452
|
const result = runConfigDoctor(config3, directory);
|
|
42453
|
+
let output;
|
|
42308
42454
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
42309
42455
|
const { runConfigDoctorWithFixes: runConfigDoctorWithFixes2 } = await Promise.resolve().then(() => (init_config_doctor(), exports_config_doctor));
|
|
42310
42456
|
const fixResult = await runConfigDoctorWithFixes2(directory, config3, true);
|
|
42311
|
-
|
|
42457
|
+
output = formatDoctorMarkdown(fixResult.result);
|
|
42458
|
+
} else {
|
|
42459
|
+
output = formatDoctorMarkdown(result);
|
|
42460
|
+
}
|
|
42461
|
+
const strayDirs = detectStraySwarmDirs(directory);
|
|
42462
|
+
if (strayDirs.length > 0) {
|
|
42463
|
+
if (enableAutoFix) {
|
|
42464
|
+
let fixOutput = `
|
|
42465
|
+
---
|
|
42466
|
+
|
|
42467
|
+
## Stray .swarm Directories
|
|
42468
|
+
|
|
42469
|
+
`;
|
|
42470
|
+
let removed = 0;
|
|
42471
|
+
let failed = 0;
|
|
42472
|
+
for (const finding of strayDirs) {
|
|
42473
|
+
const cleanupResult = removeStraySwarmDir(directory, finding.path);
|
|
42474
|
+
if (cleanupResult.success) {
|
|
42475
|
+
removed++;
|
|
42476
|
+
} else {
|
|
42477
|
+
failed++;
|
|
42478
|
+
fixOutput += `- \`${finding.path}\`: ${cleanupResult.message}
|
|
42479
|
+
`;
|
|
42480
|
+
}
|
|
42481
|
+
}
|
|
42482
|
+
fixOutput += `
|
|
42483
|
+
Cleaned up ${removed} stray director${removed === 1 ? "y" : "ies"}.`;
|
|
42484
|
+
if (failed > 0) {
|
|
42485
|
+
fixOutput += ` ${failed} could not be removed.`;
|
|
42486
|
+
}
|
|
42487
|
+
output += fixOutput;
|
|
42488
|
+
} else {
|
|
42489
|
+
output += `
|
|
42490
|
+
---
|
|
42491
|
+
|
|
42492
|
+
## Stray .swarm Directories
|
|
42493
|
+
|
|
42494
|
+
`;
|
|
42495
|
+
output += `Found ${strayDirs.length} stray .swarm director${strayDirs.length === 1 ? "y" : "ies"} in subdirectories:
|
|
42496
|
+
|
|
42497
|
+
`;
|
|
42498
|
+
for (const finding of strayDirs) {
|
|
42499
|
+
const contentsPreview = finding.contents.length > 5 ? `${finding.contents.slice(0, 5).join(", ")}, ...` : finding.contents.join(", ");
|
|
42500
|
+
output += `- \`${finding.path}\` (${finding.totalEntries} entries: ${contentsPreview})
|
|
42501
|
+
`;
|
|
42502
|
+
}
|
|
42503
|
+
output += `
|
|
42504
|
+
These are likely from a prior bug (Issue #922). `;
|
|
42505
|
+
output += "Re-run with `--fix` to auto-clean.\n";
|
|
42506
|
+
}
|
|
42312
42507
|
}
|
|
42313
|
-
return
|
|
42508
|
+
return output;
|
|
42314
42509
|
}
|
|
42315
42510
|
async function handleDoctorToolsCommand(directory, _args) {
|
|
42316
42511
|
const result = runToolDoctor(directory);
|
|
@@ -46068,7 +46263,14 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
46068
46263
|
return args;
|
|
46069
46264
|
}
|
|
46070
46265
|
case "vitest": {
|
|
46071
|
-
const args = [
|
|
46266
|
+
const args = [
|
|
46267
|
+
"npx",
|
|
46268
|
+
"vitest",
|
|
46269
|
+
"run",
|
|
46270
|
+
"--reporter=json",
|
|
46271
|
+
"--outputFile",
|
|
46272
|
+
".swarm/cache/test-runner-vitest.json"
|
|
46273
|
+
];
|
|
46072
46274
|
if (coverage)
|
|
46073
46275
|
args.push("--coverage");
|
|
46074
46276
|
if (scope !== "all" && files.length > 0)
|
|
@@ -46076,7 +46278,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
46076
46278
|
return args;
|
|
46077
46279
|
}
|
|
46078
46280
|
case "jest": {
|
|
46079
|
-
const args = ["npx", "jest"];
|
|
46281
|
+
const args = ["npx", "jest", "--json"];
|
|
46080
46282
|
if (coverage)
|
|
46081
46283
|
args.push("--coverage");
|
|
46082
46284
|
if (scope !== "all" && files.length > 0)
|
|
@@ -46961,6 +47163,10 @@ async function loadImpactMap(cwd, options) {
|
|
|
46961
47163
|
return _internals22.buildImpactMap(cwd);
|
|
46962
47164
|
}
|
|
46963
47165
|
async function saveImpactMap(cwd, impactMap) {
|
|
47166
|
+
if (!path34.isAbsolute(cwd)) {
|
|
47167
|
+
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
47168
|
+
}
|
|
47169
|
+
_internals22.validateProjectRoot(cwd);
|
|
46964
47170
|
const cacheDir2 = path34.join(cwd, ".swarm", "cache");
|
|
46965
47171
|
const cachePath = path34.join(cacheDir2, "impact-map.json");
|
|
46966
47172
|
if (!fs17.existsSync(cacheDir2)) {
|
|
@@ -47053,6 +47259,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
47053
47259
|
}
|
|
47054
47260
|
var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals22;
|
|
47055
47261
|
var init_analyzer = __esm(() => {
|
|
47262
|
+
init_manager2();
|
|
47056
47263
|
init_go();
|
|
47057
47264
|
init_python();
|
|
47058
47265
|
IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -47064,6 +47271,7 @@ var init_analyzer = __esm(() => {
|
|
|
47064
47271
|
EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
47065
47272
|
goModuleCache = new Map;
|
|
47066
47273
|
_internals22 = {
|
|
47274
|
+
validateProjectRoot,
|
|
47067
47275
|
normalizePath,
|
|
47068
47276
|
isCacheStale,
|
|
47069
47277
|
resolveRelativeImport,
|
|
@@ -47117,31 +47325,10 @@ function stringHash(str) {
|
|
|
47117
47325
|
h2 ^= Math.imul(h1 ^ h1 >>> 13, 3266489909);
|
|
47118
47326
|
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16);
|
|
47119
47327
|
}
|
|
47120
|
-
function isInfrastructureFailure(currentResult) {
|
|
47121
|
-
const errorMessage = currentResult.errorMessage || "";
|
|
47122
|
-
const stackPrefix = currentResult.stackPrefix || "";
|
|
47123
|
-
if (/\bassertionerror\b/i.test(errorMessage)) {
|
|
47124
|
-
return false;
|
|
47125
|
-
}
|
|
47126
|
-
const combinedText = `${errorMessage}
|
|
47127
|
-
${stackPrefix}`;
|
|
47128
|
-
return INFRASTRUCTURE_FAILURE_PATTERNS.some((pattern) => pattern.test(combinedText));
|
|
47129
|
-
}
|
|
47130
47328
|
function classifyFailure(currentResult, history) {
|
|
47131
47329
|
const normalizedFile = currentResult.testFile.toLowerCase();
|
|
47132
47330
|
const normalizedName = currentResult.testName.toLowerCase();
|
|
47133
47331
|
const testHistory = history.filter((r) => r.testFile.toLowerCase() === normalizedFile && r.testName.toLowerCase() === normalizedName).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
47134
|
-
if (isInfrastructureFailure(currentResult)) {
|
|
47135
|
-
return {
|
|
47136
|
-
testFile: currentResult.testFile,
|
|
47137
|
-
testName: currentResult.testName,
|
|
47138
|
-
classification: "infrastructure_failure",
|
|
47139
|
-
errorMessage: currentResult.errorMessage,
|
|
47140
|
-
stackPrefix: currentResult.stackPrefix,
|
|
47141
|
-
durationMs: currentResult.durationMs,
|
|
47142
|
-
confidence: computeConfidence2(testHistory.length)
|
|
47143
|
-
};
|
|
47144
|
-
}
|
|
47145
47332
|
const lastThree = testHistory.slice(0, 3);
|
|
47146
47333
|
const lastTen = testHistory.slice(0, 10);
|
|
47147
47334
|
const normalizedTestFile = currentResult.testFile.toLowerCase();
|
|
@@ -47241,20 +47428,6 @@ function classifyAndCluster(testResults, history) {
|
|
|
47241
47428
|
const clusters = clusterFailures(classified);
|
|
47242
47429
|
return { classified, clusters };
|
|
47243
47430
|
}
|
|
47244
|
-
var MAX_INFRA_CONTEXT_CHARS = 80, INFRASTRUCTURE_FAILURE_PATTERNS;
|
|
47245
|
-
var init_failure_classifier = __esm(() => {
|
|
47246
|
-
INFRASTRUCTURE_FAILURE_PATTERNS = [
|
|
47247
|
-
/\boutofmemoryerror\b/i,
|
|
47248
|
-
/(?:^|\n|\bcommand failed:\s*)\s*killed(?:\s*(?:[-:]\s*)?(?:out of memory|oom|by signal|signal|sigkill).*)?\s*(?:\n|$)/i,
|
|
47249
|
-
/(?:^|\n)\s*etimedout\b/i,
|
|
47250
|
-
new RegExp(`\\b(?:connect|connection|request|socket|network)\\b[^\\n]{0,${MAX_INFRA_CONTEXT_CHARS}}\\betimedout\\b`, "i"),
|
|
47251
|
-
/(?:^|\n)\s*econnrefused\b/i,
|
|
47252
|
-
new RegExp(`\\b(?:connect|connection|socket)\\b[^\\n]{0,${MAX_INFRA_CONTEXT_CHARS}}\\beconnrefused\\b`, "i"),
|
|
47253
|
-
/(?:^|\n)\s*enotfound\b/i,
|
|
47254
|
-
new RegExp(`\\b(?:getaddrinfo|dns|lookup)\\b[^\\n]{0,${MAX_INFRA_CONTEXT_CHARS}}\\benotfound\\b`, "i"),
|
|
47255
|
-
/\bexit(?:ed)?(?:\s+with)?(?:\s+code)?\s*[:=]?\s*137\b/i
|
|
47256
|
-
];
|
|
47257
|
-
});
|
|
47258
47431
|
|
|
47259
47432
|
// src/test-impact/flaky-detector.ts
|
|
47260
47433
|
function detectFlakyTests(allHistory) {
|
|
@@ -47322,7 +47495,13 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
|
|
|
47322
47495
|
import fs18 from "fs";
|
|
47323
47496
|
import path35 from "path";
|
|
47324
47497
|
function getHistoryPath(workingDir) {
|
|
47325
|
-
|
|
47498
|
+
if (!workingDir) {
|
|
47499
|
+
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
47500
|
+
}
|
|
47501
|
+
if (!path35.isAbsolute(workingDir)) {
|
|
47502
|
+
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
47503
|
+
}
|
|
47504
|
+
return path35.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
47326
47505
|
}
|
|
47327
47506
|
function sanitizeErrorMessage(errorMessage) {
|
|
47328
47507
|
if (errorMessage === undefined) {
|
|
@@ -47346,55 +47525,96 @@ function sanitizeChangedFiles(changedFiles) {
|
|
|
47346
47525
|
const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !DANGEROUS_PROPERTY_NAMES.has(f));
|
|
47347
47526
|
return validFiles.slice(0, MAX_CHANGED_FILES);
|
|
47348
47527
|
}
|
|
47349
|
-
function
|
|
47528
|
+
function isTestRunResult(value) {
|
|
47529
|
+
return value === "pass" || value === "fail" || value === "skip";
|
|
47530
|
+
}
|
|
47531
|
+
function parseStoredRecord(value) {
|
|
47532
|
+
if (typeof value !== "object" || value === null)
|
|
47533
|
+
return null;
|
|
47534
|
+
const record3 = value;
|
|
47350
47535
|
if (typeof record3.testFile !== "string" || record3.testFile.length === 0) {
|
|
47351
|
-
|
|
47536
|
+
return null;
|
|
47352
47537
|
}
|
|
47353
47538
|
if (typeof record3.testName !== "string" || record3.testName.length === 0) {
|
|
47354
|
-
|
|
47539
|
+
return null;
|
|
47355
47540
|
}
|
|
47356
47541
|
if (typeof record3.taskId !== "string" || record3.taskId.length === 0) {
|
|
47357
|
-
|
|
47358
|
-
}
|
|
47359
|
-
if (record3.result !== "pass" && record3.result !== "fail" && record3.result !== "skip") {
|
|
47360
|
-
throw new TypeError('result must be "pass", "fail", or "skip"');
|
|
47542
|
+
return null;
|
|
47361
47543
|
}
|
|
47544
|
+
if (!isTestRunResult(record3.result))
|
|
47545
|
+
return null;
|
|
47362
47546
|
if (typeof record3.durationMs !== "number" || !Number.isFinite(record3.durationMs)) {
|
|
47363
|
-
|
|
47364
|
-
}
|
|
47365
|
-
if (record3.timestamp !== undefined && Number.isNaN(Date.parse(record3.timestamp))) {
|
|
47366
|
-
throw new TypeError("timestamp must be a valid ISO 8601 string");
|
|
47547
|
+
return null;
|
|
47367
47548
|
}
|
|
47368
|
-
if (record3.
|
|
47369
|
-
|
|
47549
|
+
if (typeof record3.timestamp !== "string" || Number.isNaN(Date.parse(record3.timestamp))) {
|
|
47550
|
+
return null;
|
|
47370
47551
|
}
|
|
47371
|
-
|
|
47372
|
-
|
|
47373
|
-
|
|
47552
|
+
return {
|
|
47553
|
+
timestamp: record3.timestamp,
|
|
47554
|
+
taskId: record3.taskId,
|
|
47555
|
+
testFile: record3.testFile,
|
|
47556
|
+
testName: record3.testName,
|
|
47557
|
+
result: record3.result,
|
|
47374
47558
|
durationMs: Math.max(0, record3.durationMs),
|
|
47375
|
-
errorMessage: sanitizeErrorMessage(record3.errorMessage),
|
|
47376
|
-
stackPrefix: sanitizeStackPrefix(record3.stackPrefix),
|
|
47377
|
-
changedFiles: sanitizeChangedFiles(record3.changedFiles
|
|
47559
|
+
errorMessage: typeof record3.errorMessage === "string" ? sanitizeErrorMessage(record3.errorMessage) : undefined,
|
|
47560
|
+
stackPrefix: typeof record3.stackPrefix === "string" ? sanitizeStackPrefix(record3.stackPrefix) : undefined,
|
|
47561
|
+
changedFiles: sanitizeChangedFiles(Array.isArray(record3.changedFiles) ? record3.changedFiles : [])
|
|
47378
47562
|
};
|
|
47563
|
+
}
|
|
47564
|
+
function batchAppendTestRuns(records, workingDir) {
|
|
47565
|
+
if (records.length === 0)
|
|
47566
|
+
return;
|
|
47567
|
+
for (const record3 of records) {
|
|
47568
|
+
if (typeof record3.testFile !== "string" || record3.testFile.length === 0) {
|
|
47569
|
+
throw new TypeError("testFile must be a non-empty string");
|
|
47570
|
+
}
|
|
47571
|
+
if (typeof record3.testName !== "string" || record3.testName.length === 0) {
|
|
47572
|
+
throw new TypeError("testName must be a non-empty string");
|
|
47573
|
+
}
|
|
47574
|
+
if (typeof record3.taskId !== "string" || record3.taskId.length === 0) {
|
|
47575
|
+
throw new TypeError("taskId must be a non-empty string");
|
|
47576
|
+
}
|
|
47577
|
+
if (record3.result !== "pass" && record3.result !== "fail" && record3.result !== "skip") {
|
|
47578
|
+
throw new TypeError('result must be "pass", "fail", or "skip"');
|
|
47579
|
+
}
|
|
47580
|
+
if (typeof record3.durationMs !== "number" || !Number.isFinite(record3.durationMs)) {
|
|
47581
|
+
throw new TypeError("durationMs must be a finite number");
|
|
47582
|
+
}
|
|
47583
|
+
if (record3.timestamp !== undefined && Number.isNaN(Date.parse(record3.timestamp))) {
|
|
47584
|
+
throw new TypeError("timestamp must be a valid ISO 8601 string");
|
|
47585
|
+
}
|
|
47586
|
+
if (record3.changedFiles !== undefined && !Array.isArray(record3.changedFiles)) {
|
|
47587
|
+
throw new TypeError("changedFiles must be an array");
|
|
47588
|
+
}
|
|
47589
|
+
}
|
|
47379
47590
|
const historyPath = getHistoryPath(workingDir);
|
|
47380
47591
|
const historyDir = path35.dirname(historyPath);
|
|
47592
|
+
_internals23.validateProjectRoot(workingDir);
|
|
47381
47593
|
if (!fs18.existsSync(historyDir)) {
|
|
47382
47594
|
fs18.mkdirSync(historyDir, { recursive: true });
|
|
47383
47595
|
}
|
|
47384
47596
|
const existingRecords = readAllRecords(historyPath);
|
|
47385
|
-
|
|
47386
|
-
|
|
47597
|
+
const sanitizedRecords = records.map((record3) => ({
|
|
47598
|
+
...record3,
|
|
47599
|
+
timestamp: record3.timestamp || new Date().toISOString(),
|
|
47600
|
+
durationMs: Math.max(0, record3.durationMs),
|
|
47601
|
+
errorMessage: sanitizeErrorMessage(record3.errorMessage),
|
|
47602
|
+
stackPrefix: sanitizeStackPrefix(record3.stackPrefix),
|
|
47603
|
+
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
47604
|
+
}));
|
|
47605
|
+
existingRecords.push(...sanitizedRecords);
|
|
47606
|
+
const recordsByTest = new Map;
|
|
47387
47607
|
for (const rec of existingRecords) {
|
|
47388
|
-
const
|
|
47389
|
-
if (!
|
|
47390
|
-
|
|
47608
|
+
const normalizedKey = `${rec.testFile.toLowerCase()}|${rec.testName.toLowerCase()}`;
|
|
47609
|
+
if (!recordsByTest.has(normalizedKey)) {
|
|
47610
|
+
recordsByTest.set(normalizedKey, []);
|
|
47391
47611
|
}
|
|
47392
|
-
|
|
47612
|
+
recordsByTest.get(normalizedKey).push(rec);
|
|
47393
47613
|
}
|
|
47394
47614
|
const prunedRecords = [];
|
|
47395
|
-
for (const [,
|
|
47396
|
-
|
|
47397
|
-
const toKeep =
|
|
47615
|
+
for (const [, recs] of recordsByTest) {
|
|
47616
|
+
recs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
47617
|
+
const toKeep = recs.slice(-MAX_HISTORY_PER_TEST);
|
|
47398
47618
|
prunedRecords.push(...toKeep);
|
|
47399
47619
|
}
|
|
47400
47620
|
prunedRecords.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
@@ -47432,8 +47652,9 @@ function readAllRecords(historyPath) {
|
|
|
47432
47652
|
}
|
|
47433
47653
|
try {
|
|
47434
47654
|
const parsed = JSON.parse(trimmed);
|
|
47435
|
-
|
|
47436
|
-
|
|
47655
|
+
const record3 = parseStoredRecord(parsed);
|
|
47656
|
+
if (record3) {
|
|
47657
|
+
records.push(record3);
|
|
47437
47658
|
}
|
|
47438
47659
|
} catch {}
|
|
47439
47660
|
}
|
|
@@ -47448,13 +47669,17 @@ function getAllHistory(workingDir) {
|
|
|
47448
47669
|
records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
47449
47670
|
return records;
|
|
47450
47671
|
}
|
|
47451
|
-
var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES;
|
|
47672
|
+
var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES, _internals23;
|
|
47452
47673
|
var init_history_store = __esm(() => {
|
|
47674
|
+
init_manager2();
|
|
47453
47675
|
DANGEROUS_PROPERTY_NAMES = new Set([
|
|
47454
47676
|
"__proto__",
|
|
47455
47677
|
"constructor",
|
|
47456
47678
|
"prototype"
|
|
47457
47679
|
]);
|
|
47680
|
+
_internals23 = {
|
|
47681
|
+
validateProjectRoot
|
|
47682
|
+
};
|
|
47458
47683
|
});
|
|
47459
47684
|
|
|
47460
47685
|
// src/tools/resolve-working-directory.ts
|
|
@@ -47578,7 +47803,7 @@ function readPackageJsonRaw(dir) {
|
|
|
47578
47803
|
}
|
|
47579
47804
|
}
|
|
47580
47805
|
function readPackageJson(dir) {
|
|
47581
|
-
return
|
|
47806
|
+
return _internals24.readPackageJsonRaw(dir);
|
|
47582
47807
|
}
|
|
47583
47808
|
function readPackageJsonTestScript(dir) {
|
|
47584
47809
|
return readPackageJson(dir)?.scripts?.test ?? null;
|
|
@@ -47748,7 +47973,7 @@ function buildTypescriptBackend() {
|
|
|
47748
47973
|
selectEntryPoints: selectEntryPoints3
|
|
47749
47974
|
};
|
|
47750
47975
|
}
|
|
47751
|
-
var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2,
|
|
47976
|
+
var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals24;
|
|
47752
47977
|
var init_typescript = __esm(() => {
|
|
47753
47978
|
init_default_backend();
|
|
47754
47979
|
init_profiles();
|
|
@@ -47757,7 +47982,7 @@ var init_typescript = __esm(() => {
|
|
|
47757
47982
|
IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
47758
47983
|
IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
47759
47984
|
IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
47760
|
-
|
|
47985
|
+
_internals24 = {
|
|
47761
47986
|
readPackageJsonRaw,
|
|
47762
47987
|
readPackageJsonTestScript,
|
|
47763
47988
|
frameworkFromScriptsTest
|
|
@@ -47788,7 +48013,7 @@ __export(exports_dispatch, {
|
|
|
47788
48013
|
pickedProfiles: () => pickedProfiles,
|
|
47789
48014
|
pickBackend: () => pickBackend,
|
|
47790
48015
|
clearDispatchCache: () => clearDispatchCache,
|
|
47791
|
-
_internals: () =>
|
|
48016
|
+
_internals: () => _internals25
|
|
47792
48017
|
});
|
|
47793
48018
|
import * as fs21 from "fs";
|
|
47794
48019
|
import * as path38 from "path";
|
|
@@ -47843,7 +48068,7 @@ function findManifestRoot(start) {
|
|
|
47843
48068
|
return start;
|
|
47844
48069
|
}
|
|
47845
48070
|
function evictIfNeeded() {
|
|
47846
|
-
if (cache.size <=
|
|
48071
|
+
if (cache.size <= _internals25.cacheCapacity)
|
|
47847
48072
|
return;
|
|
47848
48073
|
let oldestKey;
|
|
47849
48074
|
let oldestOrder = Infinity;
|
|
@@ -47874,7 +48099,7 @@ async function pickBackend(dir) {
|
|
|
47874
48099
|
evictIfNeeded();
|
|
47875
48100
|
return null;
|
|
47876
48101
|
}
|
|
47877
|
-
const profiles = await
|
|
48102
|
+
const profiles = await _internals25.detectProjectLanguages(root);
|
|
47878
48103
|
if (profiles.length === 0) {
|
|
47879
48104
|
cache.set(cacheKey, {
|
|
47880
48105
|
hash: hash3,
|
|
@@ -47906,12 +48131,12 @@ function clearDispatchCache() {
|
|
|
47906
48131
|
manifestRootCache.clear();
|
|
47907
48132
|
insertCounter = 0;
|
|
47908
48133
|
}
|
|
47909
|
-
var
|
|
48134
|
+
var _internals25, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
|
|
47910
48135
|
var init_dispatch = __esm(() => {
|
|
47911
48136
|
init_backends();
|
|
47912
48137
|
init_detector();
|
|
47913
48138
|
init_registry_backend();
|
|
47914
|
-
|
|
48139
|
+
_internals25 = {
|
|
47915
48140
|
detectProjectLanguages,
|
|
47916
48141
|
cacheCapacity: 64
|
|
47917
48142
|
};
|
|
@@ -48472,7 +48697,14 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
48472
48697
|
return args;
|
|
48473
48698
|
}
|
|
48474
48699
|
case "vitest": {
|
|
48475
|
-
const args = [
|
|
48700
|
+
const args = [
|
|
48701
|
+
"npx",
|
|
48702
|
+
"vitest",
|
|
48703
|
+
"run",
|
|
48704
|
+
"--reporter=json",
|
|
48705
|
+
"--outputFile",
|
|
48706
|
+
VITEST_JSON_OUTPUT_RELATIVE_PATH
|
|
48707
|
+
];
|
|
48476
48708
|
if (coverage)
|
|
48477
48709
|
args.push("--coverage");
|
|
48478
48710
|
if (scope !== "all" && files.length > 0) {
|
|
@@ -48481,7 +48713,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
48481
48713
|
return args;
|
|
48482
48714
|
}
|
|
48483
48715
|
case "jest": {
|
|
48484
|
-
const args = ["npx", "jest"];
|
|
48716
|
+
const args = ["npx", "jest", "--json"];
|
|
48485
48717
|
if (coverage)
|
|
48486
48718
|
args.push("--coverage");
|
|
48487
48719
|
if (scope !== "all" && files.length > 0) {
|
|
@@ -48577,6 +48809,122 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
48577
48809
|
return null;
|
|
48578
48810
|
}
|
|
48579
48811
|
}
|
|
48812
|
+
function mapFrameworkStatusToResult(status) {
|
|
48813
|
+
if (typeof status !== "string")
|
|
48814
|
+
return null;
|
|
48815
|
+
const normalized = status.toLowerCase();
|
|
48816
|
+
if (normalized === "pass" || normalized === "passed")
|
|
48817
|
+
return "pass";
|
|
48818
|
+
if (normalized === "fail" || normalized === "failed")
|
|
48819
|
+
return "fail";
|
|
48820
|
+
if (normalized === "skip" || normalized === "skipped" || normalized === "pending" || normalized === "todo") {
|
|
48821
|
+
return "skip";
|
|
48822
|
+
}
|
|
48823
|
+
return null;
|
|
48824
|
+
}
|
|
48825
|
+
function firstLine(value) {
|
|
48826
|
+
if (typeof value !== "string")
|
|
48827
|
+
return;
|
|
48828
|
+
const line = value.split(`
|
|
48829
|
+
`).find((part) => part.trim().length > 0)?.trim();
|
|
48830
|
+
return line && line.length > 0 ? line : undefined;
|
|
48831
|
+
}
|
|
48832
|
+
function parseJestLikeJsonTestResults(payload) {
|
|
48833
|
+
if (typeof payload !== "object" || payload === null)
|
|
48834
|
+
return [];
|
|
48835
|
+
const rawSuites = payload.testResults;
|
|
48836
|
+
if (!Array.isArray(rawSuites))
|
|
48837
|
+
return [];
|
|
48838
|
+
const parsed = [];
|
|
48839
|
+
for (const suite of rawSuites) {
|
|
48840
|
+
if (typeof suite !== "object" || suite === null)
|
|
48841
|
+
continue;
|
|
48842
|
+
const suiteObj = suite;
|
|
48843
|
+
const rawFile = typeof suiteObj.name === "string" ? suiteObj.name : typeof suiteObj.testFilePath === "string" ? suiteObj.testFilePath : undefined;
|
|
48844
|
+
if (!rawFile)
|
|
48845
|
+
continue;
|
|
48846
|
+
const testFile = rawFile.replace(/\\/g, "/");
|
|
48847
|
+
const assertionResults = suiteObj.assertionResults;
|
|
48848
|
+
if (!Array.isArray(assertionResults))
|
|
48849
|
+
continue;
|
|
48850
|
+
for (const assertion of assertionResults) {
|
|
48851
|
+
if (typeof assertion !== "object" || assertion === null)
|
|
48852
|
+
continue;
|
|
48853
|
+
const assertionObj = assertion;
|
|
48854
|
+
const result = mapFrameworkStatusToResult(assertionObj.status);
|
|
48855
|
+
const testName = typeof assertionObj.fullName === "string" ? assertionObj.fullName : typeof assertionObj.title === "string" ? assertionObj.title : undefined;
|
|
48856
|
+
if (!result || !testName || testName.length === 0)
|
|
48857
|
+
continue;
|
|
48858
|
+
const failureMessages = Array.isArray(assertionObj.failureMessages) ? assertionObj.failureMessages : [];
|
|
48859
|
+
const firstFailure = failureMessages.find((entry) => typeof entry === "string" && entry.length > 0);
|
|
48860
|
+
const durationMs = typeof assertionObj.duration === "number" && Number.isFinite(assertionObj.duration) ? Math.max(assertionObj.duration, 0) : 0;
|
|
48861
|
+
parsed.push({
|
|
48862
|
+
testFile,
|
|
48863
|
+
testName,
|
|
48864
|
+
result,
|
|
48865
|
+
durationMs,
|
|
48866
|
+
errorMessage: firstLine(firstFailure),
|
|
48867
|
+
stackPrefix: firstLine(firstFailure)
|
|
48868
|
+
});
|
|
48869
|
+
}
|
|
48870
|
+
}
|
|
48871
|
+
return parsed;
|
|
48872
|
+
}
|
|
48873
|
+
function parseBunJsonLines(output) {
|
|
48874
|
+
const parsed = [];
|
|
48875
|
+
for (const line of output.split(`
|
|
48876
|
+
`)) {
|
|
48877
|
+
const trimmed = line.trim();
|
|
48878
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
|
|
48879
|
+
continue;
|
|
48880
|
+
try {
|
|
48881
|
+
const obj = JSON.parse(trimmed);
|
|
48882
|
+
const rawFile = typeof obj.file === "string" ? obj.file : typeof obj.testFile === "string" ? obj.testFile : typeof obj.path === "string" ? obj.path : undefined;
|
|
48883
|
+
const rawName = typeof obj.testName === "string" ? obj.testName : typeof obj.fullName === "string" ? obj.fullName : typeof obj.name === "string" ? obj.name : undefined;
|
|
48884
|
+
const result = mapFrameworkStatusToResult(typeof obj.status === "string" ? obj.status : obj.result);
|
|
48885
|
+
if (!rawFile || !rawName || !result)
|
|
48886
|
+
continue;
|
|
48887
|
+
const errorObj = typeof obj.error === "object" && obj.error !== null ? obj.error : undefined;
|
|
48888
|
+
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;
|
|
48889
|
+
parsed.push({
|
|
48890
|
+
testFile: rawFile.replace(/\\/g, "/"),
|
|
48891
|
+
testName: rawName,
|
|
48892
|
+
result,
|
|
48893
|
+
durationMs,
|
|
48894
|
+
errorMessage: firstLine(errorObj?.message ?? obj.errorMessage),
|
|
48895
|
+
stackPrefix: firstLine(errorObj?.stack)
|
|
48896
|
+
});
|
|
48897
|
+
} catch {}
|
|
48898
|
+
}
|
|
48899
|
+
return parsed;
|
|
48900
|
+
}
|
|
48901
|
+
function parseFrameworkJsonTestResults(framework, output) {
|
|
48902
|
+
const jsonMatch = output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);
|
|
48903
|
+
if (jsonMatch) {
|
|
48904
|
+
try {
|
|
48905
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
48906
|
+
const testResults = parseJestLikeJsonTestResults(parsed);
|
|
48907
|
+
if (testResults.length > 0)
|
|
48908
|
+
return testResults;
|
|
48909
|
+
} catch {}
|
|
48910
|
+
}
|
|
48911
|
+
for (const line of output.split(`
|
|
48912
|
+
`)) {
|
|
48913
|
+
const trimmed = line.trim();
|
|
48914
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
|
|
48915
|
+
continue;
|
|
48916
|
+
try {
|
|
48917
|
+
const parsed = JSON.parse(trimmed);
|
|
48918
|
+
const testResults = parseJestLikeJsonTestResults(parsed);
|
|
48919
|
+
if (testResults.length > 0)
|
|
48920
|
+
return testResults;
|
|
48921
|
+
} catch {}
|
|
48922
|
+
}
|
|
48923
|
+
if (framework === "bun") {
|
|
48924
|
+
return parseBunJsonLines(output);
|
|
48925
|
+
}
|
|
48926
|
+
return [];
|
|
48927
|
+
}
|
|
48580
48928
|
function parseTestOutput2(framework, output) {
|
|
48581
48929
|
const totals = {
|
|
48582
48930
|
passed: 0,
|
|
@@ -48864,7 +49212,16 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
48864
49212
|
};
|
|
48865
49213
|
}
|
|
48866
49214
|
const startTime = Date.now();
|
|
49215
|
+
const vitestJsonOutputPath = framework === "vitest" ? path39.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
48867
49216
|
try {
|
|
49217
|
+
if (vitestJsonOutputPath) {
|
|
49218
|
+
try {
|
|
49219
|
+
fs22.mkdirSync(path39.dirname(vitestJsonOutputPath), { recursive: true });
|
|
49220
|
+
if (fs22.existsSync(vitestJsonOutputPath)) {
|
|
49221
|
+
fs22.unlinkSync(vitestJsonOutputPath);
|
|
49222
|
+
}
|
|
49223
|
+
} catch {}
|
|
49224
|
+
}
|
|
48868
49225
|
const proc = bunSpawn(command, {
|
|
48869
49226
|
stdout: "pipe",
|
|
48870
49227
|
stderr: "pipe",
|
|
@@ -48885,13 +49242,37 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
48885
49242
|
output += (output ? `
|
|
48886
49243
|
` : "") + stderrResult.text;
|
|
48887
49244
|
}
|
|
49245
|
+
if (vitestJsonOutputPath) {
|
|
49246
|
+
try {
|
|
49247
|
+
if (fs22.existsSync(vitestJsonOutputPath)) {
|
|
49248
|
+
const vitestJsonOutput = fs22.readFileSync(vitestJsonOutputPath, "utf-8");
|
|
49249
|
+
if (vitestJsonOutput.trim().length > 0) {
|
|
49250
|
+
output += (output ? `
|
|
49251
|
+
` : "") + vitestJsonOutput;
|
|
49252
|
+
}
|
|
49253
|
+
}
|
|
49254
|
+
} catch {}
|
|
49255
|
+
}
|
|
48888
49256
|
if (stdoutResult.truncated || stderrResult.truncated) {
|
|
48889
49257
|
output += `
|
|
48890
49258
|
... (output truncated at stream read limit)`;
|
|
48891
49259
|
}
|
|
48892
49260
|
const useDispatchParse = process.env.SWARM_LANG_BACKEND !== "legacy";
|
|
48893
49261
|
const parsed = useDispatchParse ? await parseTestOutputViaDispatch(framework, output, cwd) ?? parseTestOutput2(framework, output) : parseTestOutput2(framework, output);
|
|
48894
|
-
const
|
|
49262
|
+
const parsedTestCases = parseFrameworkJsonTestResults(framework, output);
|
|
49263
|
+
const totals = { ...parsed.totals };
|
|
49264
|
+
const { coveragePercent } = parsed;
|
|
49265
|
+
if (totals.total === 0 && parsedTestCases.length > 0) {
|
|
49266
|
+
for (const entry of parsedTestCases) {
|
|
49267
|
+
if (entry.result === "pass")
|
|
49268
|
+
totals.passed++;
|
|
49269
|
+
else if (entry.result === "fail")
|
|
49270
|
+
totals.failed++;
|
|
49271
|
+
else
|
|
49272
|
+
totals.skipped++;
|
|
49273
|
+
}
|
|
49274
|
+
totals.total = parsedTestCases.length;
|
|
49275
|
+
}
|
|
48895
49276
|
const isTimeout = exitCode === -1;
|
|
48896
49277
|
const testPassed = exitCode === 0 && totals.failed === 0;
|
|
48897
49278
|
if (testPassed) {
|
|
@@ -48904,7 +49285,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
48904
49285
|
duration_ms,
|
|
48905
49286
|
totals,
|
|
48906
49287
|
rawOutput: output,
|
|
48907
|
-
outcome: "pass"
|
|
49288
|
+
outcome: "pass",
|
|
49289
|
+
testCases: parsedTestCases
|
|
48908
49290
|
};
|
|
48909
49291
|
if (coveragePercent !== undefined) {
|
|
48910
49292
|
result.coveragePercent = coveragePercent;
|
|
@@ -48926,7 +49308,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
48926
49308
|
rawOutput: output,
|
|
48927
49309
|
error: isTimeout ? `Tests timed out after ${timeout_ms}ms` : `Tests failed with ${totals.failed} failures`,
|
|
48928
49310
|
message: isTimeout ? `${framework} tests timed out after ${timeout_ms}ms` : `${framework} tests failed (${totals.failed}/${totals.total} failed)`,
|
|
48929
|
-
outcome: isTimeout ? "error" : "regression"
|
|
49311
|
+
outcome: isTimeout ? "error" : "regression",
|
|
49312
|
+
testCases: parsedTestCases
|
|
48930
49313
|
};
|
|
48931
49314
|
if (coveragePercent !== undefined) {
|
|
48932
49315
|
result.coveragePercent = coveragePercent;
|
|
@@ -48947,24 +49330,77 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
48947
49330
|
};
|
|
48948
49331
|
}
|
|
48949
49332
|
}
|
|
48950
|
-
function
|
|
49333
|
+
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
49334
|
+
const normalized = testFile.replace(/\\/g, "/");
|
|
49335
|
+
if (!path39.isAbsolute(testFile))
|
|
49336
|
+
return normalized;
|
|
49337
|
+
const relative9 = path39.relative(workingDir, testFile);
|
|
49338
|
+
if (relative9.startsWith("..") || path39.isAbsolute(relative9)) {
|
|
49339
|
+
return normalized;
|
|
49340
|
+
}
|
|
49341
|
+
return relative9.replace(/\\/g, "/");
|
|
49342
|
+
}
|
|
49343
|
+
function combineAggregateResult(current, next) {
|
|
49344
|
+
if (current === "fail" || next === "fail")
|
|
49345
|
+
return "fail";
|
|
49346
|
+
if (current === "pass" || next === "pass")
|
|
49347
|
+
return "pass";
|
|
49348
|
+
return "skip";
|
|
49349
|
+
}
|
|
49350
|
+
function recordAndAnalyzeResults(result, testFiles, workingDir, sourceFiles, parsedTestCases) {
|
|
48951
49351
|
if (!result.totals || result.totals.total === 0)
|
|
48952
49352
|
return;
|
|
48953
49353
|
const now = new Date().toISOString();
|
|
48954
49354
|
const changedFiles = (sourceFiles && sourceFiles.length > 0 ? sourceFiles : testFiles).map((f) => f.replace(/\\/g, "/"));
|
|
48955
|
-
|
|
48956
|
-
|
|
48957
|
-
|
|
48958
|
-
|
|
48959
|
-
|
|
48960
|
-
|
|
48961
|
-
|
|
48962
|
-
|
|
48963
|
-
|
|
48964
|
-
|
|
48965
|
-
|
|
48966
|
-
|
|
49355
|
+
const aggregateResultsByFile = new Map;
|
|
49356
|
+
const validParsedCases = parsedTestCases?.filter((parsedCase) => parsedCase.testFile.length > 0 && parsedCase.testName.length > 0) ?? [];
|
|
49357
|
+
const allRecords = [];
|
|
49358
|
+
for (const parsedCase of validParsedCases) {
|
|
49359
|
+
const normalizedTestFile = normalizeHistoryTestFile(parsedCase.testFile, workingDir);
|
|
49360
|
+
allRecords.push({
|
|
49361
|
+
timestamp: now,
|
|
49362
|
+
taskId: "auto",
|
|
49363
|
+
testFile: normalizedTestFile,
|
|
49364
|
+
testName: parsedCase.testName,
|
|
49365
|
+
result: parsedCase.result,
|
|
49366
|
+
durationMs: parsedCase.durationMs,
|
|
49367
|
+
errorMessage: parsedCase.errorMessage,
|
|
49368
|
+
stackPrefix: parsedCase.stackPrefix,
|
|
49369
|
+
changedFiles
|
|
49370
|
+
});
|
|
49371
|
+
aggregateResultsByFile.set(normalizedTestFile, combineAggregateResult(aggregateResultsByFile.get(normalizedTestFile), parsedCase.result));
|
|
49372
|
+
}
|
|
49373
|
+
if (aggregateResultsByFile.size === 0) {
|
|
49374
|
+
const aggregateResult = result.success ? "pass" : "fail";
|
|
49375
|
+
for (const testFile of testFiles) {
|
|
49376
|
+
aggregateResultsByFile.set(testFile.replace(/\\/g, "/"), aggregateResult);
|
|
49377
|
+
}
|
|
49378
|
+
}
|
|
49379
|
+
for (const [testFile, aggregateResult] of aggregateResultsByFile) {
|
|
49380
|
+
allRecords.push({
|
|
49381
|
+
timestamp: now,
|
|
49382
|
+
taskId: "auto",
|
|
49383
|
+
testFile,
|
|
49384
|
+
testName: AGGREGATE_TEST_NAME,
|
|
49385
|
+
result: aggregateResult,
|
|
49386
|
+
durationMs: result.duration_ms || 0,
|
|
49387
|
+
changedFiles
|
|
49388
|
+
});
|
|
49389
|
+
}
|
|
49390
|
+
try {
|
|
49391
|
+
batchAppendTestRuns(allRecords, workingDir);
|
|
49392
|
+
} catch {}
|
|
49393
|
+
}
|
|
49394
|
+
function selectHistoryForAnalysis(history) {
|
|
49395
|
+
const filesWithIndividualRecords = new Set;
|
|
49396
|
+
for (const record3 of history) {
|
|
49397
|
+
if (record3.testName !== AGGREGATE_TEST_NAME) {
|
|
49398
|
+
filesWithIndividualRecords.add(record3.testFile.toLowerCase());
|
|
49399
|
+
}
|
|
48967
49400
|
}
|
|
49401
|
+
if (filesWithIndividualRecords.size === 0)
|
|
49402
|
+
return history;
|
|
49403
|
+
return history.filter((record3) => record3.testName !== AGGREGATE_TEST_NAME || !filesWithIndividualRecords.has(record3.testFile.toLowerCase()));
|
|
48968
49404
|
}
|
|
48969
49405
|
function analyzeFailures(workingDir) {
|
|
48970
49406
|
const report = {
|
|
@@ -48973,7 +49409,7 @@ function analyzeFailures(workingDir) {
|
|
|
48973
49409
|
quarantinedFailures: []
|
|
48974
49410
|
};
|
|
48975
49411
|
try {
|
|
48976
|
-
const history = getAllHistory(workingDir);
|
|
49412
|
+
const history = selectHistoryForAnalysis(getAllHistory(workingDir));
|
|
48977
49413
|
if (history.length === 0)
|
|
48978
49414
|
return report;
|
|
48979
49415
|
report.flakyTests = detectFlakyTests(history);
|
|
@@ -48994,12 +49430,11 @@ function analyzeFailures(workingDir) {
|
|
|
48994
49430
|
} catch {}
|
|
48995
49431
|
return report;
|
|
48996
49432
|
}
|
|
48997
|
-
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;
|
|
49433
|
+
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;
|
|
48998
49434
|
var init_test_runner = __esm(() => {
|
|
48999
49435
|
init_zod();
|
|
49000
49436
|
init_discovery();
|
|
49001
49437
|
init_analyzer();
|
|
49002
|
-
init_failure_classifier();
|
|
49003
49438
|
init_history_store();
|
|
49004
49439
|
init_bun_compat();
|
|
49005
49440
|
init_path_security();
|
|
@@ -49441,7 +49876,7 @@ var init_test_runner = __esm(() => {
|
|
|
49441
49876
|
return JSON.stringify(errorResult, null, 2);
|
|
49442
49877
|
}
|
|
49443
49878
|
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir);
|
|
49444
|
-
recordAndAnalyzeResults(result, testFiles, workingDir, _files.length > 0 ? _files : undefined);
|
|
49879
|
+
recordAndAnalyzeResults(result, testFiles, workingDir, _files.length > 0 ? _files : undefined, result.testCases);
|
|
49445
49880
|
let historyReport;
|
|
49446
49881
|
if (!result.success && result.totals && result.totals.failed > 0) {
|
|
49447
49882
|
historyReport = analyzeFailures(workingDir);
|
|
@@ -49536,9 +49971,9 @@ function getVersionFileVersion(dir) {
|
|
|
49536
49971
|
async function runVersionCheck(dir, _timeoutMs) {
|
|
49537
49972
|
const startTime = Date.now();
|
|
49538
49973
|
try {
|
|
49539
|
-
const packageVersion =
|
|
49540
|
-
const changelogVersion =
|
|
49541
|
-
const versionFileVersion =
|
|
49974
|
+
const packageVersion = _internals26.getPackageVersion(dir);
|
|
49975
|
+
const changelogVersion = _internals26.getChangelogVersion(dir);
|
|
49976
|
+
const versionFileVersion = _internals26.getVersionFileVersion(dir);
|
|
49542
49977
|
const versions3 = [];
|
|
49543
49978
|
if (packageVersion)
|
|
49544
49979
|
versions3.push(`package.json: ${packageVersion}`);
|
|
@@ -49888,7 +50323,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49888
50323
|
const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
49889
50324
|
let validatedDir;
|
|
49890
50325
|
try {
|
|
49891
|
-
validatedDir =
|
|
50326
|
+
validatedDir = _internals26.validateDirectoryPath(dir);
|
|
49892
50327
|
} catch (error93) {
|
|
49893
50328
|
return {
|
|
49894
50329
|
id: reportId,
|
|
@@ -49908,7 +50343,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49908
50343
|
}
|
|
49909
50344
|
let validatedTimeout;
|
|
49910
50345
|
try {
|
|
49911
|
-
validatedTimeout =
|
|
50346
|
+
validatedTimeout = _internals26.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
49912
50347
|
} catch (error93) {
|
|
49913
50348
|
return {
|
|
49914
50349
|
id: reportId,
|
|
@@ -49949,12 +50384,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49949
50384
|
});
|
|
49950
50385
|
const checks5 = [];
|
|
49951
50386
|
log("[Preflight] Running lint check...");
|
|
49952
|
-
const lintResult = await
|
|
50387
|
+
const lintResult = await _internals26.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
49953
50388
|
checks5.push(lintResult);
|
|
49954
50389
|
log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
|
|
49955
50390
|
if (!cfg.skipTests) {
|
|
49956
50391
|
log("[Preflight] Running tests check...");
|
|
49957
|
-
const testsResult = await
|
|
50392
|
+
const testsResult = await _internals26.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
49958
50393
|
checks5.push(testsResult);
|
|
49959
50394
|
log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
|
|
49960
50395
|
} else {
|
|
@@ -49966,7 +50401,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49966
50401
|
}
|
|
49967
50402
|
if (!cfg.skipSecrets) {
|
|
49968
50403
|
log("[Preflight] Running secrets check...");
|
|
49969
|
-
const secretsResult = await
|
|
50404
|
+
const secretsResult = await _internals26.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
49970
50405
|
checks5.push(secretsResult);
|
|
49971
50406
|
log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
|
|
49972
50407
|
} else {
|
|
@@ -49978,7 +50413,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49978
50413
|
}
|
|
49979
50414
|
if (!cfg.skipEvidence) {
|
|
49980
50415
|
log("[Preflight] Running evidence check...");
|
|
49981
|
-
const evidenceResult = await
|
|
50416
|
+
const evidenceResult = await _internals26.runEvidenceCheck(validatedDir);
|
|
49982
50417
|
checks5.push(evidenceResult);
|
|
49983
50418
|
log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
|
|
49984
50419
|
} else {
|
|
@@ -49989,12 +50424,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49989
50424
|
});
|
|
49990
50425
|
}
|
|
49991
50426
|
log("[Preflight] Running requirement coverage check...");
|
|
49992
|
-
const reqCoverageResult = await
|
|
50427
|
+
const reqCoverageResult = await _internals26.runRequirementCoverageCheck(validatedDir, phase);
|
|
49993
50428
|
checks5.push(reqCoverageResult);
|
|
49994
50429
|
log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
|
|
49995
50430
|
if (!cfg.skipVersion) {
|
|
49996
50431
|
log("[Preflight] Running version check...");
|
|
49997
|
-
const versionResult = await
|
|
50432
|
+
const versionResult = await _internals26.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
49998
50433
|
checks5.push(versionResult);
|
|
49999
50434
|
log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
|
|
50000
50435
|
} else {
|
|
@@ -50057,10 +50492,10 @@ function formatPreflightMarkdown(report) {
|
|
|
50057
50492
|
async function handlePreflightCommand(directory, _args) {
|
|
50058
50493
|
const plan = await loadPlan(directory);
|
|
50059
50494
|
const phase = plan?.current_phase ?? 1;
|
|
50060
|
-
const report = await
|
|
50061
|
-
return
|
|
50495
|
+
const report = await _internals26.runPreflight(directory, phase);
|
|
50496
|
+
return _internals26.formatPreflightMarkdown(report);
|
|
50062
50497
|
}
|
|
50063
|
-
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG,
|
|
50498
|
+
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals26;
|
|
50064
50499
|
var init_preflight_service = __esm(() => {
|
|
50065
50500
|
init_manager2();
|
|
50066
50501
|
init_manager();
|
|
@@ -50077,7 +50512,7 @@ var init_preflight_service = __esm(() => {
|
|
|
50077
50512
|
testScope: "convention",
|
|
50078
50513
|
linter: "biome"
|
|
50079
50514
|
};
|
|
50080
|
-
|
|
50515
|
+
_internals26 = {
|
|
50081
50516
|
runPreflight,
|
|
50082
50517
|
formatPreflightMarkdown,
|
|
50083
50518
|
handlePreflightCommand,
|
|
@@ -51699,7 +52134,7 @@ async function getStatusData(directory, agents) {
|
|
|
51699
52134
|
}
|
|
51700
52135
|
function enrichWithLeanTurbo(status, directory) {
|
|
51701
52136
|
const turboMode = hasActiveTurboMode();
|
|
51702
|
-
const leanActive =
|
|
52137
|
+
const leanActive = _internals27.hasActiveLeanTurbo();
|
|
51703
52138
|
let turboStrategy = "off";
|
|
51704
52139
|
if (leanActive) {
|
|
51705
52140
|
turboStrategy = "lean";
|
|
@@ -51718,7 +52153,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
51718
52153
|
}
|
|
51719
52154
|
}
|
|
51720
52155
|
if (leanSessionID) {
|
|
51721
|
-
const runState =
|
|
52156
|
+
const runState = _internals27.loadLeanTurboRunState(directory, leanSessionID);
|
|
51722
52157
|
if (runState) {
|
|
51723
52158
|
status.leanTurboPhase = runState.phase;
|
|
51724
52159
|
status.leanMaxParallelCoders = runState.maxParallelCoders;
|
|
@@ -51750,7 +52185,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
51750
52185
|
}
|
|
51751
52186
|
}
|
|
51752
52187
|
}
|
|
51753
|
-
status.fullAutoActive =
|
|
52188
|
+
status.fullAutoActive = _internals27.hasActiveFullAuto();
|
|
51754
52189
|
return status;
|
|
51755
52190
|
}
|
|
51756
52191
|
function formatStatusMarkdown(status) {
|
|
@@ -51832,7 +52267,7 @@ async function handleStatusCommand(directory, agents) {
|
|
|
51832
52267
|
}
|
|
51833
52268
|
return formatStatusMarkdown(statusData);
|
|
51834
52269
|
}
|
|
51835
|
-
var
|
|
52270
|
+
var _internals27;
|
|
51836
52271
|
var init_status_service = __esm(() => {
|
|
51837
52272
|
init_extractors();
|
|
51838
52273
|
init_utils2();
|
|
@@ -51841,7 +52276,7 @@ var init_status_service = __esm(() => {
|
|
|
51841
52276
|
init_state3();
|
|
51842
52277
|
init_compaction_service();
|
|
51843
52278
|
init_context_budget_service();
|
|
51844
|
-
|
|
52279
|
+
_internals27 = {
|
|
51845
52280
|
loadLeanTurboRunState,
|
|
51846
52281
|
hasActiveLeanTurbo,
|
|
51847
52282
|
hasActiveFullAuto
|
|
@@ -51932,7 +52367,7 @@ async function handleTurboCommand(directory, args, sessionID) {
|
|
|
51932
52367
|
if (arg0 === "on") {
|
|
51933
52368
|
let strategy = "standard";
|
|
51934
52369
|
try {
|
|
51935
|
-
const { config: config3 } =
|
|
52370
|
+
const { config: config3 } = _internals28.loadPluginConfigWithMeta(directory);
|
|
51936
52371
|
if (config3.turbo?.strategy === "lean") {
|
|
51937
52372
|
strategy = "lean";
|
|
51938
52373
|
}
|
|
@@ -51987,7 +52422,7 @@ function enableLeanTurbo(session, directory, sessionID) {
|
|
|
51987
52422
|
let maxParallelCoders = 4;
|
|
51988
52423
|
let conflictPolicy = "serialize";
|
|
51989
52424
|
try {
|
|
51990
|
-
const { config: config3 } =
|
|
52425
|
+
const { config: config3 } = _internals28.loadPluginConfigWithMeta(directory);
|
|
51991
52426
|
const leanConfig = config3.turbo?.lean;
|
|
51992
52427
|
if (leanConfig) {
|
|
51993
52428
|
maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
|
|
@@ -52057,13 +52492,13 @@ function buildStatusMessage(session, directory, sessionID) {
|
|
|
52057
52492
|
].join(`
|
|
52058
52493
|
`);
|
|
52059
52494
|
}
|
|
52060
|
-
var
|
|
52495
|
+
var _internals28;
|
|
52061
52496
|
var init_turbo = __esm(() => {
|
|
52062
52497
|
init_config();
|
|
52063
52498
|
init_state();
|
|
52064
52499
|
init_state3();
|
|
52065
52500
|
init_logger();
|
|
52066
|
-
|
|
52501
|
+
_internals28 = {
|
|
52067
52502
|
loadPluginConfigWithMeta
|
|
52068
52503
|
};
|
|
52069
52504
|
});
|
|
@@ -52156,7 +52591,7 @@ function formatCommandNotFound(tokens) {
|
|
|
52156
52591
|
const attemptedCommand = tokens[0] || "";
|
|
52157
52592
|
const MAX_DISPLAY = 100;
|
|
52158
52593
|
const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
|
|
52159
|
-
const similar =
|
|
52594
|
+
const similar = _internals29.findSimilarCommands(attemptedCommand);
|
|
52160
52595
|
const header = `Command \`/swarm ${displayCommand}\` not found.`;
|
|
52161
52596
|
const suggestions = similar.length > 0 ? `Did you mean:
|
|
52162
52597
|
${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
@@ -52605,7 +53040,7 @@ async function buildSwarmCommandPrompt(args) {
|
|
|
52605
53040
|
activeAgentName,
|
|
52606
53041
|
registeredAgents
|
|
52607
53042
|
} = args;
|
|
52608
|
-
const resolved =
|
|
53043
|
+
const resolved = _internals29.resolveCommand(tokens);
|
|
52609
53044
|
if (!resolved) {
|
|
52610
53045
|
if (tokens.length === 0) {
|
|
52611
53046
|
return buildHelpText();
|
|
@@ -52756,7 +53191,7 @@ function findSimilarCommands(query) {
|
|
|
52756
53191
|
}
|
|
52757
53192
|
const scored = VALID_COMMANDS.map((cmd) => {
|
|
52758
53193
|
const cmdLower = cmd.toLowerCase();
|
|
52759
|
-
const fullScore =
|
|
53194
|
+
const fullScore = _internals29.levenshteinDistance(q, cmdLower);
|
|
52760
53195
|
let tokenScore = Infinity;
|
|
52761
53196
|
if (cmd.includes(" ") || cmd.includes("-")) {
|
|
52762
53197
|
const qTokens = q.split(/[\s-]+/);
|
|
@@ -52769,7 +53204,7 @@ function findSimilarCommands(query) {
|
|
|
52769
53204
|
for (const ct of cmdTokens) {
|
|
52770
53205
|
if (ct.length === 0)
|
|
52771
53206
|
continue;
|
|
52772
|
-
const dist =
|
|
53207
|
+
const dist = _internals29.levenshteinDistance(qt, ct);
|
|
52773
53208
|
if (dist < minDist)
|
|
52774
53209
|
minDist = dist;
|
|
52775
53210
|
}
|
|
@@ -52779,7 +53214,7 @@ function findSimilarCommands(query) {
|
|
|
52779
53214
|
}
|
|
52780
53215
|
const dashStrippedQ = q.replace(/-/g, "");
|
|
52781
53216
|
const dashStrippedCmd = cmdLower.replace(/-/g, "");
|
|
52782
|
-
const dashScore =
|
|
53217
|
+
const dashScore = _internals29.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
|
|
52783
53218
|
const score = Math.min(fullScore, tokenScore, dashScore);
|
|
52784
53219
|
return { cmd, score };
|
|
52785
53220
|
});
|
|
@@ -52811,11 +53246,11 @@ async function handleHelpCommand(ctx) {
|
|
|
52811
53246
|
return buildHelpText2();
|
|
52812
53247
|
}
|
|
52813
53248
|
const tokens = targetCommand.split(/\s+/);
|
|
52814
|
-
const resolved =
|
|
53249
|
+
const resolved = _internals29.resolveCommand(tokens);
|
|
52815
53250
|
if (resolved) {
|
|
52816
|
-
return
|
|
53251
|
+
return _internals29.buildDetailedHelp(resolved.key, resolved.entry);
|
|
52817
53252
|
}
|
|
52818
|
-
const similar =
|
|
53253
|
+
const similar = _internals29.findSimilarCommands(targetCommand);
|
|
52819
53254
|
const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
|
|
52820
53255
|
if (similar.length > 0) {
|
|
52821
53256
|
return `Command '/swarm ${targetCommand}' not found.
|
|
@@ -52909,7 +53344,7 @@ function resolveCommand(tokens) {
|
|
|
52909
53344
|
}
|
|
52910
53345
|
return null;
|
|
52911
53346
|
}
|
|
52912
|
-
var COMMAND_REGISTRY, VALID_COMMANDS,
|
|
53347
|
+
var COMMAND_REGISTRY, VALID_COMMANDS, _internals29, validation;
|
|
52913
53348
|
var init_registry = __esm(() => {
|
|
52914
53349
|
init_acknowledge_spec_drift();
|
|
52915
53350
|
init_agents();
|
|
@@ -52979,7 +53414,7 @@ var init_registry = __esm(() => {
|
|
|
52979
53414
|
clashesWithNativeCcCommand: "/agents"
|
|
52980
53415
|
},
|
|
52981
53416
|
help: {
|
|
52982
|
-
handler: (ctx) =>
|
|
53417
|
+
handler: (ctx) => _internals29.handleHelpCommand(ctx),
|
|
52983
53418
|
description: "Show help for swarm commands",
|
|
52984
53419
|
category: "core",
|
|
52985
53420
|
args: "[command]",
|
|
@@ -53351,7 +53786,7 @@ Subcommands:
|
|
|
53351
53786
|
}
|
|
53352
53787
|
};
|
|
53353
53788
|
VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
|
|
53354
|
-
|
|
53789
|
+
_internals29 = {
|
|
53355
53790
|
handleHelpCommand,
|
|
53356
53791
|
validateAliases,
|
|
53357
53792
|
resolveCommand,
|
|
@@ -53359,7 +53794,7 @@ Subcommands:
|
|
|
53359
53794
|
findSimilarCommands,
|
|
53360
53795
|
buildDetailedHelp
|
|
53361
53796
|
};
|
|
53362
|
-
validation =
|
|
53797
|
+
validation = _internals29.validateAliases();
|
|
53363
53798
|
if (!validation.valid) {
|
|
53364
53799
|
throw new Error(`COMMAND_REGISTRY alias validation failed:
|
|
53365
53800
|
${validation.errors.join(`
|