opencode-swarm 6.41.2 → 6.41.3
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 +246 -159
- package/dist/index.js +750 -609
- package/dist/tools/completion-verify.d.ts +2 -0
- package/dist/tools/resolve-working-directory.d.ts +35 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35466,9 +35466,52 @@ var init_secretscan = __esm(() => {
|
|
|
35466
35466
|
});
|
|
35467
35467
|
});
|
|
35468
35468
|
|
|
35469
|
-
// src/tools/
|
|
35469
|
+
// src/tools/resolve-working-directory.ts
|
|
35470
35470
|
import * as fs15 from "fs";
|
|
35471
35471
|
import * as path26 from "path";
|
|
35472
|
+
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
35473
|
+
if (workingDirectory == null || workingDirectory === "") {
|
|
35474
|
+
return { success: true, directory: fallbackDirectory };
|
|
35475
|
+
}
|
|
35476
|
+
if (workingDirectory.includes("\x00")) {
|
|
35477
|
+
return {
|
|
35478
|
+
success: false,
|
|
35479
|
+
message: "Invalid working_directory: null bytes are not allowed"
|
|
35480
|
+
};
|
|
35481
|
+
}
|
|
35482
|
+
if (process.platform === "win32") {
|
|
35483
|
+
const devicePathPattern = /^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i;
|
|
35484
|
+
if (devicePathPattern.test(workingDirectory)) {
|
|
35485
|
+
return {
|
|
35486
|
+
success: false,
|
|
35487
|
+
message: "Invalid working_directory: Windows device paths are not allowed"
|
|
35488
|
+
};
|
|
35489
|
+
}
|
|
35490
|
+
}
|
|
35491
|
+
const normalizedDir = path26.normalize(workingDirectory);
|
|
35492
|
+
const pathParts = normalizedDir.split(path26.sep);
|
|
35493
|
+
if (pathParts.includes("..")) {
|
|
35494
|
+
return {
|
|
35495
|
+
success: false,
|
|
35496
|
+
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
35497
|
+
};
|
|
35498
|
+
}
|
|
35499
|
+
const resolvedDir = path26.resolve(normalizedDir);
|
|
35500
|
+
try {
|
|
35501
|
+
const realPath = fs15.realpathSync(resolvedDir);
|
|
35502
|
+
return { success: true, directory: realPath };
|
|
35503
|
+
} catch {
|
|
35504
|
+
return {
|
|
35505
|
+
success: false,
|
|
35506
|
+
message: `Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`
|
|
35507
|
+
};
|
|
35508
|
+
}
|
|
35509
|
+
}
|
|
35510
|
+
var init_resolve_working_directory = () => {};
|
|
35511
|
+
|
|
35512
|
+
// src/tools/test-runner.ts
|
|
35513
|
+
import * as fs16 from "fs";
|
|
35514
|
+
import * as path27 from "path";
|
|
35472
35515
|
function isAbsolutePath(str) {
|
|
35473
35516
|
if (str.startsWith("/"))
|
|
35474
35517
|
return true;
|
|
@@ -35533,19 +35576,19 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
35533
35576
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
35534
35577
|
}
|
|
35535
35578
|
function detectGoTest(cwd) {
|
|
35536
|
-
return
|
|
35579
|
+
return fs16.existsSync(path27.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
35537
35580
|
}
|
|
35538
35581
|
function detectJavaMaven(cwd) {
|
|
35539
|
-
return
|
|
35582
|
+
return fs16.existsSync(path27.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
35540
35583
|
}
|
|
35541
35584
|
function detectGradle(cwd) {
|
|
35542
|
-
const hasBuildFile =
|
|
35543
|
-
const hasGradlew =
|
|
35585
|
+
const hasBuildFile = fs16.existsSync(path27.join(cwd, "build.gradle")) || fs16.existsSync(path27.join(cwd, "build.gradle.kts"));
|
|
35586
|
+
const hasGradlew = fs16.existsSync(path27.join(cwd, "gradlew")) || fs16.existsSync(path27.join(cwd, "gradlew.bat"));
|
|
35544
35587
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
35545
35588
|
}
|
|
35546
35589
|
function detectDotnetTest(cwd) {
|
|
35547
35590
|
try {
|
|
35548
|
-
const files =
|
|
35591
|
+
const files = fs16.readdirSync(cwd);
|
|
35549
35592
|
const hasCsproj = files.some((f) => f.endsWith(".csproj"));
|
|
35550
35593
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
35551
35594
|
} catch {
|
|
@@ -35553,32 +35596,32 @@ function detectDotnetTest(cwd) {
|
|
|
35553
35596
|
}
|
|
35554
35597
|
}
|
|
35555
35598
|
function detectCTest(cwd) {
|
|
35556
|
-
const hasSource =
|
|
35557
|
-
const hasBuildCache =
|
|
35599
|
+
const hasSource = fs16.existsSync(path27.join(cwd, "CMakeLists.txt"));
|
|
35600
|
+
const hasBuildCache = fs16.existsSync(path27.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path27.join(cwd, "build", "CMakeCache.txt"));
|
|
35558
35601
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
35559
35602
|
}
|
|
35560
35603
|
function detectSwiftTest(cwd) {
|
|
35561
|
-
return
|
|
35604
|
+
return fs16.existsSync(path27.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
35562
35605
|
}
|
|
35563
35606
|
function detectDartTest(cwd) {
|
|
35564
|
-
return
|
|
35607
|
+
return fs16.existsSync(path27.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
35565
35608
|
}
|
|
35566
35609
|
function detectRSpec(cwd) {
|
|
35567
|
-
const hasRSpecFile =
|
|
35568
|
-
const hasGemfile =
|
|
35569
|
-
const hasSpecDir =
|
|
35610
|
+
const hasRSpecFile = fs16.existsSync(path27.join(cwd, ".rspec"));
|
|
35611
|
+
const hasGemfile = fs16.existsSync(path27.join(cwd, "Gemfile"));
|
|
35612
|
+
const hasSpecDir = fs16.existsSync(path27.join(cwd, "spec"));
|
|
35570
35613
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
35571
35614
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
35572
35615
|
}
|
|
35573
35616
|
function detectMinitest(cwd) {
|
|
35574
|
-
return
|
|
35617
|
+
return fs16.existsSync(path27.join(cwd, "test")) && (fs16.existsSync(path27.join(cwd, "Gemfile")) || fs16.existsSync(path27.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
35575
35618
|
}
|
|
35576
35619
|
async function detectTestFramework(cwd) {
|
|
35577
35620
|
const baseDir = cwd;
|
|
35578
35621
|
try {
|
|
35579
|
-
const packageJsonPath =
|
|
35580
|
-
if (
|
|
35581
|
-
const content =
|
|
35622
|
+
const packageJsonPath = path27.join(baseDir, "package.json");
|
|
35623
|
+
if (fs16.existsSync(packageJsonPath)) {
|
|
35624
|
+
const content = fs16.readFileSync(packageJsonPath, "utf-8");
|
|
35582
35625
|
const pkg = JSON.parse(content);
|
|
35583
35626
|
const _deps = pkg.dependencies || {};
|
|
35584
35627
|
const devDeps = pkg.devDependencies || {};
|
|
@@ -35597,38 +35640,38 @@ async function detectTestFramework(cwd) {
|
|
|
35597
35640
|
return "jest";
|
|
35598
35641
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
35599
35642
|
return "mocha";
|
|
35600
|
-
if (
|
|
35643
|
+
if (fs16.existsSync(path27.join(baseDir, "bun.lockb")) || fs16.existsSync(path27.join(baseDir, "bun.lock"))) {
|
|
35601
35644
|
if (scripts.test?.includes("bun"))
|
|
35602
35645
|
return "bun";
|
|
35603
35646
|
}
|
|
35604
35647
|
}
|
|
35605
35648
|
} catch {}
|
|
35606
35649
|
try {
|
|
35607
|
-
const pyprojectTomlPath =
|
|
35608
|
-
const setupCfgPath =
|
|
35609
|
-
const requirementsTxtPath =
|
|
35610
|
-
if (
|
|
35611
|
-
const content =
|
|
35650
|
+
const pyprojectTomlPath = path27.join(baseDir, "pyproject.toml");
|
|
35651
|
+
const setupCfgPath = path27.join(baseDir, "setup.cfg");
|
|
35652
|
+
const requirementsTxtPath = path27.join(baseDir, "requirements.txt");
|
|
35653
|
+
if (fs16.existsSync(pyprojectTomlPath)) {
|
|
35654
|
+
const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
|
|
35612
35655
|
if (content.includes("[tool.pytest"))
|
|
35613
35656
|
return "pytest";
|
|
35614
35657
|
if (content.includes("pytest"))
|
|
35615
35658
|
return "pytest";
|
|
35616
35659
|
}
|
|
35617
|
-
if (
|
|
35618
|
-
const content =
|
|
35660
|
+
if (fs16.existsSync(setupCfgPath)) {
|
|
35661
|
+
const content = fs16.readFileSync(setupCfgPath, "utf-8");
|
|
35619
35662
|
if (content.includes("[pytest]"))
|
|
35620
35663
|
return "pytest";
|
|
35621
35664
|
}
|
|
35622
|
-
if (
|
|
35623
|
-
const content =
|
|
35665
|
+
if (fs16.existsSync(requirementsTxtPath)) {
|
|
35666
|
+
const content = fs16.readFileSync(requirementsTxtPath, "utf-8");
|
|
35624
35667
|
if (content.includes("pytest"))
|
|
35625
35668
|
return "pytest";
|
|
35626
35669
|
}
|
|
35627
35670
|
} catch {}
|
|
35628
35671
|
try {
|
|
35629
|
-
const cargoTomlPath =
|
|
35630
|
-
if (
|
|
35631
|
-
const content =
|
|
35672
|
+
const cargoTomlPath = path27.join(baseDir, "Cargo.toml");
|
|
35673
|
+
if (fs16.existsSync(cargoTomlPath)) {
|
|
35674
|
+
const content = fs16.readFileSync(cargoTomlPath, "utf-8");
|
|
35632
35675
|
if (content.includes("[dev-dependencies]")) {
|
|
35633
35676
|
if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
|
|
35634
35677
|
return "cargo";
|
|
@@ -35637,10 +35680,10 @@ async function detectTestFramework(cwd) {
|
|
|
35637
35680
|
}
|
|
35638
35681
|
} catch {}
|
|
35639
35682
|
try {
|
|
35640
|
-
const pesterConfigPath =
|
|
35641
|
-
const pesterConfigJsonPath =
|
|
35642
|
-
const pesterPs1Path =
|
|
35643
|
-
if (
|
|
35683
|
+
const pesterConfigPath = path27.join(baseDir, "pester.config.ps1");
|
|
35684
|
+
const pesterConfigJsonPath = path27.join(baseDir, "pester.config.ps1.json");
|
|
35685
|
+
const pesterPs1Path = path27.join(baseDir, "tests.ps1");
|
|
35686
|
+
if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
|
|
35644
35687
|
return "pester";
|
|
35645
35688
|
}
|
|
35646
35689
|
} catch {}
|
|
@@ -35672,8 +35715,8 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
35672
35715
|
const testFiles = [];
|
|
35673
35716
|
for (const file3 of sourceFiles) {
|
|
35674
35717
|
const normalizedPath = file3.replace(/\\/g, "/");
|
|
35675
|
-
const basename4 =
|
|
35676
|
-
const dirname11 =
|
|
35718
|
+
const basename4 = path27.basename(file3);
|
|
35719
|
+
const dirname11 = path27.dirname(file3);
|
|
35677
35720
|
if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
|
|
35678
35721
|
if (!testFiles.includes(file3)) {
|
|
35679
35722
|
testFiles.push(file3);
|
|
@@ -35682,16 +35725,16 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
35682
35725
|
}
|
|
35683
35726
|
for (const _pattern of TEST_PATTERNS) {
|
|
35684
35727
|
const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
|
|
35685
|
-
const ext =
|
|
35728
|
+
const ext = path27.extname(basename4);
|
|
35686
35729
|
const possibleTestFiles = [
|
|
35687
|
-
|
|
35688
|
-
|
|
35689
|
-
|
|
35690
|
-
|
|
35691
|
-
|
|
35730
|
+
path27.join(dirname11, `${nameWithoutExt}.spec${ext}`),
|
|
35731
|
+
path27.join(dirname11, `${nameWithoutExt}.test${ext}`),
|
|
35732
|
+
path27.join(dirname11, "__tests__", `${nameWithoutExt}${ext}`),
|
|
35733
|
+
path27.join(dirname11, "tests", `${nameWithoutExt}${ext}`),
|
|
35734
|
+
path27.join(dirname11, "test", `${nameWithoutExt}${ext}`)
|
|
35692
35735
|
];
|
|
35693
35736
|
for (const testFile of possibleTestFiles) {
|
|
35694
|
-
if (
|
|
35737
|
+
if (fs16.existsSync(testFile) && !testFiles.includes(testFile)) {
|
|
35695
35738
|
testFiles.push(testFile);
|
|
35696
35739
|
}
|
|
35697
35740
|
}
|
|
@@ -35707,8 +35750,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
35707
35750
|
}
|
|
35708
35751
|
for (const testFile of candidateTestFiles) {
|
|
35709
35752
|
try {
|
|
35710
|
-
const content =
|
|
35711
|
-
const testDir =
|
|
35753
|
+
const content = fs16.readFileSync(testFile, "utf-8");
|
|
35754
|
+
const testDir = path27.dirname(testFile);
|
|
35712
35755
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
35713
35756
|
let match;
|
|
35714
35757
|
match = importRegex.exec(content);
|
|
@@ -35716,8 +35759,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
35716
35759
|
const importPath = match[1];
|
|
35717
35760
|
let resolvedImport;
|
|
35718
35761
|
if (importPath.startsWith(".")) {
|
|
35719
|
-
resolvedImport =
|
|
35720
|
-
const existingExt =
|
|
35762
|
+
resolvedImport = path27.resolve(testDir, importPath);
|
|
35763
|
+
const existingExt = path27.extname(resolvedImport);
|
|
35721
35764
|
if (!existingExt) {
|
|
35722
35765
|
for (const extToTry of [
|
|
35723
35766
|
".ts",
|
|
@@ -35728,7 +35771,7 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
35728
35771
|
".cjs"
|
|
35729
35772
|
]) {
|
|
35730
35773
|
const withExt = resolvedImport + extToTry;
|
|
35731
|
-
if (sourceFiles.includes(withExt) ||
|
|
35774
|
+
if (sourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
|
|
35732
35775
|
resolvedImport = withExt;
|
|
35733
35776
|
break;
|
|
35734
35777
|
}
|
|
@@ -35737,12 +35780,12 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
35737
35780
|
} else {
|
|
35738
35781
|
continue;
|
|
35739
35782
|
}
|
|
35740
|
-
const importBasename =
|
|
35741
|
-
const importDir =
|
|
35783
|
+
const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
|
|
35784
|
+
const importDir = path27.dirname(resolvedImport);
|
|
35742
35785
|
for (const sourceFile of sourceFiles) {
|
|
35743
|
-
const sourceDir =
|
|
35744
|
-
const sourceBasename =
|
|
35745
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
35786
|
+
const sourceDir = path27.dirname(sourceFile);
|
|
35787
|
+
const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
|
|
35788
|
+
const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test");
|
|
35746
35789
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
35747
35790
|
if (!testFiles.includes(testFile)) {
|
|
35748
35791
|
testFiles.push(testFile);
|
|
@@ -35757,8 +35800,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
35757
35800
|
while (match !== null) {
|
|
35758
35801
|
const importPath = match[1];
|
|
35759
35802
|
if (importPath.startsWith(".")) {
|
|
35760
|
-
let resolvedImport =
|
|
35761
|
-
const existingExt =
|
|
35803
|
+
let resolvedImport = path27.resolve(testDir, importPath);
|
|
35804
|
+
const existingExt = path27.extname(resolvedImport);
|
|
35762
35805
|
if (!existingExt) {
|
|
35763
35806
|
for (const extToTry of [
|
|
35764
35807
|
".ts",
|
|
@@ -35769,18 +35812,18 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
35769
35812
|
".cjs"
|
|
35770
35813
|
]) {
|
|
35771
35814
|
const withExt = resolvedImport + extToTry;
|
|
35772
|
-
if (sourceFiles.includes(withExt) ||
|
|
35815
|
+
if (sourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
|
|
35773
35816
|
resolvedImport = withExt;
|
|
35774
35817
|
break;
|
|
35775
35818
|
}
|
|
35776
35819
|
}
|
|
35777
35820
|
}
|
|
35778
|
-
const importDir =
|
|
35779
|
-
const importBasename =
|
|
35821
|
+
const importDir = path27.dirname(resolvedImport);
|
|
35822
|
+
const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
|
|
35780
35823
|
for (const sourceFile of sourceFiles) {
|
|
35781
|
-
const sourceDir =
|
|
35782
|
-
const sourceBasename =
|
|
35783
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
35824
|
+
const sourceDir = path27.dirname(sourceFile);
|
|
35825
|
+
const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
|
|
35826
|
+
const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test");
|
|
35784
35827
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
35785
35828
|
if (!testFiles.includes(testFile)) {
|
|
35786
35829
|
testFiles.push(testFile);
|
|
@@ -35865,8 +35908,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
35865
35908
|
return ["mvn", "test"];
|
|
35866
35909
|
case "gradle": {
|
|
35867
35910
|
const isWindows = process.platform === "win32";
|
|
35868
|
-
const hasGradlewBat =
|
|
35869
|
-
const hasGradlew =
|
|
35911
|
+
const hasGradlewBat = fs16.existsSync(path27.join(baseDir, "gradlew.bat"));
|
|
35912
|
+
const hasGradlew = fs16.existsSync(path27.join(baseDir, "gradlew"));
|
|
35870
35913
|
if (hasGradlewBat && isWindows)
|
|
35871
35914
|
return ["gradlew.bat", "test"];
|
|
35872
35915
|
if (hasGradlew)
|
|
@@ -35883,7 +35926,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
35883
35926
|
"cmake-build-release",
|
|
35884
35927
|
"out"
|
|
35885
35928
|
];
|
|
35886
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
35929
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path27.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
35887
35930
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
35888
35931
|
}
|
|
35889
35932
|
case "swift-test":
|
|
@@ -36115,6 +36158,43 @@ function parseTestOutput(framework, output) {
|
|
|
36115
36158
|
}
|
|
36116
36159
|
return { totals, coveragePercent };
|
|
36117
36160
|
}
|
|
36161
|
+
async function readBoundedStream(stream, maxBytes) {
|
|
36162
|
+
const reader = stream.getReader();
|
|
36163
|
+
const chunks = [];
|
|
36164
|
+
let totalBytes = 0;
|
|
36165
|
+
let truncated = false;
|
|
36166
|
+
try {
|
|
36167
|
+
while (true) {
|
|
36168
|
+
const { done, value } = await reader.read();
|
|
36169
|
+
if (done)
|
|
36170
|
+
break;
|
|
36171
|
+
if (totalBytes + value.length > maxBytes) {
|
|
36172
|
+
const remaining = maxBytes - totalBytes;
|
|
36173
|
+
if (remaining > 0) {
|
|
36174
|
+
chunks.push(value.slice(0, remaining));
|
|
36175
|
+
}
|
|
36176
|
+
totalBytes = maxBytes;
|
|
36177
|
+
truncated = true;
|
|
36178
|
+
reader.cancel().catch(() => {});
|
|
36179
|
+
break;
|
|
36180
|
+
}
|
|
36181
|
+
chunks.push(value);
|
|
36182
|
+
totalBytes += value.length;
|
|
36183
|
+
}
|
|
36184
|
+
} catch {} finally {
|
|
36185
|
+
try {
|
|
36186
|
+
reader.releaseLock();
|
|
36187
|
+
} catch {}
|
|
36188
|
+
}
|
|
36189
|
+
const decoder = new TextDecoder("utf-8", { fatal: false });
|
|
36190
|
+
const combined = new Uint8Array(totalBytes);
|
|
36191
|
+
let offset = 0;
|
|
36192
|
+
for (const chunk of chunks) {
|
|
36193
|
+
combined.set(chunk, offset);
|
|
36194
|
+
offset += chunk.length;
|
|
36195
|
+
}
|
|
36196
|
+
return { text: decoder.decode(combined), truncated };
|
|
36197
|
+
}
|
|
36118
36198
|
async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
36119
36199
|
const command = buildTestCommand(framework, scope, files, coverage, cwd);
|
|
36120
36200
|
if (!command) {
|
|
@@ -36143,34 +36223,24 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
36143
36223
|
stderr: "pipe",
|
|
36144
36224
|
cwd
|
|
36145
36225
|
});
|
|
36146
|
-
const
|
|
36147
|
-
const timeoutPromise = new Promise((resolve8) => setTimeout(() => {
|
|
36226
|
+
const timeoutPromise = new Promise((resolve9) => setTimeout(() => {
|
|
36148
36227
|
proc.kill();
|
|
36149
|
-
|
|
36228
|
+
resolve9(-1);
|
|
36150
36229
|
}, timeout_ms));
|
|
36151
|
-
const exitCode = await Promise.
|
|
36152
|
-
|
|
36153
|
-
|
|
36154
|
-
|
|
36155
|
-
new Response(proc.stderr).text()
|
|
36230
|
+
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
36231
|
+
Promise.race([proc.exited, timeoutPromise]),
|
|
36232
|
+
readBoundedStream(proc.stdout, MAX_OUTPUT_BYTES3),
|
|
36233
|
+
readBoundedStream(proc.stderr, MAX_OUTPUT_BYTES3)
|
|
36156
36234
|
]);
|
|
36157
|
-
|
|
36158
|
-
|
|
36235
|
+
const duration_ms = Date.now() - startTime;
|
|
36236
|
+
let output = stdoutResult.text;
|
|
36237
|
+
if (stderrResult.text) {
|
|
36159
36238
|
output += (output ? `
|
|
36160
|
-
` : "") +
|
|
36239
|
+
` : "") + stderrResult.text;
|
|
36161
36240
|
}
|
|
36162
|
-
|
|
36163
|
-
|
|
36164
|
-
|
|
36165
|
-
while (truncIndex > 0) {
|
|
36166
|
-
const truncated = output.slice(0, truncIndex);
|
|
36167
|
-
if (Buffer.byteLength(truncated, "utf-8") <= MAX_OUTPUT_BYTES3) {
|
|
36168
|
-
break;
|
|
36169
|
-
}
|
|
36170
|
-
truncIndex--;
|
|
36171
|
-
}
|
|
36172
|
-
output = `${output.slice(0, truncIndex)}
|
|
36173
|
-
... (output truncated)`;
|
|
36241
|
+
if (stdoutResult.truncated || stderrResult.truncated) {
|
|
36242
|
+
output += `
|
|
36243
|
+
... (output truncated at stream read limit)`;
|
|
36174
36244
|
}
|
|
36175
36245
|
const { totals, coveragePercent } = parseTestOutput(framework, output);
|
|
36176
36246
|
const isTimeout = exitCode === -1;
|
|
@@ -36230,6 +36300,7 @@ var init_test_runner = __esm(() => {
|
|
|
36230
36300
|
init_dist();
|
|
36231
36301
|
init_discovery();
|
|
36232
36302
|
init_create_tool();
|
|
36303
|
+
init_resolve_working_directory();
|
|
36233
36304
|
POWERSHELL_METACHARACTERS = /[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;
|
|
36234
36305
|
TEST_PATTERNS = [
|
|
36235
36306
|
{ test: ".spec.", source: "." },
|
|
@@ -36309,10 +36380,26 @@ var init_test_runner = __esm(() => {
|
|
|
36309
36380
|
files: tool.schema.array(tool.schema.string()).optional().describe("Specific files to test (used with convention or graph scope)"),
|
|
36310
36381
|
coverage: tool.schema.boolean().optional().describe("Enable coverage reporting if supported"),
|
|
36311
36382
|
timeout_ms: tool.schema.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
|
|
36312
|
-
allow_full_suite: tool.schema.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.')
|
|
36383
|
+
allow_full_suite: tool.schema.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
|
|
36384
|
+
working_directory: tool.schema.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
36313
36385
|
},
|
|
36314
36386
|
async execute(args2, directory) {
|
|
36315
|
-
|
|
36387
|
+
let workingDirInput;
|
|
36388
|
+
if (args2 && typeof args2 === "object") {
|
|
36389
|
+
const obj = args2;
|
|
36390
|
+
workingDirInput = typeof obj.working_directory === "string" ? obj.working_directory : undefined;
|
|
36391
|
+
}
|
|
36392
|
+
const dirResult = resolveWorkingDirectory(workingDirInput, directory);
|
|
36393
|
+
if (!dirResult.success) {
|
|
36394
|
+
const errorResult = {
|
|
36395
|
+
success: false,
|
|
36396
|
+
framework: "none",
|
|
36397
|
+
scope: "all",
|
|
36398
|
+
error: dirResult.message
|
|
36399
|
+
};
|
|
36400
|
+
return JSON.stringify(errorResult, null, 2);
|
|
36401
|
+
}
|
|
36402
|
+
const workingDir = dirResult.directory;
|
|
36316
36403
|
if (workingDir.length > 4096) {
|
|
36317
36404
|
const errorResult = {
|
|
36318
36405
|
success: false,
|
|
@@ -36366,8 +36453,8 @@ var init_test_runner = __esm(() => {
|
|
|
36366
36453
|
success: false,
|
|
36367
36454
|
framework: "none",
|
|
36368
36455
|
scope: "all",
|
|
36369
|
-
error: '
|
|
36370
|
-
message: '
|
|
36456
|
+
error: 'scope "all" is not allowed without explicit files. Use scope "convention" or "graph" with a files array to run targeted tests.',
|
|
36457
|
+
message: 'Running the full test suite without file targeting is blocked. Provide scope "convention" or "graph" with specific source files in the files array. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }'
|
|
36371
36458
|
};
|
|
36372
36459
|
return JSON.stringify(errorResult, null, 2);
|
|
36373
36460
|
}
|
|
@@ -36407,7 +36494,7 @@ var init_test_runner = __esm(() => {
|
|
|
36407
36494
|
let effectiveScope = scope;
|
|
36408
36495
|
if (scope === "all") {} else if (scope === "convention") {
|
|
36409
36496
|
const sourceFiles = args2.files.filter((f) => {
|
|
36410
|
-
const ext =
|
|
36497
|
+
const ext = path27.extname(f).toLowerCase();
|
|
36411
36498
|
return SOURCE_EXTENSIONS.has(ext);
|
|
36412
36499
|
});
|
|
36413
36500
|
if (sourceFiles.length === 0) {
|
|
@@ -36423,7 +36510,7 @@ var init_test_runner = __esm(() => {
|
|
|
36423
36510
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
36424
36511
|
} else if (scope === "graph") {
|
|
36425
36512
|
const sourceFiles = args2.files.filter((f) => {
|
|
36426
|
-
const ext =
|
|
36513
|
+
const ext = path27.extname(f).toLowerCase();
|
|
36427
36514
|
return SOURCE_EXTENSIONS.has(ext);
|
|
36428
36515
|
});
|
|
36429
36516
|
if (sourceFiles.length === 0) {
|
|
@@ -36476,8 +36563,8 @@ var init_test_runner = __esm(() => {
|
|
|
36476
36563
|
});
|
|
36477
36564
|
|
|
36478
36565
|
// src/services/preflight-service.ts
|
|
36479
|
-
import * as
|
|
36480
|
-
import * as
|
|
36566
|
+
import * as fs17 from "fs";
|
|
36567
|
+
import * as path28 from "path";
|
|
36481
36568
|
function validateDirectoryPath(dir) {
|
|
36482
36569
|
if (!dir || typeof dir !== "string") {
|
|
36483
36570
|
throw new Error("Directory path is required");
|
|
@@ -36485,8 +36572,8 @@ function validateDirectoryPath(dir) {
|
|
|
36485
36572
|
if (dir.includes("..")) {
|
|
36486
36573
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
36487
36574
|
}
|
|
36488
|
-
const normalized =
|
|
36489
|
-
const absolutePath =
|
|
36575
|
+
const normalized = path28.normalize(dir);
|
|
36576
|
+
const absolutePath = path28.isAbsolute(normalized) ? normalized : path28.resolve(normalized);
|
|
36490
36577
|
return absolutePath;
|
|
36491
36578
|
}
|
|
36492
36579
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -36509,9 +36596,9 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
36509
36596
|
}
|
|
36510
36597
|
function getPackageVersion(dir) {
|
|
36511
36598
|
try {
|
|
36512
|
-
const packagePath =
|
|
36513
|
-
if (
|
|
36514
|
-
const content =
|
|
36599
|
+
const packagePath = path28.join(dir, "package.json");
|
|
36600
|
+
if (fs17.existsSync(packagePath)) {
|
|
36601
|
+
const content = fs17.readFileSync(packagePath, "utf-8");
|
|
36515
36602
|
const pkg = JSON.parse(content);
|
|
36516
36603
|
return pkg.version ?? null;
|
|
36517
36604
|
}
|
|
@@ -36520,9 +36607,9 @@ function getPackageVersion(dir) {
|
|
|
36520
36607
|
}
|
|
36521
36608
|
function getChangelogVersion(dir) {
|
|
36522
36609
|
try {
|
|
36523
|
-
const changelogPath =
|
|
36524
|
-
if (
|
|
36525
|
-
const content =
|
|
36610
|
+
const changelogPath = path28.join(dir, "CHANGELOG.md");
|
|
36611
|
+
if (fs17.existsSync(changelogPath)) {
|
|
36612
|
+
const content = fs17.readFileSync(changelogPath, "utf-8");
|
|
36526
36613
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
36527
36614
|
if (match) {
|
|
36528
36615
|
return match[1];
|
|
@@ -36534,10 +36621,10 @@ function getChangelogVersion(dir) {
|
|
|
36534
36621
|
function getVersionFileVersion(dir) {
|
|
36535
36622
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
36536
36623
|
for (const file3 of possibleFiles) {
|
|
36537
|
-
const filePath =
|
|
36538
|
-
if (
|
|
36624
|
+
const filePath = path28.join(dir, file3);
|
|
36625
|
+
if (fs17.existsSync(filePath)) {
|
|
36539
36626
|
try {
|
|
36540
|
-
const content =
|
|
36627
|
+
const content = fs17.readFileSync(filePath, "utf-8").trim();
|
|
36541
36628
|
const match = content.match(/(\d+\.\d+\.\d+)/);
|
|
36542
36629
|
if (match) {
|
|
36543
36630
|
return match[1];
|
|
@@ -37062,7 +37149,7 @@ __export(exports_gate_evidence, {
|
|
|
37062
37149
|
DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
|
|
37063
37150
|
});
|
|
37064
37151
|
import { mkdirSync as mkdirSync10, readFileSync as readFileSync14, renameSync as renameSync9, unlinkSync as unlinkSync5 } from "fs";
|
|
37065
|
-
import * as
|
|
37152
|
+
import * as path34 from "path";
|
|
37066
37153
|
function isValidTaskId2(taskId) {
|
|
37067
37154
|
if (!taskId)
|
|
37068
37155
|
return false;
|
|
@@ -37109,10 +37196,10 @@ function expandRequiredGates(existingGates, newAgentType) {
|
|
|
37109
37196
|
return combined.sort();
|
|
37110
37197
|
}
|
|
37111
37198
|
function getEvidenceDir(directory) {
|
|
37112
|
-
return
|
|
37199
|
+
return path34.join(directory, ".swarm", "evidence");
|
|
37113
37200
|
}
|
|
37114
37201
|
function getEvidencePath(directory, taskId) {
|
|
37115
|
-
return
|
|
37202
|
+
return path34.join(getEvidenceDir(directory), `${taskId}.json`);
|
|
37116
37203
|
}
|
|
37117
37204
|
function readExisting(evidencePath) {
|
|
37118
37205
|
try {
|
|
@@ -37282,15 +37369,15 @@ __export(exports_doc_scan, {
|
|
|
37282
37369
|
doc_extract: () => doc_extract
|
|
37283
37370
|
});
|
|
37284
37371
|
import * as crypto4 from "crypto";
|
|
37285
|
-
import * as
|
|
37372
|
+
import * as fs27 from "fs";
|
|
37286
37373
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
37287
|
-
import * as
|
|
37374
|
+
import * as path39 from "path";
|
|
37288
37375
|
function normalizeSeparators(filePath) {
|
|
37289
37376
|
return filePath.replace(/\\/g, "/");
|
|
37290
37377
|
}
|
|
37291
37378
|
function matchesDocPattern(filePath, patterns) {
|
|
37292
37379
|
const normalizedPath = normalizeSeparators(filePath);
|
|
37293
|
-
const basename5 =
|
|
37380
|
+
const basename5 = path39.basename(filePath);
|
|
37294
37381
|
for (const pattern of patterns) {
|
|
37295
37382
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
37296
37383
|
if (basename5 === pattern) {
|
|
@@ -37346,7 +37433,7 @@ function stripMarkdown(text) {
|
|
|
37346
37433
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
37347
37434
|
}
|
|
37348
37435
|
async function scanDocIndex(directory) {
|
|
37349
|
-
const manifestPath =
|
|
37436
|
+
const manifestPath = path39.join(directory, ".swarm", "doc-manifest.json");
|
|
37350
37437
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
37351
37438
|
const extraPatterns = [
|
|
37352
37439
|
"ARCHITECTURE.md",
|
|
@@ -37363,8 +37450,8 @@ async function scanDocIndex(directory) {
|
|
|
37363
37450
|
let cacheValid = true;
|
|
37364
37451
|
for (const file3 of existingManifest.files) {
|
|
37365
37452
|
try {
|
|
37366
|
-
const fullPath =
|
|
37367
|
-
const stat2 =
|
|
37453
|
+
const fullPath = path39.join(directory, file3.path);
|
|
37454
|
+
const stat2 = fs27.statSync(fullPath);
|
|
37368
37455
|
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
37369
37456
|
cacheValid = false;
|
|
37370
37457
|
break;
|
|
@@ -37382,7 +37469,7 @@ async function scanDocIndex(directory) {
|
|
|
37382
37469
|
const discoveredFiles = [];
|
|
37383
37470
|
let rawEntries;
|
|
37384
37471
|
try {
|
|
37385
|
-
rawEntries =
|
|
37472
|
+
rawEntries = fs27.readdirSync(directory, { recursive: true });
|
|
37386
37473
|
} catch {
|
|
37387
37474
|
const manifest2 = {
|
|
37388
37475
|
schema_version: 1,
|
|
@@ -37393,10 +37480,10 @@ async function scanDocIndex(directory) {
|
|
|
37393
37480
|
}
|
|
37394
37481
|
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
37395
37482
|
for (const entry of entries) {
|
|
37396
|
-
const fullPath =
|
|
37483
|
+
const fullPath = path39.join(directory, entry);
|
|
37397
37484
|
let stat2;
|
|
37398
37485
|
try {
|
|
37399
|
-
stat2 =
|
|
37486
|
+
stat2 = fs27.statSync(fullPath);
|
|
37400
37487
|
} catch {
|
|
37401
37488
|
continue;
|
|
37402
37489
|
}
|
|
@@ -37425,11 +37512,11 @@ async function scanDocIndex(directory) {
|
|
|
37425
37512
|
}
|
|
37426
37513
|
let content;
|
|
37427
37514
|
try {
|
|
37428
|
-
content =
|
|
37515
|
+
content = fs27.readFileSync(fullPath, "utf-8");
|
|
37429
37516
|
} catch {
|
|
37430
37517
|
continue;
|
|
37431
37518
|
}
|
|
37432
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
37519
|
+
const { title, summary } = extractTitleAndSummary(content, path39.basename(entry));
|
|
37433
37520
|
const lineCount = content.split(`
|
|
37434
37521
|
`).length;
|
|
37435
37522
|
discoveredFiles.push({
|
|
@@ -37455,7 +37542,7 @@ async function scanDocIndex(directory) {
|
|
|
37455
37542
|
files: discoveredFiles
|
|
37456
37543
|
};
|
|
37457
37544
|
try {
|
|
37458
|
-
await mkdir6(
|
|
37545
|
+
await mkdir6(path39.dirname(manifestPath), { recursive: true });
|
|
37459
37546
|
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
37460
37547
|
} catch {}
|
|
37461
37548
|
return { manifest, cached: false };
|
|
@@ -37494,7 +37581,7 @@ function extractConstraintsFromContent(content) {
|
|
|
37494
37581
|
return constraints;
|
|
37495
37582
|
}
|
|
37496
37583
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
37497
|
-
const manifestPath =
|
|
37584
|
+
const manifestPath = path39.join(directory, ".swarm", "doc-manifest.json");
|
|
37498
37585
|
let manifest;
|
|
37499
37586
|
try {
|
|
37500
37587
|
const content = await readFile6(manifestPath, "utf-8");
|
|
@@ -37520,7 +37607,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
37520
37607
|
}
|
|
37521
37608
|
let fullContent;
|
|
37522
37609
|
try {
|
|
37523
|
-
fullContent = await readFile6(
|
|
37610
|
+
fullContent = await readFile6(path39.join(directory, docFile.path), "utf-8");
|
|
37524
37611
|
} catch {
|
|
37525
37612
|
skippedCount++;
|
|
37526
37613
|
continue;
|
|
@@ -37543,7 +37630,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
37543
37630
|
tier: "swarm",
|
|
37544
37631
|
lesson: constraint,
|
|
37545
37632
|
category: "architecture",
|
|
37546
|
-
tags: ["doc-scan",
|
|
37633
|
+
tags: ["doc-scan", path39.basename(docFile.path)],
|
|
37547
37634
|
scope: "global",
|
|
37548
37635
|
confidence: 0.5,
|
|
37549
37636
|
status: "candidate",
|
|
@@ -37616,9 +37703,9 @@ var init_doc_scan = __esm(() => {
|
|
|
37616
37703
|
}
|
|
37617
37704
|
} catch {}
|
|
37618
37705
|
if (force) {
|
|
37619
|
-
const manifestPath =
|
|
37706
|
+
const manifestPath = path39.join(directory, ".swarm", "doc-manifest.json");
|
|
37620
37707
|
try {
|
|
37621
|
-
|
|
37708
|
+
fs27.unlinkSync(manifestPath);
|
|
37622
37709
|
} catch {}
|
|
37623
37710
|
}
|
|
37624
37711
|
const { manifest, cached: cached3 } = await scanDocIndex(directory);
|
|
@@ -37670,11 +37757,11 @@ __export(exports_curator_drift, {
|
|
|
37670
37757
|
readPriorDriftReports: () => readPriorDriftReports,
|
|
37671
37758
|
buildDriftInjectionText: () => buildDriftInjectionText
|
|
37672
37759
|
});
|
|
37673
|
-
import * as
|
|
37674
|
-
import * as
|
|
37760
|
+
import * as fs30 from "fs";
|
|
37761
|
+
import * as path42 from "path";
|
|
37675
37762
|
async function readPriorDriftReports(directory) {
|
|
37676
|
-
const swarmDir =
|
|
37677
|
-
const entries = await
|
|
37763
|
+
const swarmDir = path42.join(directory, ".swarm");
|
|
37764
|
+
const entries = await fs30.promises.readdir(swarmDir).catch(() => null);
|
|
37678
37765
|
if (entries === null)
|
|
37679
37766
|
return [];
|
|
37680
37767
|
const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
|
|
@@ -37700,10 +37787,10 @@ async function readPriorDriftReports(directory) {
|
|
|
37700
37787
|
async function writeDriftReport(directory, report) {
|
|
37701
37788
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
37702
37789
|
const filePath = validateSwarmPath(directory, filename);
|
|
37703
|
-
const swarmDir =
|
|
37704
|
-
await
|
|
37790
|
+
const swarmDir = path42.dirname(filePath);
|
|
37791
|
+
await fs30.promises.mkdir(swarmDir, { recursive: true });
|
|
37705
37792
|
try {
|
|
37706
|
-
await
|
|
37793
|
+
await fs30.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
37707
37794
|
} catch (err2) {
|
|
37708
37795
|
throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
|
|
37709
37796
|
}
|
|
@@ -39270,8 +39357,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
39270
39357
|
var moduleRtn;
|
|
39271
39358
|
var Module = moduleArg;
|
|
39272
39359
|
var readyPromiseResolve, readyPromiseReject;
|
|
39273
|
-
var readyPromise = new Promise((
|
|
39274
|
-
readyPromiseResolve =
|
|
39360
|
+
var readyPromise = new Promise((resolve17, reject) => {
|
|
39361
|
+
readyPromiseResolve = resolve17;
|
|
39275
39362
|
readyPromiseReject = reject;
|
|
39276
39363
|
});
|
|
39277
39364
|
var ENVIRONMENT_IS_WEB = typeof window == "object";
|
|
@@ -39293,11 +39380,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
39293
39380
|
throw toThrow;
|
|
39294
39381
|
}, "quit_");
|
|
39295
39382
|
var scriptDirectory = "";
|
|
39296
|
-
function locateFile(
|
|
39383
|
+
function locateFile(path50) {
|
|
39297
39384
|
if (Module["locateFile"]) {
|
|
39298
|
-
return Module["locateFile"](
|
|
39385
|
+
return Module["locateFile"](path50, scriptDirectory);
|
|
39299
39386
|
}
|
|
39300
|
-
return scriptDirectory +
|
|
39387
|
+
return scriptDirectory + path50;
|
|
39301
39388
|
}
|
|
39302
39389
|
__name(locateFile, "locateFile");
|
|
39303
39390
|
var readAsync, readBinary;
|
|
@@ -39351,13 +39438,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
39351
39438
|
}
|
|
39352
39439
|
readAsync = /* @__PURE__ */ __name(async (url3) => {
|
|
39353
39440
|
if (isFileURI(url3)) {
|
|
39354
|
-
return new Promise((
|
|
39441
|
+
return new Promise((resolve17, reject) => {
|
|
39355
39442
|
var xhr = new XMLHttpRequest;
|
|
39356
39443
|
xhr.open("GET", url3, true);
|
|
39357
39444
|
xhr.responseType = "arraybuffer";
|
|
39358
39445
|
xhr.onload = () => {
|
|
39359
39446
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
39360
|
-
|
|
39447
|
+
resolve17(xhr.response);
|
|
39361
39448
|
return;
|
|
39362
39449
|
}
|
|
39363
39450
|
reject(xhr.status);
|
|
@@ -39577,10 +39664,10 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
39577
39664
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
39578
39665
|
var info2 = getWasmImports();
|
|
39579
39666
|
if (Module["instantiateWasm"]) {
|
|
39580
|
-
return new Promise((
|
|
39667
|
+
return new Promise((resolve17, reject) => {
|
|
39581
39668
|
Module["instantiateWasm"](info2, (mod, inst) => {
|
|
39582
39669
|
receiveInstance(mod, inst);
|
|
39583
|
-
|
|
39670
|
+
resolve17(mod.exports);
|
|
39584
39671
|
});
|
|
39585
39672
|
});
|
|
39586
39673
|
}
|
|
@@ -41037,13 +41124,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
41037
41124
|
});
|
|
41038
41125
|
|
|
41039
41126
|
// src/lang/runtime.ts
|
|
41040
|
-
import * as
|
|
41127
|
+
import * as path50 from "path";
|
|
41041
41128
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
41042
41129
|
async function initTreeSitter() {
|
|
41043
41130
|
if (treeSitterInitialized) {
|
|
41044
41131
|
return;
|
|
41045
41132
|
}
|
|
41046
|
-
const thisDir =
|
|
41133
|
+
const thisDir = path50.dirname(fileURLToPath2(import.meta.url));
|
|
41047
41134
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41048
41135
|
if (isSource) {
|
|
41049
41136
|
await Parser.init();
|
|
@@ -41051,7 +41138,7 @@ async function initTreeSitter() {
|
|
|
41051
41138
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
41052
41139
|
await Parser.init({
|
|
41053
41140
|
locateFile(scriptName) {
|
|
41054
|
-
return
|
|
41141
|
+
return path50.join(grammarsDir, scriptName);
|
|
41055
41142
|
}
|
|
41056
41143
|
});
|
|
41057
41144
|
}
|
|
@@ -41072,9 +41159,9 @@ function getWasmFileName(languageId) {
|
|
|
41072
41159
|
return `tree-sitter-${sanitized}.wasm`;
|
|
41073
41160
|
}
|
|
41074
41161
|
function getGrammarsDirAbsolute() {
|
|
41075
|
-
const thisDir =
|
|
41162
|
+
const thisDir = path50.dirname(fileURLToPath2(import.meta.url));
|
|
41076
41163
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41077
|
-
return isSource ?
|
|
41164
|
+
return isSource ? path50.join(thisDir, "grammars") : path50.join(thisDir, "lang", "grammars");
|
|
41078
41165
|
}
|
|
41079
41166
|
async function loadGrammar(languageId) {
|
|
41080
41167
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -41090,7 +41177,7 @@ async function loadGrammar(languageId) {
|
|
|
41090
41177
|
await initTreeSitter();
|
|
41091
41178
|
const parser = new Parser;
|
|
41092
41179
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
41093
|
-
const wasmPath =
|
|
41180
|
+
const wasmPath = path50.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
41094
41181
|
const { existsSync: existsSync29 } = await import("fs");
|
|
41095
41182
|
if (!existsSync29(wasmPath)) {
|
|
41096
41183
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
@@ -41137,7 +41224,7 @@ var init_runtime = __esm(() => {
|
|
|
41137
41224
|
});
|
|
41138
41225
|
|
|
41139
41226
|
// src/index.ts
|
|
41140
|
-
import * as
|
|
41227
|
+
import * as path67 from "path";
|
|
41141
41228
|
|
|
41142
41229
|
// src/agents/index.ts
|
|
41143
41230
|
init_config();
|
|
@@ -50040,7 +50127,7 @@ async function handlePromoteCommand(directory, args2) {
|
|
|
50040
50127
|
}
|
|
50041
50128
|
|
|
50042
50129
|
// src/commands/reset.ts
|
|
50043
|
-
import * as
|
|
50130
|
+
import * as fs18 from "fs";
|
|
50044
50131
|
init_utils2();
|
|
50045
50132
|
async function handleResetCommand(directory, args2) {
|
|
50046
50133
|
const hasConfirm = args2.includes("--confirm");
|
|
@@ -50061,8 +50148,8 @@ async function handleResetCommand(directory, args2) {
|
|
|
50061
50148
|
for (const filename of filesToReset) {
|
|
50062
50149
|
try {
|
|
50063
50150
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
50064
|
-
if (
|
|
50065
|
-
|
|
50151
|
+
if (fs18.existsSync(resolvedPath)) {
|
|
50152
|
+
fs18.unlinkSync(resolvedPath);
|
|
50066
50153
|
results.push(`- \u2705 Deleted ${filename}`);
|
|
50067
50154
|
} else {
|
|
50068
50155
|
results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
|
|
@@ -50079,8 +50166,8 @@ async function handleResetCommand(directory, args2) {
|
|
|
50079
50166
|
}
|
|
50080
50167
|
try {
|
|
50081
50168
|
const summariesPath = validateSwarmPath(directory, "summaries");
|
|
50082
|
-
if (
|
|
50083
|
-
|
|
50169
|
+
if (fs18.existsSync(summariesPath)) {
|
|
50170
|
+
fs18.rmSync(summariesPath, { recursive: true, force: true });
|
|
50084
50171
|
results.push("- \u2705 Deleted summaries/ directory");
|
|
50085
50172
|
} else {
|
|
50086
50173
|
results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
|
|
@@ -50100,14 +50187,14 @@ async function handleResetCommand(directory, args2) {
|
|
|
50100
50187
|
|
|
50101
50188
|
// src/commands/reset-session.ts
|
|
50102
50189
|
init_utils2();
|
|
50103
|
-
import * as
|
|
50104
|
-
import * as
|
|
50190
|
+
import * as fs19 from "fs";
|
|
50191
|
+
import * as path29 from "path";
|
|
50105
50192
|
async function handleResetSessionCommand(directory, _args) {
|
|
50106
50193
|
const results = [];
|
|
50107
50194
|
try {
|
|
50108
50195
|
const statePath = validateSwarmPath(directory, "session/state.json");
|
|
50109
|
-
if (
|
|
50110
|
-
|
|
50196
|
+
if (fs19.existsSync(statePath)) {
|
|
50197
|
+
fs19.unlinkSync(statePath);
|
|
50111
50198
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
50112
50199
|
} else {
|
|
50113
50200
|
results.push("\u23ED\uFE0F state.json not found (already clean)");
|
|
@@ -50116,15 +50203,15 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
50116
50203
|
results.push("\u274C Failed to delete state.json");
|
|
50117
50204
|
}
|
|
50118
50205
|
try {
|
|
50119
|
-
const sessionDir =
|
|
50120
|
-
if (
|
|
50121
|
-
const files =
|
|
50206
|
+
const sessionDir = path29.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
50207
|
+
if (fs19.existsSync(sessionDir)) {
|
|
50208
|
+
const files = fs19.readdirSync(sessionDir);
|
|
50122
50209
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
50123
50210
|
let deletedCount = 0;
|
|
50124
50211
|
for (const file3 of otherFiles) {
|
|
50125
|
-
const filePath =
|
|
50126
|
-
if (
|
|
50127
|
-
|
|
50212
|
+
const filePath = path29.join(sessionDir, file3);
|
|
50213
|
+
if (fs19.lstatSync(filePath).isFile()) {
|
|
50214
|
+
fs19.unlinkSync(filePath);
|
|
50128
50215
|
deletedCount++;
|
|
50129
50216
|
}
|
|
50130
50217
|
}
|
|
@@ -50153,7 +50240,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
50153
50240
|
init_utils2();
|
|
50154
50241
|
init_utils();
|
|
50155
50242
|
import { mkdirSync as mkdirSync9, readdirSync as readdirSync8, renameSync as renameSync7, rmSync as rmSync3, statSync as statSync8 } from "fs";
|
|
50156
|
-
import * as
|
|
50243
|
+
import * as path30 from "path";
|
|
50157
50244
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
50158
50245
|
function sanitizeSummaryId(id) {
|
|
50159
50246
|
if (!id || id.length === 0) {
|
|
@@ -50188,9 +50275,9 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
50188
50275
|
if (serializedSize > maxStoredBytes) {
|
|
50189
50276
|
throw new Error(`Summary entry size (${serializedSize} bytes) exceeds maximum (${maxStoredBytes} bytes)`);
|
|
50190
50277
|
}
|
|
50191
|
-
const relativePath =
|
|
50278
|
+
const relativePath = path30.join("summaries", `${sanitizedId}.json`);
|
|
50192
50279
|
const summaryPath = validateSwarmPath(directory, relativePath);
|
|
50193
|
-
const summaryDir =
|
|
50280
|
+
const summaryDir = path30.dirname(summaryPath);
|
|
50194
50281
|
const entry = {
|
|
50195
50282
|
id: sanitizedId,
|
|
50196
50283
|
summaryText,
|
|
@@ -50200,7 +50287,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
50200
50287
|
};
|
|
50201
50288
|
const entryJson = JSON.stringify(entry);
|
|
50202
50289
|
mkdirSync9(summaryDir, { recursive: true });
|
|
50203
|
-
const tempPath =
|
|
50290
|
+
const tempPath = path30.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
|
|
50204
50291
|
try {
|
|
50205
50292
|
await Bun.write(tempPath, entryJson);
|
|
50206
50293
|
renameSync7(tempPath, summaryPath);
|
|
@@ -50213,7 +50300,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
50213
50300
|
}
|
|
50214
50301
|
async function loadFullOutput(directory, id) {
|
|
50215
50302
|
const sanitizedId = sanitizeSummaryId(id);
|
|
50216
|
-
const relativePath =
|
|
50303
|
+
const relativePath = path30.join("summaries", `${sanitizedId}.json`);
|
|
50217
50304
|
validateSwarmPath(directory, relativePath);
|
|
50218
50305
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
50219
50306
|
if (content === null) {
|
|
@@ -50266,18 +50353,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
|
50266
50353
|
|
|
50267
50354
|
// src/commands/rollback.ts
|
|
50268
50355
|
init_utils2();
|
|
50269
|
-
import * as
|
|
50270
|
-
import * as
|
|
50356
|
+
import * as fs20 from "fs";
|
|
50357
|
+
import * as path31 from "path";
|
|
50271
50358
|
async function handleRollbackCommand(directory, args2) {
|
|
50272
50359
|
const phaseArg = args2[0];
|
|
50273
50360
|
if (!phaseArg) {
|
|
50274
50361
|
const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
50275
|
-
if (!
|
|
50362
|
+
if (!fs20.existsSync(manifestPath2)) {
|
|
50276
50363
|
return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
|
|
50277
50364
|
}
|
|
50278
50365
|
let manifest2;
|
|
50279
50366
|
try {
|
|
50280
|
-
manifest2 = JSON.parse(
|
|
50367
|
+
manifest2 = JSON.parse(fs20.readFileSync(manifestPath2, "utf-8"));
|
|
50281
50368
|
} catch {
|
|
50282
50369
|
return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
|
|
50283
50370
|
}
|
|
@@ -50299,12 +50386,12 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
50299
50386
|
return "Error: Phase number must be a positive integer.";
|
|
50300
50387
|
}
|
|
50301
50388
|
const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
50302
|
-
if (!
|
|
50389
|
+
if (!fs20.existsSync(manifestPath)) {
|
|
50303
50390
|
return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
|
|
50304
50391
|
}
|
|
50305
50392
|
let manifest;
|
|
50306
50393
|
try {
|
|
50307
|
-
manifest = JSON.parse(
|
|
50394
|
+
manifest = JSON.parse(fs20.readFileSync(manifestPath, "utf-8"));
|
|
50308
50395
|
} catch {
|
|
50309
50396
|
return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
|
|
50310
50397
|
}
|
|
@@ -50314,10 +50401,10 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
50314
50401
|
return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
|
|
50315
50402
|
}
|
|
50316
50403
|
const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
|
|
50317
|
-
if (!
|
|
50404
|
+
if (!fs20.existsSync(checkpointDir)) {
|
|
50318
50405
|
return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
|
|
50319
50406
|
}
|
|
50320
|
-
const checkpointFiles =
|
|
50407
|
+
const checkpointFiles = fs20.readdirSync(checkpointDir);
|
|
50321
50408
|
if (checkpointFiles.length === 0) {
|
|
50322
50409
|
return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
|
|
50323
50410
|
}
|
|
@@ -50325,10 +50412,10 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
50325
50412
|
const successes = [];
|
|
50326
50413
|
const failures = [];
|
|
50327
50414
|
for (const file3 of checkpointFiles) {
|
|
50328
|
-
const src =
|
|
50329
|
-
const dest =
|
|
50415
|
+
const src = path31.join(checkpointDir, file3);
|
|
50416
|
+
const dest = path31.join(swarmDir, file3);
|
|
50330
50417
|
try {
|
|
50331
|
-
|
|
50418
|
+
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
50332
50419
|
successes.push(file3);
|
|
50333
50420
|
} catch (error93) {
|
|
50334
50421
|
failures.push({ file: file3, error: error93.message });
|
|
@@ -50345,7 +50432,7 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
50345
50432
|
timestamp: new Date().toISOString()
|
|
50346
50433
|
};
|
|
50347
50434
|
try {
|
|
50348
|
-
|
|
50435
|
+
fs20.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
50349
50436
|
`);
|
|
50350
50437
|
} catch (error93) {
|
|
50351
50438
|
console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
|
|
@@ -50389,11 +50476,11 @@ async function handleSimulateCommand(directory, args2) {
|
|
|
50389
50476
|
];
|
|
50390
50477
|
const report = reportLines.filter(Boolean).join(`
|
|
50391
50478
|
`);
|
|
50392
|
-
const
|
|
50393
|
-
const
|
|
50394
|
-
const reportPath =
|
|
50395
|
-
await
|
|
50396
|
-
await
|
|
50479
|
+
const fs21 = await import("fs/promises");
|
|
50480
|
+
const path32 = await import("path");
|
|
50481
|
+
const reportPath = path32.join(directory, ".swarm", "simulate-report.md");
|
|
50482
|
+
await fs21.mkdir(path32.dirname(reportPath), { recursive: true });
|
|
50483
|
+
await fs21.writeFile(reportPath, report, "utf-8");
|
|
50397
50484
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
50398
50485
|
}
|
|
50399
50486
|
|
|
@@ -50750,8 +50837,8 @@ init_utils2();
|
|
|
50750
50837
|
init_manager2();
|
|
50751
50838
|
|
|
50752
50839
|
// src/services/compaction-service.ts
|
|
50753
|
-
import * as
|
|
50754
|
-
import * as
|
|
50840
|
+
import * as fs21 from "fs";
|
|
50841
|
+
import * as path32 from "path";
|
|
50755
50842
|
function makeInitialState() {
|
|
50756
50843
|
return {
|
|
50757
50844
|
lastObservationAt: 0,
|
|
@@ -50774,13 +50861,13 @@ function getSessionState(sessionId) {
|
|
|
50774
50861
|
}
|
|
50775
50862
|
function appendSnapshot(directory, tier, budgetPct, message) {
|
|
50776
50863
|
try {
|
|
50777
|
-
const snapshotPath =
|
|
50864
|
+
const snapshotPath = path32.join(directory, ".swarm", "context-snapshot.md");
|
|
50778
50865
|
const timestamp = new Date().toISOString();
|
|
50779
50866
|
const entry = `
|
|
50780
50867
|
## [${tier.toUpperCase()}] ${timestamp} \u2014 ${budgetPct.toFixed(1)}% used
|
|
50781
50868
|
${message}
|
|
50782
50869
|
`;
|
|
50783
|
-
|
|
50870
|
+
fs21.appendFileSync(snapshotPath, entry, "utf-8");
|
|
50784
50871
|
} catch {}
|
|
50785
50872
|
}
|
|
50786
50873
|
function buildObservationMessage(budgetPct) {
|
|
@@ -51505,11 +51592,11 @@ async function doFlush(directory) {
|
|
|
51505
51592
|
const activitySection = renderActivitySection();
|
|
51506
51593
|
const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
|
|
51507
51594
|
const flushedCount = swarmState.pendingEvents;
|
|
51508
|
-
const
|
|
51509
|
-
const tempPath = `${
|
|
51595
|
+
const path33 = nodePath2.join(directory, ".swarm", "context.md");
|
|
51596
|
+
const tempPath = `${path33}.tmp`;
|
|
51510
51597
|
try {
|
|
51511
51598
|
await Bun.write(tempPath, updated);
|
|
51512
|
-
renameSync8(tempPath,
|
|
51599
|
+
renameSync8(tempPath, path33);
|
|
51513
51600
|
} catch (writeError) {
|
|
51514
51601
|
try {
|
|
51515
51602
|
unlinkSync4(tempPath);
|
|
@@ -51558,7 +51645,7 @@ ${content.substring(endIndex + 1)}`;
|
|
|
51558
51645
|
}
|
|
51559
51646
|
// src/hooks/compaction-customizer.ts
|
|
51560
51647
|
init_manager2();
|
|
51561
|
-
import * as
|
|
51648
|
+
import * as fs22 from "fs";
|
|
51562
51649
|
import { join as join29 } from "path";
|
|
51563
51650
|
init_utils2();
|
|
51564
51651
|
function createCompactionCustomizerHook(config3, directory) {
|
|
@@ -51606,7 +51693,7 @@ function createCompactionCustomizerHook(config3, directory) {
|
|
|
51606
51693
|
}
|
|
51607
51694
|
try {
|
|
51608
51695
|
const summariesDir = join29(directory, ".swarm", "summaries");
|
|
51609
|
-
const files = await
|
|
51696
|
+
const files = await fs22.promises.readdir(summariesDir);
|
|
51610
51697
|
if (files.length > 0) {
|
|
51611
51698
|
const count = files.length;
|
|
51612
51699
|
output.context.push(`[CONTEXT OPTIMIZATION] Tool outputs from earlier in this session have been stored to disk. When compacting, replace any large tool output blocks (bash, test_runner, lint, diff results) with a one-line reference: "[Output stored \u2014 use /swarm retrieve to access full content]". Preserve the tool name, exit status, and any error messages. Discard raw output lines.`);
|
|
@@ -52091,8 +52178,8 @@ function maskToolOutput(msg, _threshold) {
|
|
|
52091
52178
|
}
|
|
52092
52179
|
// src/hooks/delegation-gate.ts
|
|
52093
52180
|
init_schema();
|
|
52094
|
-
import * as
|
|
52095
|
-
import * as
|
|
52181
|
+
import * as fs23 from "fs";
|
|
52182
|
+
import * as path35 from "path";
|
|
52096
52183
|
|
|
52097
52184
|
// src/parallel/review-router.ts
|
|
52098
52185
|
async function computeComplexity(directory, changedFiles) {
|
|
@@ -52104,13 +52191,13 @@ async function computeComplexity(directory, changedFiles) {
|
|
|
52104
52191
|
continue;
|
|
52105
52192
|
}
|
|
52106
52193
|
try {
|
|
52107
|
-
const
|
|
52108
|
-
const
|
|
52109
|
-
const filePath =
|
|
52110
|
-
if (!
|
|
52194
|
+
const fs23 = await import("fs");
|
|
52195
|
+
const path33 = await import("path");
|
|
52196
|
+
const filePath = path33.join(directory, file3);
|
|
52197
|
+
if (!fs23.existsSync(filePath)) {
|
|
52111
52198
|
continue;
|
|
52112
52199
|
}
|
|
52113
|
-
const content =
|
|
52200
|
+
const content = fs23.readFileSync(filePath, "utf-8");
|
|
52114
52201
|
const functionMatches = content.match(/\b(function|def|func|fn)\s+\w+/g);
|
|
52115
52202
|
const fileFunctionCount = functionMatches?.length || 0;
|
|
52116
52203
|
functionCount += fileFunctionCount;
|
|
@@ -52158,7 +52245,7 @@ function shouldParallelizeReview(routing) {
|
|
|
52158
52245
|
init_telemetry();
|
|
52159
52246
|
|
|
52160
52247
|
// src/hooks/guardrails.ts
|
|
52161
|
-
import * as
|
|
52248
|
+
import * as path33 from "path";
|
|
52162
52249
|
init_constants();
|
|
52163
52250
|
init_schema();
|
|
52164
52251
|
|
|
@@ -52320,10 +52407,10 @@ function isArchitect(sessionId) {
|
|
|
52320
52407
|
function isOutsideSwarmDir(filePath, directory) {
|
|
52321
52408
|
if (!filePath)
|
|
52322
52409
|
return false;
|
|
52323
|
-
const swarmDir =
|
|
52324
|
-
const resolved =
|
|
52325
|
-
const relative4 =
|
|
52326
|
-
return relative4.startsWith("..") ||
|
|
52410
|
+
const swarmDir = path33.resolve(directory, ".swarm");
|
|
52411
|
+
const resolved = path33.resolve(directory, filePath);
|
|
52412
|
+
const relative4 = path33.relative(swarmDir, resolved);
|
|
52413
|
+
return relative4.startsWith("..") || path33.isAbsolute(relative4);
|
|
52327
52414
|
}
|
|
52328
52415
|
function isSourceCodePath(filePath) {
|
|
52329
52416
|
if (!filePath)
|
|
@@ -52391,13 +52478,13 @@ function getCurrentTaskId(sessionId) {
|
|
|
52391
52478
|
}
|
|
52392
52479
|
function isInDeclaredScope(filePath, scopeEntries, cwd) {
|
|
52393
52480
|
const dir = cwd ?? process.cwd();
|
|
52394
|
-
const resolvedFile =
|
|
52481
|
+
const resolvedFile = path33.resolve(dir, filePath);
|
|
52395
52482
|
return scopeEntries.some((scope) => {
|
|
52396
|
-
const resolvedScope =
|
|
52483
|
+
const resolvedScope = path33.resolve(dir, scope);
|
|
52397
52484
|
if (resolvedFile === resolvedScope)
|
|
52398
52485
|
return true;
|
|
52399
|
-
const rel =
|
|
52400
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
52486
|
+
const rel = path33.relative(resolvedScope, resolvedFile);
|
|
52487
|
+
return rel.length > 0 && !rel.startsWith("..") && !path33.isAbsolute(rel);
|
|
52401
52488
|
});
|
|
52402
52489
|
}
|
|
52403
52490
|
function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
@@ -52593,9 +52680,9 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
52593
52680
|
const toolArgs = args2;
|
|
52594
52681
|
const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
|
|
52595
52682
|
if (typeof targetPath === "string" && targetPath.length > 0) {
|
|
52596
|
-
const resolvedTarget =
|
|
52597
|
-
const planMdPath =
|
|
52598
|
-
const planJsonPath =
|
|
52683
|
+
const resolvedTarget = path33.resolve(effectiveDirectory, targetPath).toLowerCase();
|
|
52684
|
+
const planMdPath = path33.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
|
|
52685
|
+
const planJsonPath = path33.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
|
|
52599
52686
|
if (resolvedTarget === planMdPath || resolvedTarget === planJsonPath) {
|
|
52600
52687
|
throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
|
|
52601
52688
|
}
|
|
@@ -52644,9 +52731,9 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
52644
52731
|
}
|
|
52645
52732
|
}
|
|
52646
52733
|
for (const p of paths) {
|
|
52647
|
-
const resolvedP =
|
|
52648
|
-
const planMdPath =
|
|
52649
|
-
const planJsonPath =
|
|
52734
|
+
const resolvedP = path33.resolve(effectiveDirectory, p);
|
|
52735
|
+
const planMdPath = path33.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
|
|
52736
|
+
const planJsonPath = path33.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
|
|
52650
52737
|
if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
|
|
52651
52738
|
throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
|
|
52652
52739
|
}
|
|
@@ -52666,7 +52753,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
52666
52753
|
}
|
|
52667
52754
|
}
|
|
52668
52755
|
}
|
|
52669
|
-
if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(
|
|
52756
|
+
if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(path33.relative(effectiveDirectory, path33.resolve(effectiveDirectory, targetPath)))) {
|
|
52670
52757
|
const session = swarmState.agentSessions.get(sessionID);
|
|
52671
52758
|
if (session) {
|
|
52672
52759
|
session.architectWriteCount++;
|
|
@@ -53297,8 +53384,8 @@ var AGENT_AUTHORITY_RULES = {
|
|
|
53297
53384
|
function checkFileAuthority(agentName, filePath, cwd) {
|
|
53298
53385
|
const normalizedAgent = agentName.toLowerCase();
|
|
53299
53386
|
const dir = cwd || process.cwd();
|
|
53300
|
-
const resolved =
|
|
53301
|
-
const normalizedPath =
|
|
53387
|
+
const resolved = path33.resolve(dir, filePath);
|
|
53388
|
+
const normalizedPath = path33.relative(dir, resolved).replace(/\\/g, "/");
|
|
53302
53389
|
const rules = AGENT_AUTHORITY_RULES[normalizedAgent];
|
|
53303
53390
|
if (!rules) {
|
|
53304
53391
|
return { allowed: false, reason: `Unknown agent: ${agentName}` };
|
|
@@ -53380,13 +53467,13 @@ async function getEvidenceTaskId(session, directory) {
|
|
|
53380
53467
|
if (typeof directory !== "string" || directory.length === 0) {
|
|
53381
53468
|
return null;
|
|
53382
53469
|
}
|
|
53383
|
-
const resolvedDirectory =
|
|
53384
|
-
const planPath =
|
|
53385
|
-
const resolvedPlanPath =
|
|
53386
|
-
if (!resolvedPlanPath.startsWith(resolvedDirectory +
|
|
53470
|
+
const resolvedDirectory = path35.resolve(directory);
|
|
53471
|
+
const planPath = path35.join(resolvedDirectory, ".swarm", "plan.json");
|
|
53472
|
+
const resolvedPlanPath = path35.resolve(planPath);
|
|
53473
|
+
if (!resolvedPlanPath.startsWith(resolvedDirectory + path35.sep) && resolvedPlanPath !== resolvedDirectory) {
|
|
53387
53474
|
return null;
|
|
53388
53475
|
}
|
|
53389
|
-
const planContent = await
|
|
53476
|
+
const planContent = await fs23.promises.readFile(resolvedPlanPath, "utf-8");
|
|
53390
53477
|
const plan = JSON.parse(planContent);
|
|
53391
53478
|
if (!plan || !Array.isArray(plan.phases)) {
|
|
53392
53479
|
return null;
|
|
@@ -53915,7 +54002,7 @@ ${warningLines.join(`
|
|
|
53915
54002
|
}
|
|
53916
54003
|
// src/hooks/delegation-sanitizer.ts
|
|
53917
54004
|
init_utils2();
|
|
53918
|
-
import * as
|
|
54005
|
+
import * as fs24 from "fs";
|
|
53919
54006
|
var SANITIZATION_PATTERNS = [
|
|
53920
54007
|
/\b\d+(st|nd|rd|th)\s+(attempt|try|time)\b/gi,
|
|
53921
54008
|
/\b(5th|fifth|final|last)\s+attempt\b/gi,
|
|
@@ -53986,7 +54073,7 @@ function createDelegationSanitizerHook(directory) {
|
|
|
53986
54073
|
stripped_patterns: result.stripped,
|
|
53987
54074
|
timestamp: new Date().toISOString()
|
|
53988
54075
|
};
|
|
53989
|
-
|
|
54076
|
+
fs24.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
53990
54077
|
`, "utf-8");
|
|
53991
54078
|
} catch {}
|
|
53992
54079
|
}
|
|
@@ -54111,7 +54198,7 @@ function consolidateSystemMessages(messages) {
|
|
|
54111
54198
|
// src/hooks/phase-monitor.ts
|
|
54112
54199
|
init_schema();
|
|
54113
54200
|
init_manager2();
|
|
54114
|
-
import * as
|
|
54201
|
+
import * as path36 from "path";
|
|
54115
54202
|
init_utils2();
|
|
54116
54203
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner = runCuratorInit) {
|
|
54117
54204
|
let lastKnownPhase = null;
|
|
@@ -54129,9 +54216,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner = run
|
|
|
54129
54216
|
if (curatorConfig.enabled && curatorConfig.init_enabled) {
|
|
54130
54217
|
const initResult = await curatorRunner(directory, curatorConfig);
|
|
54131
54218
|
if (initResult.briefing) {
|
|
54132
|
-
const briefingPath =
|
|
54219
|
+
const briefingPath = path36.join(directory, ".swarm", "curator-briefing.md");
|
|
54133
54220
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
54134
|
-
await mkdir5(
|
|
54221
|
+
await mkdir5(path36.dirname(briefingPath), { recursive: true });
|
|
54135
54222
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
54136
54223
|
}
|
|
54137
54224
|
}
|
|
@@ -54243,15 +54330,15 @@ init_schema();
|
|
|
54243
54330
|
init_manager();
|
|
54244
54331
|
init_detector();
|
|
54245
54332
|
init_manager2();
|
|
54246
|
-
import * as
|
|
54247
|
-
import * as
|
|
54333
|
+
import * as fs28 from "fs";
|
|
54334
|
+
import * as path40 from "path";
|
|
54248
54335
|
|
|
54249
54336
|
// src/services/decision-drift-analyzer.ts
|
|
54250
54337
|
init_utils2();
|
|
54251
54338
|
init_manager2();
|
|
54252
54339
|
init_utils();
|
|
54253
|
-
import * as
|
|
54254
|
-
import * as
|
|
54340
|
+
import * as fs25 from "fs";
|
|
54341
|
+
import * as path37 from "path";
|
|
54255
54342
|
var DEFAULT_DRIFT_CONFIG = {
|
|
54256
54343
|
staleThresholdPhases: 1,
|
|
54257
54344
|
detectContradictions: true,
|
|
@@ -54405,11 +54492,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
54405
54492
|
currentPhase = legacyPhase;
|
|
54406
54493
|
}
|
|
54407
54494
|
}
|
|
54408
|
-
const contextPath =
|
|
54495
|
+
const contextPath = path37.join(directory, ".swarm", "context.md");
|
|
54409
54496
|
let contextContent = "";
|
|
54410
54497
|
try {
|
|
54411
|
-
if (
|
|
54412
|
-
contextContent =
|
|
54498
|
+
if (fs25.existsSync(contextPath)) {
|
|
54499
|
+
contextContent = fs25.readFileSync(contextPath, "utf-8");
|
|
54413
54500
|
}
|
|
54414
54501
|
} catch (error93) {
|
|
54415
54502
|
log("[DecisionDriftAnalyzer] context file read failed", {
|
|
@@ -54534,8 +54621,8 @@ init_utils();
|
|
|
54534
54621
|
// src/hooks/adversarial-detector.ts
|
|
54535
54622
|
init_constants();
|
|
54536
54623
|
init_schema();
|
|
54537
|
-
import * as
|
|
54538
|
-
import * as
|
|
54624
|
+
import * as fs26 from "fs/promises";
|
|
54625
|
+
import * as path38 from "path";
|
|
54539
54626
|
function safeGet(obj, key) {
|
|
54540
54627
|
if (!obj || !Object.hasOwn(obj, key))
|
|
54541
54628
|
return;
|
|
@@ -54749,10 +54836,10 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
54749
54836
|
let eventLogged = false;
|
|
54750
54837
|
let checkpointCreated = false;
|
|
54751
54838
|
try {
|
|
54752
|
-
const swarmDir =
|
|
54753
|
-
await
|
|
54754
|
-
const eventsPath =
|
|
54755
|
-
await
|
|
54839
|
+
const swarmDir = path38.join(directory, ".swarm");
|
|
54840
|
+
await fs26.mkdir(swarmDir, { recursive: true });
|
|
54841
|
+
const eventsPath = path38.join(swarmDir, "events.jsonl");
|
|
54842
|
+
await fs26.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
54756
54843
|
`);
|
|
54757
54844
|
eventLogged = true;
|
|
54758
54845
|
} catch {}
|
|
@@ -55133,7 +55220,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55133
55220
|
} catch {}
|
|
55134
55221
|
try {
|
|
55135
55222
|
const darkMatterPath = validateSwarmPath(directory, "dark-matter.md");
|
|
55136
|
-
if (!
|
|
55223
|
+
if (!fs28.existsSync(darkMatterPath)) {
|
|
55137
55224
|
const {
|
|
55138
55225
|
detectDarkMatter: detectDarkMatter2,
|
|
55139
55226
|
formatDarkMatterOutput: formatDarkMatterOutput2,
|
|
@@ -55146,10 +55233,10 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55146
55233
|
});
|
|
55147
55234
|
if (darkMatter && darkMatter.length > 0) {
|
|
55148
55235
|
const darkMatterReport = formatDarkMatterOutput2(darkMatter);
|
|
55149
|
-
await
|
|
55236
|
+
await fs28.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
55150
55237
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
55151
55238
|
try {
|
|
55152
|
-
const projectName =
|
|
55239
|
+
const projectName = path40.basename(path40.resolve(directory));
|
|
55153
55240
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
55154
55241
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
55155
55242
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -55200,11 +55287,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55200
55287
|
if (handoffContent) {
|
|
55201
55288
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55202
55289
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55203
|
-
if (
|
|
55290
|
+
if (fs28.existsSync(consumedPath)) {
|
|
55204
55291
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55205
|
-
|
|
55292
|
+
fs28.unlinkSync(consumedPath);
|
|
55206
55293
|
}
|
|
55207
|
-
|
|
55294
|
+
fs28.renameSync(handoffPath, consumedPath);
|
|
55208
55295
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55209
55296
|
The previous model's session ended. Here is your starting context:
|
|
55210
55297
|
|
|
@@ -55485,11 +55572,11 @@ ${budgetWarning}`);
|
|
|
55485
55572
|
if (handoffContent) {
|
|
55486
55573
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55487
55574
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55488
|
-
if (
|
|
55575
|
+
if (fs28.existsSync(consumedPath)) {
|
|
55489
55576
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55490
|
-
|
|
55577
|
+
fs28.unlinkSync(consumedPath);
|
|
55491
55578
|
}
|
|
55492
|
-
|
|
55579
|
+
fs28.renameSync(handoffPath, consumedPath);
|
|
55493
55580
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55494
55581
|
The previous model's session ended. Here is your starting context:
|
|
55495
55582
|
|
|
@@ -56259,14 +56346,14 @@ function isReadTool(toolName) {
|
|
|
56259
56346
|
}
|
|
56260
56347
|
|
|
56261
56348
|
// src/hooks/incremental-verify.ts
|
|
56262
|
-
import * as
|
|
56263
|
-
import * as
|
|
56349
|
+
import * as fs29 from "fs";
|
|
56350
|
+
import * as path41 from "path";
|
|
56264
56351
|
|
|
56265
56352
|
// src/hooks/spawn-helper.ts
|
|
56266
56353
|
import { spawn } from "child_process";
|
|
56267
56354
|
var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
|
|
56268
56355
|
function spawnAsync(command, cwd, timeoutMs) {
|
|
56269
|
-
return new Promise((
|
|
56356
|
+
return new Promise((resolve13) => {
|
|
56270
56357
|
try {
|
|
56271
56358
|
const [rawCmd, ...args2] = command;
|
|
56272
56359
|
const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
|
|
@@ -56310,24 +56397,24 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
56310
56397
|
try {
|
|
56311
56398
|
proc.kill();
|
|
56312
56399
|
} catch {}
|
|
56313
|
-
|
|
56400
|
+
resolve13(null);
|
|
56314
56401
|
}, timeoutMs);
|
|
56315
56402
|
proc.on("close", (code) => {
|
|
56316
56403
|
if (done)
|
|
56317
56404
|
return;
|
|
56318
56405
|
done = true;
|
|
56319
56406
|
clearTimeout(timer);
|
|
56320
|
-
|
|
56407
|
+
resolve13({ exitCode: code ?? 1, stdout, stderr });
|
|
56321
56408
|
});
|
|
56322
56409
|
proc.on("error", () => {
|
|
56323
56410
|
if (done)
|
|
56324
56411
|
return;
|
|
56325
56412
|
done = true;
|
|
56326
56413
|
clearTimeout(timer);
|
|
56327
|
-
|
|
56414
|
+
resolve13(null);
|
|
56328
56415
|
});
|
|
56329
56416
|
} catch {
|
|
56330
|
-
|
|
56417
|
+
resolve13(null);
|
|
56331
56418
|
}
|
|
56332
56419
|
});
|
|
56333
56420
|
}
|
|
@@ -56335,21 +56422,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
56335
56422
|
// src/hooks/incremental-verify.ts
|
|
56336
56423
|
var emittedSkipAdvisories = new Set;
|
|
56337
56424
|
function detectPackageManager(projectDir) {
|
|
56338
|
-
if (
|
|
56425
|
+
if (fs29.existsSync(path41.join(projectDir, "bun.lockb")))
|
|
56339
56426
|
return "bun";
|
|
56340
|
-
if (
|
|
56427
|
+
if (fs29.existsSync(path41.join(projectDir, "pnpm-lock.yaml")))
|
|
56341
56428
|
return "pnpm";
|
|
56342
|
-
if (
|
|
56429
|
+
if (fs29.existsSync(path41.join(projectDir, "yarn.lock")))
|
|
56343
56430
|
return "yarn";
|
|
56344
|
-
if (
|
|
56431
|
+
if (fs29.existsSync(path41.join(projectDir, "package-lock.json")))
|
|
56345
56432
|
return "npm";
|
|
56346
56433
|
return "bun";
|
|
56347
56434
|
}
|
|
56348
56435
|
function detectTypecheckCommand(projectDir) {
|
|
56349
|
-
const pkgPath =
|
|
56350
|
-
if (
|
|
56436
|
+
const pkgPath = path41.join(projectDir, "package.json");
|
|
56437
|
+
if (fs29.existsSync(pkgPath)) {
|
|
56351
56438
|
try {
|
|
56352
|
-
const pkg = JSON.parse(
|
|
56439
|
+
const pkg = JSON.parse(fs29.readFileSync(pkgPath, "utf8"));
|
|
56353
56440
|
const scripts = pkg.scripts;
|
|
56354
56441
|
if (scripts?.typecheck) {
|
|
56355
56442
|
const pm = detectPackageManager(projectDir);
|
|
@@ -56363,8 +56450,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56363
56450
|
...pkg.dependencies,
|
|
56364
56451
|
...pkg.devDependencies
|
|
56365
56452
|
};
|
|
56366
|
-
if (!deps?.typescript && !
|
|
56367
|
-
const hasTSMarkers = deps?.typescript ||
|
|
56453
|
+
if (!deps?.typescript && !fs29.existsSync(path41.join(projectDir, "tsconfig.json"))) {}
|
|
56454
|
+
const hasTSMarkers = deps?.typescript || fs29.existsSync(path41.join(projectDir, "tsconfig.json"));
|
|
56368
56455
|
if (hasTSMarkers) {
|
|
56369
56456
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
56370
56457
|
}
|
|
@@ -56372,17 +56459,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56372
56459
|
return null;
|
|
56373
56460
|
}
|
|
56374
56461
|
}
|
|
56375
|
-
if (
|
|
56462
|
+
if (fs29.existsSync(path41.join(projectDir, "go.mod"))) {
|
|
56376
56463
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
56377
56464
|
}
|
|
56378
|
-
if (
|
|
56465
|
+
if (fs29.existsSync(path41.join(projectDir, "Cargo.toml"))) {
|
|
56379
56466
|
return { command: ["cargo", "check"], language: "rust" };
|
|
56380
56467
|
}
|
|
56381
|
-
if (
|
|
56468
|
+
if (fs29.existsSync(path41.join(projectDir, "pyproject.toml")) || fs29.existsSync(path41.join(projectDir, "requirements.txt")) || fs29.existsSync(path41.join(projectDir, "setup.py"))) {
|
|
56382
56469
|
return { command: null, language: "python" };
|
|
56383
56470
|
}
|
|
56384
56471
|
try {
|
|
56385
|
-
const entries =
|
|
56472
|
+
const entries = fs29.readdirSync(projectDir);
|
|
56386
56473
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
56387
56474
|
return {
|
|
56388
56475
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -56691,7 +56778,7 @@ ${injectionText}`;
|
|
|
56691
56778
|
// src/hooks/scope-guard.ts
|
|
56692
56779
|
init_constants();
|
|
56693
56780
|
init_schema();
|
|
56694
|
-
import * as
|
|
56781
|
+
import * as path43 from "path";
|
|
56695
56782
|
var WRITE_TOOLS = new Set([
|
|
56696
56783
|
"write",
|
|
56697
56784
|
"edit",
|
|
@@ -56753,13 +56840,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
56753
56840
|
}
|
|
56754
56841
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
56755
56842
|
const dir = directory ?? process.cwd();
|
|
56756
|
-
const resolvedFile =
|
|
56843
|
+
const resolvedFile = path43.resolve(dir, filePath);
|
|
56757
56844
|
return scopeEntries.some((scope) => {
|
|
56758
|
-
const resolvedScope =
|
|
56845
|
+
const resolvedScope = path43.resolve(dir, scope);
|
|
56759
56846
|
if (resolvedFile === resolvedScope)
|
|
56760
56847
|
return true;
|
|
56761
|
-
const rel =
|
|
56762
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
56848
|
+
const rel = path43.relative(resolvedScope, resolvedFile);
|
|
56849
|
+
return rel.length > 0 && !rel.startsWith("..") && !path43.isAbsolute(rel);
|
|
56763
56850
|
});
|
|
56764
56851
|
}
|
|
56765
56852
|
|
|
@@ -56808,8 +56895,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
56808
56895
|
}
|
|
56809
56896
|
|
|
56810
56897
|
// src/hooks/slop-detector.ts
|
|
56811
|
-
import * as
|
|
56812
|
-
import * as
|
|
56898
|
+
import * as fs31 from "fs";
|
|
56899
|
+
import * as path44 from "path";
|
|
56813
56900
|
var WRITE_EDIT_TOOLS = new Set([
|
|
56814
56901
|
"write",
|
|
56815
56902
|
"edit",
|
|
@@ -56854,12 +56941,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
56854
56941
|
function walkFiles(dir, exts, deadline) {
|
|
56855
56942
|
const results = [];
|
|
56856
56943
|
try {
|
|
56857
|
-
for (const entry of
|
|
56944
|
+
for (const entry of fs31.readdirSync(dir, { withFileTypes: true })) {
|
|
56858
56945
|
if (deadline !== undefined && Date.now() > deadline)
|
|
56859
56946
|
break;
|
|
56860
56947
|
if (entry.isSymbolicLink())
|
|
56861
56948
|
continue;
|
|
56862
|
-
const full =
|
|
56949
|
+
const full = path44.join(dir, entry.name);
|
|
56863
56950
|
if (entry.isDirectory()) {
|
|
56864
56951
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
56865
56952
|
continue;
|
|
@@ -56874,7 +56961,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
56874
56961
|
return results;
|
|
56875
56962
|
}
|
|
56876
56963
|
function checkDeadExports(content, projectDir, startTime) {
|
|
56877
|
-
const hasPackageJson =
|
|
56964
|
+
const hasPackageJson = fs31.existsSync(path44.join(projectDir, "package.json"));
|
|
56878
56965
|
if (!hasPackageJson)
|
|
56879
56966
|
return null;
|
|
56880
56967
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -56897,7 +56984,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
56897
56984
|
if (found || Date.now() - startTime > 480)
|
|
56898
56985
|
break;
|
|
56899
56986
|
try {
|
|
56900
|
-
const text =
|
|
56987
|
+
const text = fs31.readFileSync(file3, "utf-8");
|
|
56901
56988
|
if (importPattern.test(text))
|
|
56902
56989
|
found = true;
|
|
56903
56990
|
importPattern.lastIndex = 0;
|
|
@@ -57030,7 +57117,7 @@ Review before proceeding.`;
|
|
|
57030
57117
|
|
|
57031
57118
|
// src/hooks/steering-consumed.ts
|
|
57032
57119
|
init_utils2();
|
|
57033
|
-
import * as
|
|
57120
|
+
import * as fs32 from "fs";
|
|
57034
57121
|
function recordSteeringConsumed(directory, directiveId) {
|
|
57035
57122
|
try {
|
|
57036
57123
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -57039,7 +57126,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
57039
57126
|
directiveId,
|
|
57040
57127
|
timestamp: new Date().toISOString()
|
|
57041
57128
|
};
|
|
57042
|
-
|
|
57129
|
+
fs32.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57043
57130
|
`, "utf-8");
|
|
57044
57131
|
} catch {}
|
|
57045
57132
|
}
|
|
@@ -57329,21 +57416,24 @@ async function executeCommand(command) {
|
|
|
57329
57416
|
cmd = ["/bin/sh"];
|
|
57330
57417
|
args2 = ["-c", command.command];
|
|
57331
57418
|
}
|
|
57332
|
-
const result =
|
|
57419
|
+
const result = Bun.spawn({
|
|
57333
57420
|
cmd: [...cmd, ...args2],
|
|
57334
57421
|
cwd: command.cwd,
|
|
57335
57422
|
stdout: "pipe",
|
|
57336
57423
|
stderr: "pipe",
|
|
57337
57424
|
timeout: DEFAULT_TIMEOUT_MS2
|
|
57338
57425
|
});
|
|
57426
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
57427
|
+
result.exited,
|
|
57428
|
+
new Response(result.stdout).text(),
|
|
57429
|
+
new Response(result.stderr).text()
|
|
57430
|
+
]);
|
|
57339
57431
|
const duration_ms = Date.now() - startTime;
|
|
57340
|
-
const stdout = await new Response(result.stdout).text();
|
|
57341
|
-
const stderr = await new Response(result.stderr).text();
|
|
57342
57432
|
return {
|
|
57343
57433
|
kind,
|
|
57344
57434
|
command: command.command,
|
|
57345
57435
|
cwd: command.cwd,
|
|
57346
|
-
exit_code:
|
|
57436
|
+
exit_code: exitCode ?? -1,
|
|
57347
57437
|
duration_ms,
|
|
57348
57438
|
stdout_tail: truncateOutput(stdout),
|
|
57349
57439
|
stderr_tail: truncateOutput(stderr)
|
|
@@ -57448,8 +57538,9 @@ var build_check = createSwarmTool({
|
|
|
57448
57538
|
init_dist();
|
|
57449
57539
|
init_manager();
|
|
57450
57540
|
init_create_tool();
|
|
57451
|
-
|
|
57452
|
-
import * as
|
|
57541
|
+
init_resolve_working_directory();
|
|
57542
|
+
import * as fs33 from "fs";
|
|
57543
|
+
import * as path45 from "path";
|
|
57453
57544
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
57454
57545
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
57455
57546
|
function isValidTaskId3(taskId) {
|
|
@@ -57466,18 +57557,18 @@ function isValidTaskId3(taskId) {
|
|
|
57466
57557
|
return TASK_ID_PATTERN2.test(taskId);
|
|
57467
57558
|
}
|
|
57468
57559
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
57469
|
-
const normalizedWorkspace =
|
|
57470
|
-
const swarmPath =
|
|
57471
|
-
const normalizedPath =
|
|
57560
|
+
const normalizedWorkspace = path45.resolve(workspaceRoot);
|
|
57561
|
+
const swarmPath = path45.join(normalizedWorkspace, ".swarm", "evidence");
|
|
57562
|
+
const normalizedPath = path45.resolve(filePath);
|
|
57472
57563
|
return normalizedPath.startsWith(swarmPath);
|
|
57473
57564
|
}
|
|
57474
57565
|
function readEvidenceFile(evidencePath) {
|
|
57475
|
-
if (!
|
|
57566
|
+
if (!fs33.existsSync(evidencePath)) {
|
|
57476
57567
|
return null;
|
|
57477
57568
|
}
|
|
57478
57569
|
let content;
|
|
57479
57570
|
try {
|
|
57480
|
-
content =
|
|
57571
|
+
content = fs33.readFileSync(evidencePath, "utf-8");
|
|
57481
57572
|
} catch {
|
|
57482
57573
|
return null;
|
|
57483
57574
|
}
|
|
@@ -57495,16 +57586,34 @@ function readEvidenceFile(evidencePath) {
|
|
|
57495
57586
|
var check_gate_status = createSwarmTool({
|
|
57496
57587
|
description: "Read-only tool to check the gate status of a specific task. Reads .swarm/evidence/{taskId}.json and returns structured JSON describing required, passed, and missing gates.",
|
|
57497
57588
|
args: {
|
|
57498
|
-
task_id: tool.schema.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/, 'Task ID must be in N.M or N.M.P format (e.g., "1.1", "1.2.3", "1.2.3.4")').describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")')
|
|
57589
|
+
task_id: tool.schema.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/, 'Task ID must be in N.M or N.M.P format (e.g., "1.1", "1.2.3", "1.2.3.4")').describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")'),
|
|
57590
|
+
working_directory: tool.schema.string().optional().describe("Explicit project root directory. When provided, .swarm/evidence/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
57499
57591
|
},
|
|
57500
57592
|
async execute(args2, directory) {
|
|
57501
57593
|
let taskIdInput;
|
|
57594
|
+
let workingDirInput;
|
|
57502
57595
|
try {
|
|
57503
57596
|
if (args2 && typeof args2 === "object") {
|
|
57504
57597
|
const obj = args2;
|
|
57505
57598
|
taskIdInput = typeof obj.task_id === "string" ? obj.task_id : undefined;
|
|
57599
|
+
workingDirInput = typeof obj.working_directory === "string" ? obj.working_directory : undefined;
|
|
57506
57600
|
}
|
|
57507
57601
|
} catch {}
|
|
57602
|
+
const dirResult = resolveWorkingDirectory(workingDirInput, directory);
|
|
57603
|
+
if (!dirResult.success) {
|
|
57604
|
+
const errorResult = {
|
|
57605
|
+
taskId: taskIdInput ?? "",
|
|
57606
|
+
status: "no_evidence",
|
|
57607
|
+
required_gates: [],
|
|
57608
|
+
passed_gates: [],
|
|
57609
|
+
missing_gates: [],
|
|
57610
|
+
gates: {},
|
|
57611
|
+
message: dirResult.message,
|
|
57612
|
+
todo_scan: null
|
|
57613
|
+
};
|
|
57614
|
+
return JSON.stringify(errorResult, null, 2);
|
|
57615
|
+
}
|
|
57616
|
+
directory = dirResult.directory;
|
|
57508
57617
|
if (!taskIdInput) {
|
|
57509
57618
|
const errorResult = {
|
|
57510
57619
|
taskId: "",
|
|
@@ -57531,7 +57640,7 @@ var check_gate_status = createSwarmTool({
|
|
|
57531
57640
|
};
|
|
57532
57641
|
return JSON.stringify(errorResult, null, 2);
|
|
57533
57642
|
}
|
|
57534
|
-
const evidencePath =
|
|
57643
|
+
const evidencePath = path45.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
57535
57644
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
57536
57645
|
const errorResult = {
|
|
57537
57646
|
taskId: taskIdInput,
|
|
@@ -57624,9 +57733,10 @@ init_co_change_analyzer();
|
|
|
57624
57733
|
// src/tools/completion-verify.ts
|
|
57625
57734
|
init_dist();
|
|
57626
57735
|
init_utils2();
|
|
57627
|
-
import * as
|
|
57628
|
-
import * as
|
|
57736
|
+
import * as fs34 from "fs";
|
|
57737
|
+
import * as path46 from "path";
|
|
57629
57738
|
init_create_tool();
|
|
57739
|
+
init_resolve_working_directory();
|
|
57630
57740
|
function extractMatches(regex, text) {
|
|
57631
57741
|
return Array.from(text.matchAll(regex));
|
|
57632
57742
|
}
|
|
@@ -57720,7 +57830,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57720
57830
|
let plan;
|
|
57721
57831
|
try {
|
|
57722
57832
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
57723
|
-
const planRaw =
|
|
57833
|
+
const planRaw = fs34.readFileSync(planPath, "utf-8");
|
|
57724
57834
|
plan = JSON.parse(planRaw);
|
|
57725
57835
|
} catch {
|
|
57726
57836
|
const result2 = {
|
|
@@ -57778,10 +57888,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57778
57888
|
let hasFileReadFailure = false;
|
|
57779
57889
|
for (const filePath of fileTargets) {
|
|
57780
57890
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
57781
|
-
const resolvedPath =
|
|
57782
|
-
const projectRoot =
|
|
57783
|
-
const relative6 =
|
|
57784
|
-
const withinProject = relative6 === "" || !relative6.startsWith("..") && !
|
|
57891
|
+
const resolvedPath = path46.resolve(directory, normalizedPath);
|
|
57892
|
+
const projectRoot = path46.resolve(directory);
|
|
57893
|
+
const relative6 = path46.relative(projectRoot, resolvedPath);
|
|
57894
|
+
const withinProject = relative6 === "" || !relative6.startsWith("..") && !path46.isAbsolute(relative6);
|
|
57785
57895
|
if (!withinProject) {
|
|
57786
57896
|
blockedTasks.push({
|
|
57787
57897
|
task_id: task.id,
|
|
@@ -57794,7 +57904,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57794
57904
|
}
|
|
57795
57905
|
let fileContent;
|
|
57796
57906
|
try {
|
|
57797
|
-
fileContent =
|
|
57907
|
+
fileContent = fs34.readFileSync(resolvedPath, "utf-8");
|
|
57798
57908
|
} catch {
|
|
57799
57909
|
blockedTasks.push({
|
|
57800
57910
|
task_id: task.id,
|
|
@@ -57836,9 +57946,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57836
57946
|
blockedTasks
|
|
57837
57947
|
};
|
|
57838
57948
|
try {
|
|
57839
|
-
const evidenceDir =
|
|
57840
|
-
const evidencePath =
|
|
57841
|
-
|
|
57949
|
+
const evidenceDir = path46.join(directory, ".swarm", "evidence", `${phase}`);
|
|
57950
|
+
const evidencePath = path46.join(evidenceDir, "completion-verify.json");
|
|
57951
|
+
fs34.mkdirSync(evidenceDir, { recursive: true });
|
|
57842
57952
|
const evidenceBundle = {
|
|
57843
57953
|
schema_version: "1.0.0",
|
|
57844
57954
|
task_id: "completion-verify",
|
|
@@ -57859,7 +57969,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57859
57969
|
}
|
|
57860
57970
|
]
|
|
57861
57971
|
};
|
|
57862
|
-
|
|
57972
|
+
fs34.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
57863
57973
|
} catch {}
|
|
57864
57974
|
return JSON.stringify(result, null, 2);
|
|
57865
57975
|
}
|
|
@@ -57867,7 +57977,8 @@ var completion_verify = createSwarmTool({
|
|
|
57867
57977
|
description: "Deterministic pre-check verifying that plan task identifiers exist in their target source files before phase completion. Blocks if obviously incomplete.",
|
|
57868
57978
|
args: {
|
|
57869
57979
|
phase: tool.schema.number().describe("The phase number to check"),
|
|
57870
|
-
sessionID: tool.schema.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)")
|
|
57980
|
+
sessionID: tool.schema.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),
|
|
57981
|
+
working_directory: tool.schema.string().optional().describe("Explicit project root directory. When provided, .swarm/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
57871
57982
|
},
|
|
57872
57983
|
execute: async (args2, directory) => {
|
|
57873
57984
|
let parsedArgs;
|
|
@@ -57876,7 +57987,8 @@ var completion_verify = createSwarmTool({
|
|
|
57876
57987
|
const obj = args2;
|
|
57877
57988
|
parsedArgs = {
|
|
57878
57989
|
phase: typeof obj.phase === "number" ? obj.phase : typeof obj.phase === "string" ? Number(obj.phase) : 0,
|
|
57879
|
-
sessionID: typeof obj.sessionID === "string" ? obj.sessionID : undefined
|
|
57990
|
+
sessionID: typeof obj.sessionID === "string" ? obj.sessionID : undefined,
|
|
57991
|
+
working_directory: typeof obj.working_directory === "string" ? obj.working_directory : undefined
|
|
57880
57992
|
};
|
|
57881
57993
|
} else {
|
|
57882
57994
|
parsedArgs = { phase: 0 };
|
|
@@ -57893,17 +58005,30 @@ var completion_verify = createSwarmTool({
|
|
|
57893
58005
|
blockedTasks: []
|
|
57894
58006
|
}, null, 2);
|
|
57895
58007
|
}
|
|
57896
|
-
|
|
58008
|
+
const dirResult = resolveWorkingDirectory(parsedArgs.working_directory, directory);
|
|
58009
|
+
if (!dirResult.success) {
|
|
58010
|
+
return JSON.stringify({
|
|
58011
|
+
success: false,
|
|
58012
|
+
phase: parsedArgs.phase,
|
|
58013
|
+
status: "blocked",
|
|
58014
|
+
reason: dirResult.message,
|
|
58015
|
+
tasksChecked: 0,
|
|
58016
|
+
tasksSkipped: 0,
|
|
58017
|
+
tasksBlocked: 0,
|
|
58018
|
+
blockedTasks: []
|
|
58019
|
+
}, null, 2);
|
|
58020
|
+
}
|
|
58021
|
+
return executeCompletionVerify(parsedArgs, dirResult.directory);
|
|
57897
58022
|
}
|
|
57898
58023
|
});
|
|
57899
58024
|
// src/tools/complexity-hotspots.ts
|
|
57900
58025
|
init_dist();
|
|
57901
|
-
import * as
|
|
57902
|
-
import * as
|
|
58026
|
+
import * as fs36 from "fs";
|
|
58027
|
+
import * as path48 from "path";
|
|
57903
58028
|
|
|
57904
58029
|
// src/quality/metrics.ts
|
|
57905
|
-
import * as
|
|
57906
|
-
import * as
|
|
58030
|
+
import * as fs35 from "fs";
|
|
58031
|
+
import * as path47 from "path";
|
|
57907
58032
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
57908
58033
|
var MIN_DUPLICATION_LINES = 10;
|
|
57909
58034
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -57941,11 +58066,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
57941
58066
|
}
|
|
57942
58067
|
function getComplexityForFile(filePath) {
|
|
57943
58068
|
try {
|
|
57944
|
-
const stat2 =
|
|
58069
|
+
const stat2 = fs35.statSync(filePath);
|
|
57945
58070
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
57946
58071
|
return null;
|
|
57947
58072
|
}
|
|
57948
|
-
const content =
|
|
58073
|
+
const content = fs35.readFileSync(filePath, "utf-8");
|
|
57949
58074
|
return estimateCyclomaticComplexity(content);
|
|
57950
58075
|
} catch {
|
|
57951
58076
|
return null;
|
|
@@ -57955,8 +58080,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
57955
58080
|
let totalComplexity = 0;
|
|
57956
58081
|
const analyzedFiles = [];
|
|
57957
58082
|
for (const file3 of files) {
|
|
57958
|
-
const fullPath =
|
|
57959
|
-
if (!
|
|
58083
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58084
|
+
if (!fs35.existsSync(fullPath)) {
|
|
57960
58085
|
continue;
|
|
57961
58086
|
}
|
|
57962
58087
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -58077,8 +58202,8 @@ function countGoExports(content) {
|
|
|
58077
58202
|
}
|
|
58078
58203
|
function getExportCountForFile(filePath) {
|
|
58079
58204
|
try {
|
|
58080
|
-
const content =
|
|
58081
|
-
const ext =
|
|
58205
|
+
const content = fs35.readFileSync(filePath, "utf-8");
|
|
58206
|
+
const ext = path47.extname(filePath).toLowerCase();
|
|
58082
58207
|
switch (ext) {
|
|
58083
58208
|
case ".ts":
|
|
58084
58209
|
case ".tsx":
|
|
@@ -58104,8 +58229,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58104
58229
|
let totalExports = 0;
|
|
58105
58230
|
const analyzedFiles = [];
|
|
58106
58231
|
for (const file3 of files) {
|
|
58107
|
-
const fullPath =
|
|
58108
|
-
if (!
|
|
58232
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58233
|
+
if (!fs35.existsSync(fullPath)) {
|
|
58109
58234
|
continue;
|
|
58110
58235
|
}
|
|
58111
58236
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -58138,16 +58263,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58138
58263
|
let duplicateLines = 0;
|
|
58139
58264
|
const analyzedFiles = [];
|
|
58140
58265
|
for (const file3 of files) {
|
|
58141
|
-
const fullPath =
|
|
58142
|
-
if (!
|
|
58266
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58267
|
+
if (!fs35.existsSync(fullPath)) {
|
|
58143
58268
|
continue;
|
|
58144
58269
|
}
|
|
58145
58270
|
try {
|
|
58146
|
-
const stat2 =
|
|
58271
|
+
const stat2 = fs35.statSync(fullPath);
|
|
58147
58272
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58148
58273
|
continue;
|
|
58149
58274
|
}
|
|
58150
|
-
const content =
|
|
58275
|
+
const content = fs35.readFileSync(fullPath, "utf-8");
|
|
58151
58276
|
const lines = content.split(`
|
|
58152
58277
|
`).filter((line) => line.trim().length > 0);
|
|
58153
58278
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -58171,8 +58296,8 @@ function countCodeLines(content) {
|
|
|
58171
58296
|
return lines.length;
|
|
58172
58297
|
}
|
|
58173
58298
|
function isTestFile(filePath) {
|
|
58174
|
-
const basename7 =
|
|
58175
|
-
const _ext =
|
|
58299
|
+
const basename7 = path47.basename(filePath);
|
|
58300
|
+
const _ext = path47.extname(filePath).toLowerCase();
|
|
58176
58301
|
const testPatterns = [
|
|
58177
58302
|
".test.",
|
|
58178
58303
|
".spec.",
|
|
@@ -58253,8 +58378,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58253
58378
|
}
|
|
58254
58379
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58255
58380
|
}
|
|
58256
|
-
function matchesGlobSegment(
|
|
58257
|
-
const normalizedPath =
|
|
58381
|
+
function matchesGlobSegment(path48, glob) {
|
|
58382
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58258
58383
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58259
58384
|
if (normalizedPath.includes("//")) {
|
|
58260
58385
|
return false;
|
|
@@ -58285,8 +58410,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58285
58410
|
function hasGlobstar(glob) {
|
|
58286
58411
|
return glob.includes("**");
|
|
58287
58412
|
}
|
|
58288
|
-
function globMatches(
|
|
58289
|
-
const normalizedPath =
|
|
58413
|
+
function globMatches(path48, glob) {
|
|
58414
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58290
58415
|
if (!glob || glob === "") {
|
|
58291
58416
|
if (normalizedPath.includes("//")) {
|
|
58292
58417
|
return false;
|
|
@@ -58322,31 +58447,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58322
58447
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58323
58448
|
let testLines = 0;
|
|
58324
58449
|
let codeLines = 0;
|
|
58325
|
-
const srcDir =
|
|
58326
|
-
if (
|
|
58450
|
+
const srcDir = path47.join(workingDir, "src");
|
|
58451
|
+
if (fs35.existsSync(srcDir)) {
|
|
58327
58452
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58328
58453
|
codeLines += lines;
|
|
58329
58454
|
});
|
|
58330
58455
|
}
|
|
58331
58456
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58332
58457
|
for (const dir of possibleSrcDirs) {
|
|
58333
|
-
const dirPath =
|
|
58334
|
-
if (
|
|
58458
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58459
|
+
if (fs35.existsSync(dirPath)) {
|
|
58335
58460
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58336
58461
|
codeLines += lines;
|
|
58337
58462
|
});
|
|
58338
58463
|
}
|
|
58339
58464
|
}
|
|
58340
|
-
const testsDir =
|
|
58341
|
-
if (
|
|
58465
|
+
const testsDir = path47.join(workingDir, "tests");
|
|
58466
|
+
if (fs35.existsSync(testsDir)) {
|
|
58342
58467
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58343
58468
|
testLines += lines;
|
|
58344
58469
|
});
|
|
58345
58470
|
}
|
|
58346
58471
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58347
58472
|
for (const dir of possibleTestDirs) {
|
|
58348
|
-
const dirPath =
|
|
58349
|
-
if (
|
|
58473
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58474
|
+
if (fs35.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58350
58475
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58351
58476
|
testLines += lines;
|
|
58352
58477
|
});
|
|
@@ -58358,9 +58483,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58358
58483
|
}
|
|
58359
58484
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
58360
58485
|
try {
|
|
58361
|
-
const entries =
|
|
58486
|
+
const entries = fs35.readdirSync(dirPath, { withFileTypes: true });
|
|
58362
58487
|
for (const entry of entries) {
|
|
58363
|
-
const fullPath =
|
|
58488
|
+
const fullPath = path47.join(dirPath, entry.name);
|
|
58364
58489
|
if (entry.isDirectory()) {
|
|
58365
58490
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58366
58491
|
continue;
|
|
@@ -58368,7 +58493,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58368
58493
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58369
58494
|
} else if (entry.isFile()) {
|
|
58370
58495
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
58371
|
-
const ext =
|
|
58496
|
+
const ext = path47.extname(entry.name).toLowerCase();
|
|
58372
58497
|
const validExts = [
|
|
58373
58498
|
".ts",
|
|
58374
58499
|
".tsx",
|
|
@@ -58404,7 +58529,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58404
58529
|
continue;
|
|
58405
58530
|
}
|
|
58406
58531
|
try {
|
|
58407
|
-
const content =
|
|
58532
|
+
const content = fs35.readFileSync(fullPath, "utf-8");
|
|
58408
58533
|
const lines = countCodeLines(content);
|
|
58409
58534
|
callback(lines);
|
|
58410
58535
|
} catch {}
|
|
@@ -58583,8 +58708,10 @@ async function getGitChurn(days, directory) {
|
|
|
58583
58708
|
stderr: "pipe",
|
|
58584
58709
|
cwd: directory
|
|
58585
58710
|
});
|
|
58586
|
-
const stdout = await
|
|
58587
|
-
|
|
58711
|
+
const [stdout] = await Promise.all([
|
|
58712
|
+
new Response(proc.stdout).text(),
|
|
58713
|
+
proc.exited
|
|
58714
|
+
]);
|
|
58588
58715
|
const lines = stdout.split(/\r?\n/);
|
|
58589
58716
|
for (const line of lines) {
|
|
58590
58717
|
const normalizedPath = line.replace(/\\/g, "/");
|
|
@@ -58603,11 +58730,11 @@ async function getGitChurn(days, directory) {
|
|
|
58603
58730
|
}
|
|
58604
58731
|
function getComplexityForFile2(filePath) {
|
|
58605
58732
|
try {
|
|
58606
|
-
const stat2 =
|
|
58733
|
+
const stat2 = fs36.statSync(filePath);
|
|
58607
58734
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
58608
58735
|
return null;
|
|
58609
58736
|
}
|
|
58610
|
-
const content =
|
|
58737
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58611
58738
|
return estimateCyclomaticComplexity(content);
|
|
58612
58739
|
} catch {
|
|
58613
58740
|
return null;
|
|
@@ -58618,7 +58745,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58618
58745
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
58619
58746
|
const filteredChurn = new Map;
|
|
58620
58747
|
for (const [file3, count] of churnMap) {
|
|
58621
|
-
const ext =
|
|
58748
|
+
const ext = path48.extname(file3).toLowerCase();
|
|
58622
58749
|
if (extSet.has(ext)) {
|
|
58623
58750
|
filteredChurn.set(file3, count);
|
|
58624
58751
|
}
|
|
@@ -58628,8 +58755,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58628
58755
|
let analyzedFiles = 0;
|
|
58629
58756
|
for (const [file3, churnCount] of filteredChurn) {
|
|
58630
58757
|
let fullPath = file3;
|
|
58631
|
-
if (!
|
|
58632
|
-
fullPath =
|
|
58758
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58759
|
+
fullPath = path48.join(cwd, file3);
|
|
58633
58760
|
}
|
|
58634
58761
|
const complexity = getComplexityForFile2(fullPath);
|
|
58635
58762
|
if (complexity !== null) {
|
|
@@ -58837,8 +58964,8 @@ var curator_analyze = createSwarmTool({
|
|
|
58837
58964
|
});
|
|
58838
58965
|
// src/tools/declare-scope.ts
|
|
58839
58966
|
init_tool();
|
|
58840
|
-
import * as
|
|
58841
|
-
import * as
|
|
58967
|
+
import * as fs37 from "fs";
|
|
58968
|
+
import * as path49 from "path";
|
|
58842
58969
|
init_create_tool();
|
|
58843
58970
|
function validateTaskIdFormat(taskId) {
|
|
58844
58971
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -58917,8 +59044,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58917
59044
|
};
|
|
58918
59045
|
}
|
|
58919
59046
|
}
|
|
58920
|
-
normalizedDir =
|
|
58921
|
-
const pathParts = normalizedDir.split(
|
|
59047
|
+
normalizedDir = path49.normalize(args2.working_directory);
|
|
59048
|
+
const pathParts = normalizedDir.split(path49.sep);
|
|
58922
59049
|
if (pathParts.includes("..")) {
|
|
58923
59050
|
return {
|
|
58924
59051
|
success: false,
|
|
@@ -58928,11 +59055,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58928
59055
|
]
|
|
58929
59056
|
};
|
|
58930
59057
|
}
|
|
58931
|
-
const resolvedDir =
|
|
59058
|
+
const resolvedDir = path49.resolve(normalizedDir);
|
|
58932
59059
|
try {
|
|
58933
|
-
const realPath =
|
|
58934
|
-
const planPath2 =
|
|
58935
|
-
if (!
|
|
59060
|
+
const realPath = fs37.realpathSync(resolvedDir);
|
|
59061
|
+
const planPath2 = path49.join(realPath, ".swarm", "plan.json");
|
|
59062
|
+
if (!fs37.existsSync(planPath2)) {
|
|
58936
59063
|
return {
|
|
58937
59064
|
success: false,
|
|
58938
59065
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -58955,8 +59082,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58955
59082
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
58956
59083
|
}
|
|
58957
59084
|
const directory = normalizedDir || fallbackDir;
|
|
58958
|
-
const planPath =
|
|
58959
|
-
if (!
|
|
59085
|
+
const planPath = path49.resolve(directory, ".swarm", "plan.json");
|
|
59086
|
+
if (!fs37.existsSync(planPath)) {
|
|
58960
59087
|
return {
|
|
58961
59088
|
success: false,
|
|
58962
59089
|
message: "No plan found",
|
|
@@ -58965,7 +59092,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58965
59092
|
}
|
|
58966
59093
|
let planContent;
|
|
58967
59094
|
try {
|
|
58968
|
-
planContent = JSON.parse(
|
|
59095
|
+
planContent = JSON.parse(fs37.readFileSync(planPath, "utf-8"));
|
|
58969
59096
|
} catch {
|
|
58970
59097
|
return {
|
|
58971
59098
|
success: false,
|
|
@@ -58997,8 +59124,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58997
59124
|
const normalizeErrors = [];
|
|
58998
59125
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
58999
59126
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
59000
|
-
if (
|
|
59001
|
-
const relativePath =
|
|
59127
|
+
if (path49.isAbsolute(file3)) {
|
|
59128
|
+
const relativePath = path49.relative(dir, file3).replace(/\\/g, "/");
|
|
59002
59129
|
if (relativePath.startsWith("..")) {
|
|
59003
59130
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
59004
59131
|
return file3;
|
|
@@ -59324,20 +59451,20 @@ function validateBase(base) {
|
|
|
59324
59451
|
function validatePaths(paths) {
|
|
59325
59452
|
if (!paths)
|
|
59326
59453
|
return null;
|
|
59327
|
-
for (const
|
|
59328
|
-
if (!
|
|
59454
|
+
for (const path51 of paths) {
|
|
59455
|
+
if (!path51 || path51.length === 0) {
|
|
59329
59456
|
return "empty path not allowed";
|
|
59330
59457
|
}
|
|
59331
|
-
if (
|
|
59458
|
+
if (path51.length > MAX_PATH_LENGTH) {
|
|
59332
59459
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
59333
59460
|
}
|
|
59334
|
-
if (SHELL_METACHARACTERS2.test(
|
|
59461
|
+
if (SHELL_METACHARACTERS2.test(path51)) {
|
|
59335
59462
|
return "path contains shell metacharacters";
|
|
59336
59463
|
}
|
|
59337
|
-
if (
|
|
59464
|
+
if (path51.startsWith("-")) {
|
|
59338
59465
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
59339
59466
|
}
|
|
59340
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
59467
|
+
if (CONTROL_CHAR_PATTERN2.test(path51)) {
|
|
59341
59468
|
return "path contains control characters";
|
|
59342
59469
|
}
|
|
59343
59470
|
}
|
|
@@ -59418,8 +59545,8 @@ var diff = createSwarmTool({
|
|
|
59418
59545
|
if (parts2.length >= 3) {
|
|
59419
59546
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
59420
59547
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
59421
|
-
const
|
|
59422
|
-
files.push({ path:
|
|
59548
|
+
const path51 = parts2[2];
|
|
59549
|
+
files.push({ path: path51, additions, deletions });
|
|
59423
59550
|
}
|
|
59424
59551
|
}
|
|
59425
59552
|
const contractChanges = [];
|
|
@@ -59701,8 +59828,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
59701
59828
|
// src/tools/evidence-check.ts
|
|
59702
59829
|
init_dist();
|
|
59703
59830
|
init_create_tool();
|
|
59704
|
-
import * as
|
|
59705
|
-
import * as
|
|
59831
|
+
import * as fs38 from "fs";
|
|
59832
|
+
import * as path51 from "path";
|
|
59706
59833
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
59707
59834
|
var MAX_EVIDENCE_FILES = 1000;
|
|
59708
59835
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -59729,9 +59856,9 @@ function validateRequiredTypes(input) {
|
|
|
59729
59856
|
return null;
|
|
59730
59857
|
}
|
|
59731
59858
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
59732
|
-
const normalizedCwd =
|
|
59733
|
-
const swarmPath =
|
|
59734
|
-
const normalizedPath =
|
|
59859
|
+
const normalizedCwd = path51.resolve(cwd);
|
|
59860
|
+
const swarmPath = path51.join(normalizedCwd, ".swarm");
|
|
59861
|
+
const normalizedPath = path51.resolve(filePath);
|
|
59735
59862
|
return normalizedPath.startsWith(swarmPath);
|
|
59736
59863
|
}
|
|
59737
59864
|
function parseCompletedTasks(planContent) {
|
|
@@ -59747,12 +59874,12 @@ function parseCompletedTasks(planContent) {
|
|
|
59747
59874
|
}
|
|
59748
59875
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
59749
59876
|
const evidence = [];
|
|
59750
|
-
if (!
|
|
59877
|
+
if (!fs38.existsSync(evidenceDir) || !fs38.statSync(evidenceDir).isDirectory()) {
|
|
59751
59878
|
return evidence;
|
|
59752
59879
|
}
|
|
59753
59880
|
let files;
|
|
59754
59881
|
try {
|
|
59755
|
-
files =
|
|
59882
|
+
files = fs38.readdirSync(evidenceDir);
|
|
59756
59883
|
} catch {
|
|
59757
59884
|
return evidence;
|
|
59758
59885
|
}
|
|
@@ -59761,14 +59888,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59761
59888
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
59762
59889
|
continue;
|
|
59763
59890
|
}
|
|
59764
|
-
const filePath =
|
|
59891
|
+
const filePath = path51.join(evidenceDir, filename);
|
|
59765
59892
|
try {
|
|
59766
|
-
const resolvedPath =
|
|
59767
|
-
const evidenceDirResolved =
|
|
59893
|
+
const resolvedPath = path51.resolve(filePath);
|
|
59894
|
+
const evidenceDirResolved = path51.resolve(evidenceDir);
|
|
59768
59895
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
59769
59896
|
continue;
|
|
59770
59897
|
}
|
|
59771
|
-
const stat2 =
|
|
59898
|
+
const stat2 = fs38.lstatSync(filePath);
|
|
59772
59899
|
if (!stat2.isFile()) {
|
|
59773
59900
|
continue;
|
|
59774
59901
|
}
|
|
@@ -59777,7 +59904,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59777
59904
|
}
|
|
59778
59905
|
let fileStat;
|
|
59779
59906
|
try {
|
|
59780
|
-
fileStat =
|
|
59907
|
+
fileStat = fs38.statSync(filePath);
|
|
59781
59908
|
if (fileStat.size > MAX_FILE_SIZE_BYTES4) {
|
|
59782
59909
|
continue;
|
|
59783
59910
|
}
|
|
@@ -59786,7 +59913,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59786
59913
|
}
|
|
59787
59914
|
let content;
|
|
59788
59915
|
try {
|
|
59789
|
-
content =
|
|
59916
|
+
content = fs38.readFileSync(filePath, "utf-8");
|
|
59790
59917
|
} catch {
|
|
59791
59918
|
continue;
|
|
59792
59919
|
}
|
|
@@ -59882,7 +60009,7 @@ var evidence_check = createSwarmTool({
|
|
|
59882
60009
|
return JSON.stringify(errorResult, null, 2);
|
|
59883
60010
|
}
|
|
59884
60011
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
59885
|
-
const planPath =
|
|
60012
|
+
const planPath = path51.join(cwd, PLAN_FILE);
|
|
59886
60013
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
59887
60014
|
const errorResult = {
|
|
59888
60015
|
error: "plan file path validation failed",
|
|
@@ -59896,7 +60023,7 @@ var evidence_check = createSwarmTool({
|
|
|
59896
60023
|
}
|
|
59897
60024
|
let planContent;
|
|
59898
60025
|
try {
|
|
59899
|
-
planContent =
|
|
60026
|
+
planContent = fs38.readFileSync(planPath, "utf-8");
|
|
59900
60027
|
} catch {
|
|
59901
60028
|
const result2 = {
|
|
59902
60029
|
message: "No completed tasks found in plan.",
|
|
@@ -59914,7 +60041,7 @@ var evidence_check = createSwarmTool({
|
|
|
59914
60041
|
};
|
|
59915
60042
|
return JSON.stringify(result2, null, 2);
|
|
59916
60043
|
}
|
|
59917
|
-
const evidenceDir =
|
|
60044
|
+
const evidenceDir = path51.join(cwd, EVIDENCE_DIR2);
|
|
59918
60045
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
59919
60046
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
59920
60047
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -59931,8 +60058,8 @@ var evidence_check = createSwarmTool({
|
|
|
59931
60058
|
// src/tools/file-extractor.ts
|
|
59932
60059
|
init_tool();
|
|
59933
60060
|
init_create_tool();
|
|
59934
|
-
import * as
|
|
59935
|
-
import * as
|
|
60061
|
+
import * as fs39 from "fs";
|
|
60062
|
+
import * as path52 from "path";
|
|
59936
60063
|
var EXT_MAP = {
|
|
59937
60064
|
python: ".py",
|
|
59938
60065
|
py: ".py",
|
|
@@ -59994,8 +60121,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
59994
60121
|
execute: async (args2, directory) => {
|
|
59995
60122
|
const { content, output_dir, prefix } = args2;
|
|
59996
60123
|
const targetDir = output_dir || directory;
|
|
59997
|
-
if (!
|
|
59998
|
-
|
|
60124
|
+
if (!fs39.existsSync(targetDir)) {
|
|
60125
|
+
fs39.mkdirSync(targetDir, { recursive: true });
|
|
59999
60126
|
}
|
|
60000
60127
|
if (!content) {
|
|
60001
60128
|
return "Error: content is required";
|
|
@@ -60013,16 +60140,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60013
60140
|
if (prefix) {
|
|
60014
60141
|
filename = `${prefix}_${filename}`;
|
|
60015
60142
|
}
|
|
60016
|
-
let filepath =
|
|
60017
|
-
const base =
|
|
60018
|
-
const ext =
|
|
60143
|
+
let filepath = path52.join(targetDir, filename);
|
|
60144
|
+
const base = path52.basename(filepath, path52.extname(filepath));
|
|
60145
|
+
const ext = path52.extname(filepath);
|
|
60019
60146
|
let counter = 1;
|
|
60020
|
-
while (
|
|
60021
|
-
filepath =
|
|
60147
|
+
while (fs39.existsSync(filepath)) {
|
|
60148
|
+
filepath = path52.join(targetDir, `${base}_${counter}${ext}`);
|
|
60022
60149
|
counter++;
|
|
60023
60150
|
}
|
|
60024
60151
|
try {
|
|
60025
|
-
|
|
60152
|
+
fs39.writeFileSync(filepath, code.trim(), "utf-8");
|
|
60026
60153
|
savedFiles.push(filepath);
|
|
60027
60154
|
} catch (error93) {
|
|
60028
60155
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -60052,7 +60179,7 @@ init_create_tool();
|
|
|
60052
60179
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
60053
60180
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
60054
60181
|
var GITINGEST_MAX_RETRIES = 2;
|
|
60055
|
-
var delay = (ms) => new Promise((
|
|
60182
|
+
var delay = (ms) => new Promise((resolve18) => setTimeout(resolve18, ms));
|
|
60056
60183
|
async function fetchGitingest(args2) {
|
|
60057
60184
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
60058
60185
|
try {
|
|
@@ -60138,8 +60265,8 @@ var gitingest = createSwarmTool({
|
|
|
60138
60265
|
// src/tools/imports.ts
|
|
60139
60266
|
init_dist();
|
|
60140
60267
|
init_create_tool();
|
|
60141
|
-
import * as
|
|
60142
|
-
import * as
|
|
60268
|
+
import * as fs40 from "fs";
|
|
60269
|
+
import * as path53 from "path";
|
|
60143
60270
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
60144
60271
|
var MAX_SYMBOL_LENGTH = 256;
|
|
60145
60272
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
@@ -60187,7 +60314,7 @@ function validateSymbolInput(symbol3) {
|
|
|
60187
60314
|
return null;
|
|
60188
60315
|
}
|
|
60189
60316
|
function isBinaryFile2(filePath, buffer) {
|
|
60190
|
-
const ext =
|
|
60317
|
+
const ext = path53.extname(filePath).toLowerCase();
|
|
60191
60318
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
60192
60319
|
return false;
|
|
60193
60320
|
}
|
|
@@ -60211,15 +60338,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60211
60338
|
const imports = [];
|
|
60212
60339
|
let _resolvedTarget;
|
|
60213
60340
|
try {
|
|
60214
|
-
_resolvedTarget =
|
|
60341
|
+
_resolvedTarget = path53.resolve(targetFile);
|
|
60215
60342
|
} catch {
|
|
60216
60343
|
_resolvedTarget = targetFile;
|
|
60217
60344
|
}
|
|
60218
|
-
const targetBasename =
|
|
60345
|
+
const targetBasename = path53.basename(targetFile, path53.extname(targetFile));
|
|
60219
60346
|
const targetWithExt = targetFile;
|
|
60220
60347
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
60221
|
-
const normalizedTargetWithExt =
|
|
60222
|
-
const normalizedTargetWithoutExt =
|
|
60348
|
+
const normalizedTargetWithExt = path53.normalize(targetWithExt).replace(/\\/g, "/");
|
|
60349
|
+
const normalizedTargetWithoutExt = path53.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
60223
60350
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
60224
60351
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
60225
60352
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -60242,9 +60369,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60242
60369
|
}
|
|
60243
60370
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
60244
60371
|
let isMatch = false;
|
|
60245
|
-
const _targetDir =
|
|
60246
|
-
const targetExt =
|
|
60247
|
-
const targetBasenameNoExt =
|
|
60372
|
+
const _targetDir = path53.dirname(targetFile);
|
|
60373
|
+
const targetExt = path53.extname(targetFile);
|
|
60374
|
+
const targetBasenameNoExt = path53.basename(targetFile, targetExt);
|
|
60248
60375
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
60249
60376
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
60250
60377
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -60301,7 +60428,7 @@ var SKIP_DIRECTORIES3 = new Set([
|
|
|
60301
60428
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
60302
60429
|
let entries;
|
|
60303
60430
|
try {
|
|
60304
|
-
entries =
|
|
60431
|
+
entries = fs40.readdirSync(dir);
|
|
60305
60432
|
} catch (e) {
|
|
60306
60433
|
stats.fileErrors.push({
|
|
60307
60434
|
path: dir,
|
|
@@ -60312,13 +60439,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60312
60439
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
60313
60440
|
for (const entry of entries) {
|
|
60314
60441
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
60315
|
-
stats.skippedDirs.push(
|
|
60442
|
+
stats.skippedDirs.push(path53.join(dir, entry));
|
|
60316
60443
|
continue;
|
|
60317
60444
|
}
|
|
60318
|
-
const fullPath =
|
|
60445
|
+
const fullPath = path53.join(dir, entry);
|
|
60319
60446
|
let stat2;
|
|
60320
60447
|
try {
|
|
60321
|
-
stat2 =
|
|
60448
|
+
stat2 = fs40.statSync(fullPath);
|
|
60322
60449
|
} catch (e) {
|
|
60323
60450
|
stats.fileErrors.push({
|
|
60324
60451
|
path: fullPath,
|
|
@@ -60329,7 +60456,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60329
60456
|
if (stat2.isDirectory()) {
|
|
60330
60457
|
findSourceFiles(fullPath, files, stats);
|
|
60331
60458
|
} else if (stat2.isFile()) {
|
|
60332
|
-
const ext =
|
|
60459
|
+
const ext = path53.extname(fullPath).toLowerCase();
|
|
60333
60460
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
60334
60461
|
files.push(fullPath);
|
|
60335
60462
|
}
|
|
@@ -60386,8 +60513,8 @@ var imports = createSwarmTool({
|
|
|
60386
60513
|
return JSON.stringify(errorResult, null, 2);
|
|
60387
60514
|
}
|
|
60388
60515
|
try {
|
|
60389
|
-
const targetFile =
|
|
60390
|
-
if (!
|
|
60516
|
+
const targetFile = path53.resolve(file3);
|
|
60517
|
+
if (!fs40.existsSync(targetFile)) {
|
|
60391
60518
|
const errorResult = {
|
|
60392
60519
|
error: `target file not found: ${file3}`,
|
|
60393
60520
|
target: file3,
|
|
@@ -60397,7 +60524,7 @@ var imports = createSwarmTool({
|
|
|
60397
60524
|
};
|
|
60398
60525
|
return JSON.stringify(errorResult, null, 2);
|
|
60399
60526
|
}
|
|
60400
|
-
const targetStat =
|
|
60527
|
+
const targetStat = fs40.statSync(targetFile);
|
|
60401
60528
|
if (!targetStat.isFile()) {
|
|
60402
60529
|
const errorResult = {
|
|
60403
60530
|
error: "target must be a file, not a directory",
|
|
@@ -60408,7 +60535,7 @@ var imports = createSwarmTool({
|
|
|
60408
60535
|
};
|
|
60409
60536
|
return JSON.stringify(errorResult, null, 2);
|
|
60410
60537
|
}
|
|
60411
|
-
const baseDir =
|
|
60538
|
+
const baseDir = path53.dirname(targetFile);
|
|
60412
60539
|
const scanStats = {
|
|
60413
60540
|
skippedDirs: [],
|
|
60414
60541
|
skippedFiles: 0,
|
|
@@ -60423,12 +60550,12 @@ var imports = createSwarmTool({
|
|
|
60423
60550
|
if (consumers.length >= MAX_CONSUMERS)
|
|
60424
60551
|
break;
|
|
60425
60552
|
try {
|
|
60426
|
-
const stat2 =
|
|
60553
|
+
const stat2 = fs40.statSync(filePath);
|
|
60427
60554
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
60428
60555
|
skippedFileCount++;
|
|
60429
60556
|
continue;
|
|
60430
60557
|
}
|
|
60431
|
-
const buffer =
|
|
60558
|
+
const buffer = fs40.readFileSync(filePath);
|
|
60432
60559
|
if (isBinaryFile2(filePath, buffer)) {
|
|
60433
60560
|
skippedFileCount++;
|
|
60434
60561
|
continue;
|
|
@@ -61017,11 +61144,12 @@ init_dist();
|
|
|
61017
61144
|
init_config();
|
|
61018
61145
|
init_schema();
|
|
61019
61146
|
init_manager();
|
|
61020
|
-
import * as
|
|
61021
|
-
import * as
|
|
61147
|
+
import * as fs41 from "fs";
|
|
61148
|
+
import * as path54 from "path";
|
|
61022
61149
|
init_utils2();
|
|
61023
61150
|
init_telemetry();
|
|
61024
61151
|
init_create_tool();
|
|
61152
|
+
init_resolve_working_directory();
|
|
61025
61153
|
function safeWarn(message, error93) {
|
|
61026
61154
|
try {
|
|
61027
61155
|
console.warn(message, error93 instanceof Error ? error93.message : String(error93));
|
|
@@ -61238,11 +61366,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61238
61366
|
safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
|
|
61239
61367
|
}
|
|
61240
61368
|
try {
|
|
61241
|
-
const driftEvidencePath =
|
|
61369
|
+
const driftEvidencePath = path54.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
61242
61370
|
let driftVerdictFound = false;
|
|
61243
61371
|
let driftVerdictApproved = false;
|
|
61244
61372
|
try {
|
|
61245
|
-
const driftEvidenceContent =
|
|
61373
|
+
const driftEvidenceContent = fs41.readFileSync(driftEvidencePath, "utf-8");
|
|
61246
61374
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
61247
61375
|
const entries = driftEvidence.entries ?? [];
|
|
61248
61376
|
for (const entry of entries) {
|
|
@@ -61272,14 +61400,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61272
61400
|
driftVerdictFound = false;
|
|
61273
61401
|
}
|
|
61274
61402
|
if (!driftVerdictFound) {
|
|
61275
|
-
const specPath =
|
|
61276
|
-
const specExists =
|
|
61403
|
+
const specPath = path54.join(dir, ".swarm", "spec.md");
|
|
61404
|
+
const specExists = fs41.existsSync(specPath);
|
|
61277
61405
|
if (!specExists) {
|
|
61278
61406
|
let incompleteTaskCount = 0;
|
|
61279
61407
|
let planPhaseFound = false;
|
|
61280
61408
|
try {
|
|
61281
61409
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61282
|
-
const planRaw =
|
|
61410
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61283
61411
|
const plan = JSON.parse(planRaw);
|
|
61284
61412
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61285
61413
|
if (targetPhase) {
|
|
@@ -61346,7 +61474,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61346
61474
|
};
|
|
61347
61475
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
61348
61476
|
try {
|
|
61349
|
-
const projectName =
|
|
61477
|
+
const projectName = path54.basename(dir);
|
|
61350
61478
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
61351
61479
|
if (curationResult) {
|
|
61352
61480
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -61391,7 +61519,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61391
61519
|
let phaseRequiredAgents;
|
|
61392
61520
|
try {
|
|
61393
61521
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61394
|
-
const planRaw =
|
|
61522
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61395
61523
|
const plan = JSON.parse(planRaw);
|
|
61396
61524
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61397
61525
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -61406,7 +61534,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61406
61534
|
if (agentsMissing.length > 0) {
|
|
61407
61535
|
try {
|
|
61408
61536
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61409
|
-
const planRaw =
|
|
61537
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61410
61538
|
const plan = JSON.parse(planRaw);
|
|
61411
61539
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61412
61540
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -61437,7 +61565,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61437
61565
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
61438
61566
|
try {
|
|
61439
61567
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61440
|
-
const planRaw =
|
|
61568
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61441
61569
|
const plan = JSON.parse(planRaw);
|
|
61442
61570
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61443
61571
|
if (targetPhase) {
|
|
@@ -61475,7 +61603,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61475
61603
|
};
|
|
61476
61604
|
try {
|
|
61477
61605
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
61478
|
-
|
|
61606
|
+
fs41.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
61479
61607
|
`, "utf-8");
|
|
61480
61608
|
} catch (writeError) {
|
|
61481
61609
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -61499,12 +61627,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61499
61627
|
}
|
|
61500
61628
|
try {
|
|
61501
61629
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61502
|
-
const planJson =
|
|
61630
|
+
const planJson = fs41.readFileSync(planPath, "utf-8");
|
|
61503
61631
|
const plan = JSON.parse(planJson);
|
|
61504
61632
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61505
61633
|
if (phaseObj) {
|
|
61506
61634
|
phaseObj.status = "completed";
|
|
61507
|
-
|
|
61635
|
+
fs41.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
61508
61636
|
`, "utf-8");
|
|
61509
61637
|
}
|
|
61510
61638
|
} catch (error93) {
|
|
@@ -61531,16 +61659,19 @@ var phase_complete = createSwarmTool({
|
|
|
61531
61659
|
args: {
|
|
61532
61660
|
phase: tool.schema.number().int().min(1).describe("The phase number being completed \u2014 a positive integer (e.g., 1, 2, 3)"),
|
|
61533
61661
|
summary: tool.schema.string().optional().describe("Optional summary of what was accomplished in this phase"),
|
|
61534
|
-
sessionID: tool.schema.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)")
|
|
61662
|
+
sessionID: tool.schema.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),
|
|
61663
|
+
working_directory: tool.schema.string().optional().describe("Explicit project root directory. When provided, .swarm/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
61535
61664
|
},
|
|
61536
61665
|
execute: async (args2, directory, ctx) => {
|
|
61537
61666
|
let phaseCompleteArgs;
|
|
61667
|
+
let workingDirInput;
|
|
61538
61668
|
try {
|
|
61539
61669
|
phaseCompleteArgs = {
|
|
61540
61670
|
phase: Number(args2.phase),
|
|
61541
61671
|
summary: args2.summary !== undefined ? String(args2.summary) : undefined,
|
|
61542
61672
|
sessionID: ctx?.sessionID ?? (args2.sessionID !== undefined ? String(args2.sessionID) : undefined)
|
|
61543
61673
|
};
|
|
61674
|
+
workingDirInput = args2.working_directory !== undefined ? String(args2.working_directory) : undefined;
|
|
61544
61675
|
} catch {
|
|
61545
61676
|
return JSON.stringify({
|
|
61546
61677
|
success: false,
|
|
@@ -61550,7 +61681,17 @@ var phase_complete = createSwarmTool({
|
|
|
61550
61681
|
warnings: ["Failed to parse arguments"]
|
|
61551
61682
|
}, null, 2);
|
|
61552
61683
|
}
|
|
61553
|
-
|
|
61684
|
+
const dirResult = resolveWorkingDirectory(workingDirInput, directory);
|
|
61685
|
+
if (!dirResult.success) {
|
|
61686
|
+
return JSON.stringify({
|
|
61687
|
+
success: false,
|
|
61688
|
+
phase: phaseCompleteArgs.phase,
|
|
61689
|
+
message: dirResult.message,
|
|
61690
|
+
agentsDispatched: [],
|
|
61691
|
+
warnings: [dirResult.message]
|
|
61692
|
+
}, null, 2);
|
|
61693
|
+
}
|
|
61694
|
+
return executePhaseComplete(phaseCompleteArgs, dirResult.directory, dirResult.directory);
|
|
61554
61695
|
}
|
|
61555
61696
|
});
|
|
61556
61697
|
// src/tools/pkg-audit.ts
|
|
@@ -61558,8 +61699,8 @@ init_dist();
|
|
|
61558
61699
|
init_discovery();
|
|
61559
61700
|
init_utils();
|
|
61560
61701
|
init_create_tool();
|
|
61561
|
-
import * as
|
|
61562
|
-
import * as
|
|
61702
|
+
import * as fs42 from "fs";
|
|
61703
|
+
import * as path55 from "path";
|
|
61563
61704
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
61564
61705
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
61565
61706
|
function isValidEcosystem(value) {
|
|
@@ -61577,28 +61718,28 @@ function validateArgs3(args2) {
|
|
|
61577
61718
|
function detectEcosystems(directory) {
|
|
61578
61719
|
const ecosystems = [];
|
|
61579
61720
|
const cwd = directory;
|
|
61580
|
-
if (
|
|
61721
|
+
if (fs42.existsSync(path55.join(cwd, "package.json"))) {
|
|
61581
61722
|
ecosystems.push("npm");
|
|
61582
61723
|
}
|
|
61583
|
-
if (
|
|
61724
|
+
if (fs42.existsSync(path55.join(cwd, "pyproject.toml")) || fs42.existsSync(path55.join(cwd, "requirements.txt"))) {
|
|
61584
61725
|
ecosystems.push("pip");
|
|
61585
61726
|
}
|
|
61586
|
-
if (
|
|
61727
|
+
if (fs42.existsSync(path55.join(cwd, "Cargo.toml"))) {
|
|
61587
61728
|
ecosystems.push("cargo");
|
|
61588
61729
|
}
|
|
61589
|
-
if (
|
|
61730
|
+
if (fs42.existsSync(path55.join(cwd, "go.mod"))) {
|
|
61590
61731
|
ecosystems.push("go");
|
|
61591
61732
|
}
|
|
61592
61733
|
try {
|
|
61593
|
-
const files =
|
|
61734
|
+
const files = fs42.readdirSync(cwd);
|
|
61594
61735
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
61595
61736
|
ecosystems.push("dotnet");
|
|
61596
61737
|
}
|
|
61597
61738
|
} catch {}
|
|
61598
|
-
if (
|
|
61739
|
+
if (fs42.existsSync(path55.join(cwd, "Gemfile")) || fs42.existsSync(path55.join(cwd, "Gemfile.lock"))) {
|
|
61599
61740
|
ecosystems.push("ruby");
|
|
61600
61741
|
}
|
|
61601
|
-
if (
|
|
61742
|
+
if (fs42.existsSync(path55.join(cwd, "pubspec.yaml"))) {
|
|
61602
61743
|
ecosystems.push("dart");
|
|
61603
61744
|
}
|
|
61604
61745
|
return ecosystems;
|
|
@@ -61611,7 +61752,7 @@ async function runNpmAudit(directory) {
|
|
|
61611
61752
|
stderr: "pipe",
|
|
61612
61753
|
cwd: directory
|
|
61613
61754
|
});
|
|
61614
|
-
const timeoutPromise = new Promise((
|
|
61755
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61615
61756
|
const result = await Promise.race([
|
|
61616
61757
|
Promise.all([
|
|
61617
61758
|
new Response(proc.stdout).text(),
|
|
@@ -61734,7 +61875,7 @@ async function runPipAudit(directory) {
|
|
|
61734
61875
|
stderr: "pipe",
|
|
61735
61876
|
cwd: directory
|
|
61736
61877
|
});
|
|
61737
|
-
const timeoutPromise = new Promise((
|
|
61878
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61738
61879
|
const result = await Promise.race([
|
|
61739
61880
|
Promise.all([
|
|
61740
61881
|
new Response(proc.stdout).text(),
|
|
@@ -61865,7 +62006,7 @@ async function runCargoAudit(directory) {
|
|
|
61865
62006
|
stderr: "pipe",
|
|
61866
62007
|
cwd: directory
|
|
61867
62008
|
});
|
|
61868
|
-
const timeoutPromise = new Promise((
|
|
62009
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61869
62010
|
const result = await Promise.race([
|
|
61870
62011
|
Promise.all([
|
|
61871
62012
|
new Response(proc.stdout).text(),
|
|
@@ -61992,7 +62133,7 @@ async function runGoAudit(directory) {
|
|
|
61992
62133
|
stderr: "pipe",
|
|
61993
62134
|
cwd: directory
|
|
61994
62135
|
});
|
|
61995
|
-
const timeoutPromise = new Promise((
|
|
62136
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61996
62137
|
const result = await Promise.race([
|
|
61997
62138
|
Promise.all([
|
|
61998
62139
|
new Response(proc.stdout).text(),
|
|
@@ -62128,7 +62269,7 @@ async function runDotnetAudit(directory) {
|
|
|
62128
62269
|
stderr: "pipe",
|
|
62129
62270
|
cwd: directory
|
|
62130
62271
|
});
|
|
62131
|
-
const timeoutPromise = new Promise((
|
|
62272
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
62132
62273
|
const result = await Promise.race([
|
|
62133
62274
|
Promise.all([
|
|
62134
62275
|
new Response(proc.stdout).text(),
|
|
@@ -62247,7 +62388,7 @@ async function runBundleAudit(directory) {
|
|
|
62247
62388
|
stderr: "pipe",
|
|
62248
62389
|
cwd: directory
|
|
62249
62390
|
});
|
|
62250
|
-
const timeoutPromise = new Promise((
|
|
62391
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
62251
62392
|
const result = await Promise.race([
|
|
62252
62393
|
Promise.all([
|
|
62253
62394
|
new Response(proc.stdout).text(),
|
|
@@ -62394,7 +62535,7 @@ async function runDartAudit(directory) {
|
|
|
62394
62535
|
stderr: "pipe",
|
|
62395
62536
|
cwd: directory
|
|
62396
62537
|
});
|
|
62397
|
-
const timeoutPromise = new Promise((
|
|
62538
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
62398
62539
|
const result = await Promise.race([
|
|
62399
62540
|
Promise.all([
|
|
62400
62541
|
new Response(proc.stdout).text(),
|
|
@@ -62619,8 +62760,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
62619
62760
|
]);
|
|
62620
62761
|
// src/tools/pre-check-batch.ts
|
|
62621
62762
|
init_dist();
|
|
62622
|
-
import * as
|
|
62623
|
-
import * as
|
|
62763
|
+
import * as fs44 from "fs";
|
|
62764
|
+
import * as path57 from "path";
|
|
62624
62765
|
|
|
62625
62766
|
// node_modules/yocto-queue/index.js
|
|
62626
62767
|
class Node2 {
|
|
@@ -62711,26 +62852,26 @@ function pLimit(concurrency) {
|
|
|
62711
62852
|
activeCount--;
|
|
62712
62853
|
resumeNext();
|
|
62713
62854
|
};
|
|
62714
|
-
const run2 = async (function_,
|
|
62855
|
+
const run2 = async (function_, resolve19, arguments_2) => {
|
|
62715
62856
|
const result = (async () => function_(...arguments_2))();
|
|
62716
|
-
|
|
62857
|
+
resolve19(result);
|
|
62717
62858
|
try {
|
|
62718
62859
|
await result;
|
|
62719
62860
|
} catch {}
|
|
62720
62861
|
next();
|
|
62721
62862
|
};
|
|
62722
|
-
const enqueue = (function_,
|
|
62863
|
+
const enqueue = (function_, resolve19, reject, arguments_2) => {
|
|
62723
62864
|
const queueItem = { reject };
|
|
62724
62865
|
new Promise((internalResolve) => {
|
|
62725
62866
|
queueItem.run = internalResolve;
|
|
62726
62867
|
queue.enqueue(queueItem);
|
|
62727
|
-
}).then(run2.bind(undefined, function_,
|
|
62868
|
+
}).then(run2.bind(undefined, function_, resolve19, arguments_2));
|
|
62728
62869
|
if (activeCount < concurrency) {
|
|
62729
62870
|
resumeNext();
|
|
62730
62871
|
}
|
|
62731
62872
|
};
|
|
62732
|
-
const generator = (function_, ...arguments_2) => new Promise((
|
|
62733
|
-
enqueue(function_,
|
|
62873
|
+
const generator = (function_, ...arguments_2) => new Promise((resolve19, reject) => {
|
|
62874
|
+
enqueue(function_, resolve19, reject, arguments_2);
|
|
62734
62875
|
});
|
|
62735
62876
|
Object.defineProperties(generator, {
|
|
62736
62877
|
activeCount: {
|
|
@@ -62894,8 +63035,8 @@ async function qualityBudget(input, directory) {
|
|
|
62894
63035
|
init_dist();
|
|
62895
63036
|
init_manager();
|
|
62896
63037
|
init_detector();
|
|
62897
|
-
import * as
|
|
62898
|
-
import * as
|
|
63038
|
+
import * as fs43 from "fs";
|
|
63039
|
+
import * as path56 from "path";
|
|
62899
63040
|
import { extname as extname10 } from "path";
|
|
62900
63041
|
|
|
62901
63042
|
// src/sast/rules/c.ts
|
|
@@ -63646,7 +63787,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
63646
63787
|
}
|
|
63647
63788
|
}
|
|
63648
63789
|
async function executeWithTimeout(command, args2, options) {
|
|
63649
|
-
return new Promise((
|
|
63790
|
+
return new Promise((resolve19) => {
|
|
63650
63791
|
const child = spawn2(command, args2, {
|
|
63651
63792
|
shell: false,
|
|
63652
63793
|
cwd: options.cwd
|
|
@@ -63655,7 +63796,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
63655
63796
|
let stderr = "";
|
|
63656
63797
|
const timeout = setTimeout(() => {
|
|
63657
63798
|
child.kill("SIGTERM");
|
|
63658
|
-
|
|
63799
|
+
resolve19({
|
|
63659
63800
|
stdout,
|
|
63660
63801
|
stderr: "Process timed out",
|
|
63661
63802
|
exitCode: 124
|
|
@@ -63669,7 +63810,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
63669
63810
|
});
|
|
63670
63811
|
child.on("close", (code) => {
|
|
63671
63812
|
clearTimeout(timeout);
|
|
63672
|
-
|
|
63813
|
+
resolve19({
|
|
63673
63814
|
stdout,
|
|
63674
63815
|
stderr,
|
|
63675
63816
|
exitCode: code ?? 0
|
|
@@ -63677,7 +63818,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
63677
63818
|
});
|
|
63678
63819
|
child.on("error", (err2) => {
|
|
63679
63820
|
clearTimeout(timeout);
|
|
63680
|
-
|
|
63821
|
+
resolve19({
|
|
63681
63822
|
stdout,
|
|
63682
63823
|
stderr: err2.message,
|
|
63683
63824
|
exitCode: 1
|
|
@@ -63765,17 +63906,17 @@ var SEVERITY_ORDER = {
|
|
|
63765
63906
|
};
|
|
63766
63907
|
function shouldSkipFile(filePath) {
|
|
63767
63908
|
try {
|
|
63768
|
-
const stats =
|
|
63909
|
+
const stats = fs43.statSync(filePath);
|
|
63769
63910
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
63770
63911
|
return { skip: true, reason: "file too large" };
|
|
63771
63912
|
}
|
|
63772
63913
|
if (stats.size === 0) {
|
|
63773
63914
|
return { skip: true, reason: "empty file" };
|
|
63774
63915
|
}
|
|
63775
|
-
const fd =
|
|
63916
|
+
const fd = fs43.openSync(filePath, "r");
|
|
63776
63917
|
const buffer = Buffer.alloc(8192);
|
|
63777
|
-
const bytesRead =
|
|
63778
|
-
|
|
63918
|
+
const bytesRead = fs43.readSync(fd, buffer, 0, 8192, 0);
|
|
63919
|
+
fs43.closeSync(fd);
|
|
63779
63920
|
if (bytesRead > 0) {
|
|
63780
63921
|
let nullCount = 0;
|
|
63781
63922
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -63814,7 +63955,7 @@ function countBySeverity(findings) {
|
|
|
63814
63955
|
}
|
|
63815
63956
|
function scanFileWithTierA(filePath, language) {
|
|
63816
63957
|
try {
|
|
63817
|
-
const content =
|
|
63958
|
+
const content = fs43.readFileSync(filePath, "utf-8");
|
|
63818
63959
|
const findings = executeRulesSync(filePath, content, language);
|
|
63819
63960
|
return findings.map((f) => ({
|
|
63820
63961
|
rule_id: f.rule_id,
|
|
@@ -63861,8 +64002,8 @@ async function sastScan(input, directory, config3) {
|
|
|
63861
64002
|
_filesSkipped++;
|
|
63862
64003
|
continue;
|
|
63863
64004
|
}
|
|
63864
|
-
const resolvedPath =
|
|
63865
|
-
if (!
|
|
64005
|
+
const resolvedPath = path56.isAbsolute(filePath) ? filePath : path56.resolve(directory, filePath);
|
|
64006
|
+
if (!fs43.existsSync(resolvedPath)) {
|
|
63866
64007
|
_filesSkipped++;
|
|
63867
64008
|
continue;
|
|
63868
64009
|
}
|
|
@@ -64060,18 +64201,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
64060
64201
|
let resolved;
|
|
64061
64202
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
64062
64203
|
if (isWinAbs) {
|
|
64063
|
-
resolved =
|
|
64064
|
-
} else if (
|
|
64065
|
-
resolved =
|
|
64204
|
+
resolved = path57.win32.resolve(inputPath);
|
|
64205
|
+
} else if (path57.isAbsolute(inputPath)) {
|
|
64206
|
+
resolved = path57.resolve(inputPath);
|
|
64066
64207
|
} else {
|
|
64067
|
-
resolved =
|
|
64208
|
+
resolved = path57.resolve(baseDir, inputPath);
|
|
64068
64209
|
}
|
|
64069
|
-
const workspaceResolved =
|
|
64210
|
+
const workspaceResolved = path57.resolve(workspaceDir);
|
|
64070
64211
|
let relative8;
|
|
64071
64212
|
if (isWinAbs) {
|
|
64072
|
-
relative8 =
|
|
64213
|
+
relative8 = path57.win32.relative(workspaceResolved, resolved);
|
|
64073
64214
|
} else {
|
|
64074
|
-
relative8 =
|
|
64215
|
+
relative8 = path57.relative(workspaceResolved, resolved);
|
|
64075
64216
|
}
|
|
64076
64217
|
if (relative8.startsWith("..")) {
|
|
64077
64218
|
return "path traversal detected";
|
|
@@ -64132,13 +64273,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
64132
64273
|
}
|
|
64133
64274
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
64134
64275
|
const isWindows = process.platform === "win32";
|
|
64135
|
-
const binDir =
|
|
64276
|
+
const binDir = path57.join(workspaceDir, "node_modules", ".bin");
|
|
64136
64277
|
const validatedFiles = [];
|
|
64137
64278
|
for (const file3 of files) {
|
|
64138
64279
|
if (typeof file3 !== "string") {
|
|
64139
64280
|
continue;
|
|
64140
64281
|
}
|
|
64141
|
-
const resolvedPath =
|
|
64282
|
+
const resolvedPath = path57.resolve(file3);
|
|
64142
64283
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
64143
64284
|
if (validationError) {
|
|
64144
64285
|
continue;
|
|
@@ -64156,10 +64297,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
64156
64297
|
}
|
|
64157
64298
|
let command;
|
|
64158
64299
|
if (linter === "biome") {
|
|
64159
|
-
const biomeBin = isWindows ?
|
|
64300
|
+
const biomeBin = isWindows ? path57.join(binDir, "biome.EXE") : path57.join(binDir, "biome");
|
|
64160
64301
|
command = [biomeBin, "check", ...validatedFiles];
|
|
64161
64302
|
} else {
|
|
64162
|
-
const eslintBin = isWindows ?
|
|
64303
|
+
const eslintBin = isWindows ? path57.join(binDir, "eslint.cmd") : path57.join(binDir, "eslint");
|
|
64163
64304
|
command = [eslintBin, ...validatedFiles];
|
|
64164
64305
|
}
|
|
64165
64306
|
try {
|
|
@@ -64296,7 +64437,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64296
64437
|
skippedFiles++;
|
|
64297
64438
|
continue;
|
|
64298
64439
|
}
|
|
64299
|
-
const resolvedPath =
|
|
64440
|
+
const resolvedPath = path57.resolve(file3);
|
|
64300
64441
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
64301
64442
|
if (validationError) {
|
|
64302
64443
|
skippedFiles++;
|
|
@@ -64314,14 +64455,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64314
64455
|
};
|
|
64315
64456
|
}
|
|
64316
64457
|
for (const file3 of validatedFiles) {
|
|
64317
|
-
const ext =
|
|
64458
|
+
const ext = path57.extname(file3).toLowerCase();
|
|
64318
64459
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
64319
64460
|
skippedFiles++;
|
|
64320
64461
|
continue;
|
|
64321
64462
|
}
|
|
64322
64463
|
let stat2;
|
|
64323
64464
|
try {
|
|
64324
|
-
stat2 =
|
|
64465
|
+
stat2 = fs44.statSync(file3);
|
|
64325
64466
|
} catch {
|
|
64326
64467
|
skippedFiles++;
|
|
64327
64468
|
continue;
|
|
@@ -64332,7 +64473,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64332
64473
|
}
|
|
64333
64474
|
let content;
|
|
64334
64475
|
try {
|
|
64335
|
-
const buffer =
|
|
64476
|
+
const buffer = fs44.readFileSync(file3);
|
|
64336
64477
|
if (buffer.includes(0)) {
|
|
64337
64478
|
skippedFiles++;
|
|
64338
64479
|
continue;
|
|
@@ -64520,7 +64661,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
64520
64661
|
const preexistingFindings = [];
|
|
64521
64662
|
for (const finding of findings) {
|
|
64522
64663
|
const filePath = finding.location.file;
|
|
64523
|
-
const normalised =
|
|
64664
|
+
const normalised = path57.relative(directory, filePath).replace(/\\/g, "/");
|
|
64524
64665
|
const changedLines = changedLineRanges.get(normalised);
|
|
64525
64666
|
if (changedLines && changedLines.has(finding.location.line)) {
|
|
64526
64667
|
newFindings.push(finding);
|
|
@@ -64571,7 +64712,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
64571
64712
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
64572
64713
|
continue;
|
|
64573
64714
|
}
|
|
64574
|
-
changedFiles.push(
|
|
64715
|
+
changedFiles.push(path57.resolve(directory, file3));
|
|
64575
64716
|
}
|
|
64576
64717
|
if (changedFiles.length === 0) {
|
|
64577
64718
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -64759,7 +64900,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
64759
64900
|
};
|
|
64760
64901
|
return JSON.stringify(errorResult, null, 2);
|
|
64761
64902
|
}
|
|
64762
|
-
const resolvedDirectory =
|
|
64903
|
+
const resolvedDirectory = path57.resolve(typedArgs.directory);
|
|
64763
64904
|
const workspaceAnchor = resolvedDirectory;
|
|
64764
64905
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
64765
64906
|
if (dirError) {
|
|
@@ -64865,38 +65006,38 @@ ${paginatedContent}`;
|
|
|
64865
65006
|
});
|
|
64866
65007
|
// src/tools/save-plan.ts
|
|
64867
65008
|
init_tool();
|
|
64868
|
-
import * as
|
|
64869
|
-
import * as
|
|
65009
|
+
import * as fs46 from "fs";
|
|
65010
|
+
import * as path59 from "path";
|
|
64870
65011
|
|
|
64871
65012
|
// src/parallel/file-locks.ts
|
|
64872
|
-
import * as
|
|
64873
|
-
import * as
|
|
65013
|
+
import * as fs45 from "fs";
|
|
65014
|
+
import * as path58 from "path";
|
|
64874
65015
|
var LOCKS_DIR = ".swarm/locks";
|
|
64875
65016
|
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
64876
65017
|
function getLockFilePath(directory, filePath) {
|
|
64877
|
-
const normalized =
|
|
64878
|
-
if (!normalized.startsWith(
|
|
65018
|
+
const normalized = path58.resolve(directory, filePath);
|
|
65019
|
+
if (!normalized.startsWith(path58.resolve(directory))) {
|
|
64879
65020
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
64880
65021
|
}
|
|
64881
65022
|
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
64882
|
-
return
|
|
65023
|
+
return path58.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
64883
65024
|
}
|
|
64884
65025
|
function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
64885
65026
|
const lockPath = getLockFilePath(directory, filePath);
|
|
64886
|
-
const locksDir =
|
|
64887
|
-
if (!
|
|
64888
|
-
|
|
65027
|
+
const locksDir = path58.dirname(lockPath);
|
|
65028
|
+
if (!fs45.existsSync(locksDir)) {
|
|
65029
|
+
fs45.mkdirSync(locksDir, { recursive: true });
|
|
64889
65030
|
}
|
|
64890
|
-
if (
|
|
65031
|
+
if (fs45.existsSync(lockPath)) {
|
|
64891
65032
|
try {
|
|
64892
|
-
const existingLock = JSON.parse(
|
|
65033
|
+
const existingLock = JSON.parse(fs45.readFileSync(lockPath, "utf-8"));
|
|
64893
65034
|
if (Date.now() > existingLock.expiresAt) {
|
|
64894
|
-
|
|
65035
|
+
fs45.unlinkSync(lockPath);
|
|
64895
65036
|
} else {
|
|
64896
65037
|
return { acquired: false, existing: existingLock };
|
|
64897
65038
|
}
|
|
64898
65039
|
} catch {
|
|
64899
|
-
|
|
65040
|
+
fs45.unlinkSync(lockPath);
|
|
64900
65041
|
}
|
|
64901
65042
|
}
|
|
64902
65043
|
const lock = {
|
|
@@ -64907,24 +65048,24 @@ function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
|
64907
65048
|
expiresAt: Date.now() + LOCK_TIMEOUT_MS
|
|
64908
65049
|
};
|
|
64909
65050
|
const tempPath = `${lockPath}.tmp`;
|
|
64910
|
-
|
|
64911
|
-
|
|
65051
|
+
fs45.writeFileSync(tempPath, JSON.stringify(lock, null, 2), "utf-8");
|
|
65052
|
+
fs45.renameSync(tempPath, lockPath);
|
|
64912
65053
|
return { acquired: true, lock };
|
|
64913
65054
|
}
|
|
64914
65055
|
function releaseLock(directory, filePath, taskId) {
|
|
64915
65056
|
const lockPath = getLockFilePath(directory, filePath);
|
|
64916
|
-
if (!
|
|
65057
|
+
if (!fs45.existsSync(lockPath)) {
|
|
64917
65058
|
return true;
|
|
64918
65059
|
}
|
|
64919
65060
|
try {
|
|
64920
|
-
const lock = JSON.parse(
|
|
65061
|
+
const lock = JSON.parse(fs45.readFileSync(lockPath, "utf-8"));
|
|
64921
65062
|
if (lock.taskId === taskId) {
|
|
64922
|
-
|
|
65063
|
+
fs45.unlinkSync(lockPath);
|
|
64923
65064
|
return true;
|
|
64924
65065
|
}
|
|
64925
65066
|
return false;
|
|
64926
65067
|
} catch {
|
|
64927
|
-
|
|
65068
|
+
fs45.unlinkSync(lockPath);
|
|
64928
65069
|
return true;
|
|
64929
65070
|
}
|
|
64930
65071
|
}
|
|
@@ -65049,14 +65190,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65049
65190
|
try {
|
|
65050
65191
|
await savePlan(dir, plan);
|
|
65051
65192
|
try {
|
|
65052
|
-
const markerPath =
|
|
65193
|
+
const markerPath = path59.join(dir, ".swarm", ".plan-write-marker");
|
|
65053
65194
|
const marker = JSON.stringify({
|
|
65054
65195
|
source: "save_plan",
|
|
65055
65196
|
timestamp: new Date().toISOString(),
|
|
65056
65197
|
phases_count: plan.phases.length,
|
|
65057
65198
|
tasks_count: tasksCount
|
|
65058
65199
|
});
|
|
65059
|
-
await
|
|
65200
|
+
await fs46.promises.writeFile(markerPath, marker, "utf8");
|
|
65060
65201
|
} catch {}
|
|
65061
65202
|
const warnings = [];
|
|
65062
65203
|
let criticReviewFound = false;
|
|
@@ -65072,7 +65213,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65072
65213
|
return {
|
|
65073
65214
|
success: true,
|
|
65074
65215
|
message: "Plan saved successfully",
|
|
65075
|
-
plan_path:
|
|
65216
|
+
plan_path: path59.join(dir, ".swarm", "plan.json"),
|
|
65076
65217
|
phases_count: plan.phases.length,
|
|
65077
65218
|
tasks_count: tasksCount,
|
|
65078
65219
|
...warnings.length > 0 ? { warnings } : {}
|
|
@@ -65114,8 +65255,8 @@ var save_plan = createSwarmTool({
|
|
|
65114
65255
|
// src/tools/sbom-generate.ts
|
|
65115
65256
|
init_dist();
|
|
65116
65257
|
init_manager();
|
|
65117
|
-
import * as
|
|
65118
|
-
import * as
|
|
65258
|
+
import * as fs47 from "fs";
|
|
65259
|
+
import * as path60 from "path";
|
|
65119
65260
|
|
|
65120
65261
|
// src/sbom/detectors/index.ts
|
|
65121
65262
|
init_utils();
|
|
@@ -65963,9 +66104,9 @@ function findManifestFiles(rootDir) {
|
|
|
65963
66104
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
65964
66105
|
function searchDir(dir) {
|
|
65965
66106
|
try {
|
|
65966
|
-
const entries =
|
|
66107
|
+
const entries = fs47.readdirSync(dir, { withFileTypes: true });
|
|
65967
66108
|
for (const entry of entries) {
|
|
65968
|
-
const fullPath =
|
|
66109
|
+
const fullPath = path60.join(dir, entry.name);
|
|
65969
66110
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
65970
66111
|
continue;
|
|
65971
66112
|
}
|
|
@@ -65974,7 +66115,7 @@ function findManifestFiles(rootDir) {
|
|
|
65974
66115
|
} else if (entry.isFile()) {
|
|
65975
66116
|
for (const pattern of patterns) {
|
|
65976
66117
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
65977
|
-
manifestFiles.push(
|
|
66118
|
+
manifestFiles.push(path60.relative(rootDir, fullPath));
|
|
65978
66119
|
break;
|
|
65979
66120
|
}
|
|
65980
66121
|
}
|
|
@@ -65990,13 +66131,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
65990
66131
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
65991
66132
|
for (const dir of directories) {
|
|
65992
66133
|
try {
|
|
65993
|
-
const entries =
|
|
66134
|
+
const entries = fs47.readdirSync(dir, { withFileTypes: true });
|
|
65994
66135
|
for (const entry of entries) {
|
|
65995
|
-
const fullPath =
|
|
66136
|
+
const fullPath = path60.join(dir, entry.name);
|
|
65996
66137
|
if (entry.isFile()) {
|
|
65997
66138
|
for (const pattern of patterns) {
|
|
65998
66139
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
65999
|
-
found.push(
|
|
66140
|
+
found.push(path60.relative(workingDir, fullPath));
|
|
66000
66141
|
break;
|
|
66001
66142
|
}
|
|
66002
66143
|
}
|
|
@@ -66009,11 +66150,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66009
66150
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
66010
66151
|
const dirs = new Set;
|
|
66011
66152
|
for (const file3 of changedFiles) {
|
|
66012
|
-
let currentDir =
|
|
66153
|
+
let currentDir = path60.dirname(file3);
|
|
66013
66154
|
while (true) {
|
|
66014
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
66015
|
-
dirs.add(
|
|
66016
|
-
const parent =
|
|
66155
|
+
if (currentDir && currentDir !== "." && currentDir !== path60.sep) {
|
|
66156
|
+
dirs.add(path60.join(workingDir, currentDir));
|
|
66157
|
+
const parent = path60.dirname(currentDir);
|
|
66017
66158
|
if (parent === currentDir)
|
|
66018
66159
|
break;
|
|
66019
66160
|
currentDir = parent;
|
|
@@ -66027,7 +66168,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
66027
66168
|
}
|
|
66028
66169
|
function ensureOutputDir(outputDir) {
|
|
66029
66170
|
try {
|
|
66030
|
-
|
|
66171
|
+
fs47.mkdirSync(outputDir, { recursive: true });
|
|
66031
66172
|
} catch (error93) {
|
|
66032
66173
|
if (!error93 || error93.code !== "EEXIST") {
|
|
66033
66174
|
throw error93;
|
|
@@ -66097,7 +66238,7 @@ var sbom_generate = createSwarmTool({
|
|
|
66097
66238
|
const changedFiles = obj.changed_files;
|
|
66098
66239
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
66099
66240
|
const workingDir = directory;
|
|
66100
|
-
const outputDir =
|
|
66241
|
+
const outputDir = path60.isAbsolute(relativeOutputDir) ? relativeOutputDir : path60.join(workingDir, relativeOutputDir);
|
|
66101
66242
|
let manifestFiles = [];
|
|
66102
66243
|
if (scope === "all") {
|
|
66103
66244
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -66120,11 +66261,11 @@ var sbom_generate = createSwarmTool({
|
|
|
66120
66261
|
const processedFiles = [];
|
|
66121
66262
|
for (const manifestFile of manifestFiles) {
|
|
66122
66263
|
try {
|
|
66123
|
-
const fullPath =
|
|
66124
|
-
if (!
|
|
66264
|
+
const fullPath = path60.isAbsolute(manifestFile) ? manifestFile : path60.join(workingDir, manifestFile);
|
|
66265
|
+
if (!fs47.existsSync(fullPath)) {
|
|
66125
66266
|
continue;
|
|
66126
66267
|
}
|
|
66127
|
-
const content =
|
|
66268
|
+
const content = fs47.readFileSync(fullPath, "utf-8");
|
|
66128
66269
|
const components = detectComponents(manifestFile, content);
|
|
66129
66270
|
processedFiles.push(manifestFile);
|
|
66130
66271
|
if (components.length > 0) {
|
|
@@ -66137,8 +66278,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66137
66278
|
const bom = generateCycloneDX(allComponents);
|
|
66138
66279
|
const bomJson = serializeCycloneDX(bom);
|
|
66139
66280
|
const filename = generateSbomFilename();
|
|
66140
|
-
const outputPath =
|
|
66141
|
-
|
|
66281
|
+
const outputPath = path60.join(outputDir, filename);
|
|
66282
|
+
fs47.writeFileSync(outputPath, bomJson, "utf-8");
|
|
66142
66283
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
66143
66284
|
try {
|
|
66144
66285
|
const timestamp = new Date().toISOString();
|
|
@@ -66180,8 +66321,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66180
66321
|
// src/tools/schema-drift.ts
|
|
66181
66322
|
init_dist();
|
|
66182
66323
|
init_create_tool();
|
|
66183
|
-
import * as
|
|
66184
|
-
import * as
|
|
66324
|
+
import * as fs48 from "fs";
|
|
66325
|
+
import * as path61 from "path";
|
|
66185
66326
|
var SPEC_CANDIDATES = [
|
|
66186
66327
|
"openapi.json",
|
|
66187
66328
|
"openapi.yaml",
|
|
@@ -66213,28 +66354,28 @@ function normalizePath2(p) {
|
|
|
66213
66354
|
}
|
|
66214
66355
|
function discoverSpecFile(cwd, specFileArg) {
|
|
66215
66356
|
if (specFileArg) {
|
|
66216
|
-
const resolvedPath =
|
|
66217
|
-
const normalizedCwd = cwd.endsWith(
|
|
66357
|
+
const resolvedPath = path61.resolve(cwd, specFileArg);
|
|
66358
|
+
const normalizedCwd = cwd.endsWith(path61.sep) ? cwd : cwd + path61.sep;
|
|
66218
66359
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
66219
66360
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
66220
66361
|
}
|
|
66221
|
-
const ext =
|
|
66362
|
+
const ext = path61.extname(resolvedPath).toLowerCase();
|
|
66222
66363
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
66223
66364
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
66224
66365
|
}
|
|
66225
|
-
const stats =
|
|
66366
|
+
const stats = fs48.statSync(resolvedPath);
|
|
66226
66367
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
66227
66368
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
66228
66369
|
}
|
|
66229
|
-
if (!
|
|
66370
|
+
if (!fs48.existsSync(resolvedPath)) {
|
|
66230
66371
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
66231
66372
|
}
|
|
66232
66373
|
return resolvedPath;
|
|
66233
66374
|
}
|
|
66234
66375
|
for (const candidate of SPEC_CANDIDATES) {
|
|
66235
|
-
const candidatePath =
|
|
66236
|
-
if (
|
|
66237
|
-
const stats =
|
|
66376
|
+
const candidatePath = path61.resolve(cwd, candidate);
|
|
66377
|
+
if (fs48.existsSync(candidatePath)) {
|
|
66378
|
+
const stats = fs48.statSync(candidatePath);
|
|
66238
66379
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
66239
66380
|
return candidatePath;
|
|
66240
66381
|
}
|
|
@@ -66243,8 +66384,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
66243
66384
|
return null;
|
|
66244
66385
|
}
|
|
66245
66386
|
function parseSpec(specFile) {
|
|
66246
|
-
const content =
|
|
66247
|
-
const ext =
|
|
66387
|
+
const content = fs48.readFileSync(specFile, "utf-8");
|
|
66388
|
+
const ext = path61.extname(specFile).toLowerCase();
|
|
66248
66389
|
if (ext === ".json") {
|
|
66249
66390
|
return parseJsonSpec(content);
|
|
66250
66391
|
}
|
|
@@ -66315,12 +66456,12 @@ function extractRoutes(cwd) {
|
|
|
66315
66456
|
function walkDir(dir) {
|
|
66316
66457
|
let entries;
|
|
66317
66458
|
try {
|
|
66318
|
-
entries =
|
|
66459
|
+
entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66319
66460
|
} catch {
|
|
66320
66461
|
return;
|
|
66321
66462
|
}
|
|
66322
66463
|
for (const entry of entries) {
|
|
66323
|
-
const fullPath =
|
|
66464
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66324
66465
|
if (entry.isSymbolicLink()) {
|
|
66325
66466
|
continue;
|
|
66326
66467
|
}
|
|
@@ -66330,7 +66471,7 @@ function extractRoutes(cwd) {
|
|
|
66330
66471
|
}
|
|
66331
66472
|
walkDir(fullPath);
|
|
66332
66473
|
} else if (entry.isFile()) {
|
|
66333
|
-
const ext =
|
|
66474
|
+
const ext = path61.extname(entry.name).toLowerCase();
|
|
66334
66475
|
const baseName = entry.name.toLowerCase();
|
|
66335
66476
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
66336
66477
|
continue;
|
|
@@ -66348,7 +66489,7 @@ function extractRoutes(cwd) {
|
|
|
66348
66489
|
}
|
|
66349
66490
|
function extractRoutesFromFile(filePath) {
|
|
66350
66491
|
const routes = [];
|
|
66351
|
-
const content =
|
|
66492
|
+
const content = fs48.readFileSync(filePath, "utf-8");
|
|
66352
66493
|
const lines = content.split(/\r?\n/);
|
|
66353
66494
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
66354
66495
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -66499,8 +66640,8 @@ init_secretscan();
|
|
|
66499
66640
|
// src/tools/symbols.ts
|
|
66500
66641
|
init_tool();
|
|
66501
66642
|
init_create_tool();
|
|
66502
|
-
import * as
|
|
66503
|
-
import * as
|
|
66643
|
+
import * as fs49 from "fs";
|
|
66644
|
+
import * as path62 from "path";
|
|
66504
66645
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
66505
66646
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
66506
66647
|
function containsWindowsAttacks(str) {
|
|
@@ -66517,11 +66658,11 @@ function containsWindowsAttacks(str) {
|
|
|
66517
66658
|
}
|
|
66518
66659
|
function isPathInWorkspace(filePath, workspace) {
|
|
66519
66660
|
try {
|
|
66520
|
-
const resolvedPath =
|
|
66521
|
-
const realWorkspace =
|
|
66522
|
-
const realResolvedPath =
|
|
66523
|
-
const relativePath =
|
|
66524
|
-
if (relativePath.startsWith("..") ||
|
|
66661
|
+
const resolvedPath = path62.resolve(workspace, filePath);
|
|
66662
|
+
const realWorkspace = fs49.realpathSync(workspace);
|
|
66663
|
+
const realResolvedPath = fs49.realpathSync(resolvedPath);
|
|
66664
|
+
const relativePath = path62.relative(realWorkspace, realResolvedPath);
|
|
66665
|
+
if (relativePath.startsWith("..") || path62.isAbsolute(relativePath)) {
|
|
66525
66666
|
return false;
|
|
66526
66667
|
}
|
|
66527
66668
|
return true;
|
|
@@ -66533,17 +66674,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
66533
66674
|
return isPathInWorkspace(filePath, workspace);
|
|
66534
66675
|
}
|
|
66535
66676
|
function extractTSSymbols(filePath, cwd) {
|
|
66536
|
-
const fullPath =
|
|
66677
|
+
const fullPath = path62.join(cwd, filePath);
|
|
66537
66678
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66538
66679
|
return [];
|
|
66539
66680
|
}
|
|
66540
66681
|
let content;
|
|
66541
66682
|
try {
|
|
66542
|
-
const stats =
|
|
66683
|
+
const stats = fs49.statSync(fullPath);
|
|
66543
66684
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66544
66685
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66545
66686
|
}
|
|
66546
|
-
content =
|
|
66687
|
+
content = fs49.readFileSync(fullPath, "utf-8");
|
|
66547
66688
|
} catch {
|
|
66548
66689
|
return [];
|
|
66549
66690
|
}
|
|
@@ -66685,17 +66826,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
66685
66826
|
});
|
|
66686
66827
|
}
|
|
66687
66828
|
function extractPythonSymbols(filePath, cwd) {
|
|
66688
|
-
const fullPath =
|
|
66829
|
+
const fullPath = path62.join(cwd, filePath);
|
|
66689
66830
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66690
66831
|
return [];
|
|
66691
66832
|
}
|
|
66692
66833
|
let content;
|
|
66693
66834
|
try {
|
|
66694
|
-
const stats =
|
|
66835
|
+
const stats = fs49.statSync(fullPath);
|
|
66695
66836
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66696
66837
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66697
66838
|
}
|
|
66698
|
-
content =
|
|
66839
|
+
content = fs49.readFileSync(fullPath, "utf-8");
|
|
66699
66840
|
} catch {
|
|
66700
66841
|
return [];
|
|
66701
66842
|
}
|
|
@@ -66768,7 +66909,7 @@ var symbols = createSwarmTool({
|
|
|
66768
66909
|
}, null, 2);
|
|
66769
66910
|
}
|
|
66770
66911
|
const cwd = directory;
|
|
66771
|
-
const ext =
|
|
66912
|
+
const ext = path62.extname(file3);
|
|
66772
66913
|
if (containsControlChars(file3)) {
|
|
66773
66914
|
return JSON.stringify({
|
|
66774
66915
|
file: file3,
|
|
@@ -66839,8 +66980,8 @@ init_test_runner();
|
|
|
66839
66980
|
init_dist();
|
|
66840
66981
|
init_utils();
|
|
66841
66982
|
init_create_tool();
|
|
66842
|
-
import * as
|
|
66843
|
-
import * as
|
|
66983
|
+
import * as fs50 from "fs";
|
|
66984
|
+
import * as path63 from "path";
|
|
66844
66985
|
var MAX_TEXT_LENGTH = 200;
|
|
66845
66986
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
66846
66987
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -66905,9 +67046,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
66905
67046
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
66906
67047
|
}
|
|
66907
67048
|
try {
|
|
66908
|
-
const resolvedPath =
|
|
66909
|
-
const normalizedCwd =
|
|
66910
|
-
const normalizedResolved =
|
|
67049
|
+
const resolvedPath = path63.resolve(paths);
|
|
67050
|
+
const normalizedCwd = path63.resolve(cwd);
|
|
67051
|
+
const normalizedResolved = path63.resolve(resolvedPath);
|
|
66911
67052
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
66912
67053
|
return {
|
|
66913
67054
|
error: "paths must be within the current working directory",
|
|
@@ -66923,13 +67064,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
66923
67064
|
}
|
|
66924
67065
|
}
|
|
66925
67066
|
function isSupportedExtension(filePath) {
|
|
66926
|
-
const ext =
|
|
67067
|
+
const ext = path63.extname(filePath).toLowerCase();
|
|
66927
67068
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
66928
67069
|
}
|
|
66929
67070
|
function findSourceFiles2(dir, files = []) {
|
|
66930
67071
|
let entries;
|
|
66931
67072
|
try {
|
|
66932
|
-
entries =
|
|
67073
|
+
entries = fs50.readdirSync(dir);
|
|
66933
67074
|
} catch {
|
|
66934
67075
|
return files;
|
|
66935
67076
|
}
|
|
@@ -66938,10 +67079,10 @@ function findSourceFiles2(dir, files = []) {
|
|
|
66938
67079
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
66939
67080
|
continue;
|
|
66940
67081
|
}
|
|
66941
|
-
const fullPath =
|
|
67082
|
+
const fullPath = path63.join(dir, entry);
|
|
66942
67083
|
let stat2;
|
|
66943
67084
|
try {
|
|
66944
|
-
stat2 =
|
|
67085
|
+
stat2 = fs50.statSync(fullPath);
|
|
66945
67086
|
} catch {
|
|
66946
67087
|
continue;
|
|
66947
67088
|
}
|
|
@@ -67034,7 +67175,7 @@ var todo_extract = createSwarmTool({
|
|
|
67034
67175
|
return JSON.stringify(errorResult, null, 2);
|
|
67035
67176
|
}
|
|
67036
67177
|
const scanPath = resolvedPath;
|
|
67037
|
-
if (!
|
|
67178
|
+
if (!fs50.existsSync(scanPath)) {
|
|
67038
67179
|
const errorResult = {
|
|
67039
67180
|
error: `path not found: ${pathsInput}`,
|
|
67040
67181
|
total: 0,
|
|
@@ -67044,13 +67185,13 @@ var todo_extract = createSwarmTool({
|
|
|
67044
67185
|
return JSON.stringify(errorResult, null, 2);
|
|
67045
67186
|
}
|
|
67046
67187
|
const filesToScan = [];
|
|
67047
|
-
const stat2 =
|
|
67188
|
+
const stat2 = fs50.statSync(scanPath);
|
|
67048
67189
|
if (stat2.isFile()) {
|
|
67049
67190
|
if (isSupportedExtension(scanPath)) {
|
|
67050
67191
|
filesToScan.push(scanPath);
|
|
67051
67192
|
} else {
|
|
67052
67193
|
const errorResult = {
|
|
67053
|
-
error: `unsupported file extension: ${
|
|
67194
|
+
error: `unsupported file extension: ${path63.extname(scanPath)}`,
|
|
67054
67195
|
total: 0,
|
|
67055
67196
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
67056
67197
|
entries: []
|
|
@@ -67063,11 +67204,11 @@ var todo_extract = createSwarmTool({
|
|
|
67063
67204
|
const allEntries = [];
|
|
67064
67205
|
for (const filePath of filesToScan) {
|
|
67065
67206
|
try {
|
|
67066
|
-
const fileStat =
|
|
67207
|
+
const fileStat = fs50.statSync(filePath);
|
|
67067
67208
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
67068
67209
|
continue;
|
|
67069
67210
|
}
|
|
67070
|
-
const content =
|
|
67211
|
+
const content = fs50.readFileSync(filePath, "utf-8");
|
|
67071
67212
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
67072
67213
|
allEntries.push(...entries);
|
|
67073
67214
|
} catch {}
|
|
@@ -67096,18 +67237,18 @@ var todo_extract = createSwarmTool({
|
|
|
67096
67237
|
init_tool();
|
|
67097
67238
|
init_schema();
|
|
67098
67239
|
init_gate_evidence();
|
|
67099
|
-
import * as
|
|
67100
|
-
import * as
|
|
67240
|
+
import * as fs52 from "fs";
|
|
67241
|
+
import * as path65 from "path";
|
|
67101
67242
|
|
|
67102
67243
|
// src/hooks/diff-scope.ts
|
|
67103
|
-
import * as
|
|
67104
|
-
import * as
|
|
67244
|
+
import * as fs51 from "fs";
|
|
67245
|
+
import * as path64 from "path";
|
|
67105
67246
|
function getDeclaredScope(taskId, directory) {
|
|
67106
67247
|
try {
|
|
67107
|
-
const planPath =
|
|
67108
|
-
if (!
|
|
67248
|
+
const planPath = path64.join(directory, ".swarm", "plan.json");
|
|
67249
|
+
if (!fs51.existsSync(planPath))
|
|
67109
67250
|
return null;
|
|
67110
|
-
const raw =
|
|
67251
|
+
const raw = fs51.readFileSync(planPath, "utf-8");
|
|
67111
67252
|
const plan = JSON.parse(raw);
|
|
67112
67253
|
for (const phase of plan.phases ?? []) {
|
|
67113
67254
|
for (const task of phase.tasks ?? []) {
|
|
@@ -67220,7 +67361,7 @@ var TIER_3_PATTERNS = [
|
|
|
67220
67361
|
];
|
|
67221
67362
|
function matchesTier3Pattern(files) {
|
|
67222
67363
|
for (const file3 of files) {
|
|
67223
|
-
const fileName =
|
|
67364
|
+
const fileName = path65.basename(file3);
|
|
67224
67365
|
for (const pattern of TIER_3_PATTERNS) {
|
|
67225
67366
|
if (pattern.test(fileName)) {
|
|
67226
67367
|
return true;
|
|
@@ -67234,8 +67375,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67234
67375
|
if (hasActiveTurboMode()) {
|
|
67235
67376
|
const resolvedDir2 = workingDirectory;
|
|
67236
67377
|
try {
|
|
67237
|
-
const planPath =
|
|
67238
|
-
const planRaw =
|
|
67378
|
+
const planPath = path65.join(resolvedDir2, ".swarm", "plan.json");
|
|
67379
|
+
const planRaw = fs52.readFileSync(planPath, "utf-8");
|
|
67239
67380
|
const plan = JSON.parse(planRaw);
|
|
67240
67381
|
for (const planPhase of plan.phases ?? []) {
|
|
67241
67382
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67301,8 +67442,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67301
67442
|
}
|
|
67302
67443
|
try {
|
|
67303
67444
|
const resolvedDir2 = workingDirectory;
|
|
67304
|
-
const planPath =
|
|
67305
|
-
const planRaw =
|
|
67445
|
+
const planPath = path65.join(resolvedDir2, ".swarm", "plan.json");
|
|
67446
|
+
const planRaw = fs52.readFileSync(planPath, "utf-8");
|
|
67306
67447
|
const plan = JSON.parse(planRaw);
|
|
67307
67448
|
for (const planPhase of plan.phases ?? []) {
|
|
67308
67449
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67484,8 +67625,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67484
67625
|
};
|
|
67485
67626
|
}
|
|
67486
67627
|
}
|
|
67487
|
-
normalizedDir =
|
|
67488
|
-
const pathParts = normalizedDir.split(
|
|
67628
|
+
normalizedDir = path65.normalize(args2.working_directory);
|
|
67629
|
+
const pathParts = normalizedDir.split(path65.sep);
|
|
67489
67630
|
if (pathParts.includes("..")) {
|
|
67490
67631
|
return {
|
|
67491
67632
|
success: false,
|
|
@@ -67495,11 +67636,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67495
67636
|
]
|
|
67496
67637
|
};
|
|
67497
67638
|
}
|
|
67498
|
-
const resolvedDir =
|
|
67639
|
+
const resolvedDir = path65.resolve(normalizedDir);
|
|
67499
67640
|
try {
|
|
67500
|
-
const realPath =
|
|
67501
|
-
const planPath =
|
|
67502
|
-
if (!
|
|
67641
|
+
const realPath = fs52.realpathSync(resolvedDir);
|
|
67642
|
+
const planPath = path65.join(realPath, ".swarm", "plan.json");
|
|
67643
|
+
if (!fs52.existsSync(planPath)) {
|
|
67503
67644
|
return {
|
|
67504
67645
|
success: false,
|
|
67505
67646
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -67532,8 +67673,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67532
67673
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
67533
67674
|
let phaseRequiresReviewer = true;
|
|
67534
67675
|
try {
|
|
67535
|
-
const planPath =
|
|
67536
|
-
const planRaw =
|
|
67676
|
+
const planPath = path65.join(directory, ".swarm", "plan.json");
|
|
67677
|
+
const planRaw = fs52.readFileSync(planPath, "utf-8");
|
|
67537
67678
|
const plan = JSON.parse(planRaw);
|
|
67538
67679
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
67539
67680
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -67596,8 +67737,8 @@ var update_task_status = createSwarmTool({
|
|
|
67596
67737
|
init_tool();
|
|
67597
67738
|
init_utils2();
|
|
67598
67739
|
init_create_tool();
|
|
67599
|
-
import
|
|
67600
|
-
import
|
|
67740
|
+
import fs53 from "fs";
|
|
67741
|
+
import path66 from "path";
|
|
67601
67742
|
function normalizeVerdict(verdict) {
|
|
67602
67743
|
switch (verdict) {
|
|
67603
67744
|
case "APPROVED":
|
|
@@ -67644,7 +67785,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67644
67785
|
entries: [evidenceEntry]
|
|
67645
67786
|
};
|
|
67646
67787
|
const filename = "drift-verifier.json";
|
|
67647
|
-
const relativePath =
|
|
67788
|
+
const relativePath = path66.join("evidence", String(phase), filename);
|
|
67648
67789
|
let validatedPath;
|
|
67649
67790
|
try {
|
|
67650
67791
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -67655,12 +67796,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67655
67796
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
67656
67797
|
}, null, 2);
|
|
67657
67798
|
}
|
|
67658
|
-
const evidenceDir =
|
|
67799
|
+
const evidenceDir = path66.dirname(validatedPath);
|
|
67659
67800
|
try {
|
|
67660
|
-
await
|
|
67661
|
-
const tempPath =
|
|
67662
|
-
await
|
|
67663
|
-
await
|
|
67801
|
+
await fs53.promises.mkdir(evidenceDir, { recursive: true });
|
|
67802
|
+
const tempPath = path66.join(evidenceDir, `.${filename}.tmp`);
|
|
67803
|
+
await fs53.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
67804
|
+
await fs53.promises.rename(tempPath, validatedPath);
|
|
67664
67805
|
return JSON.stringify({
|
|
67665
67806
|
success: true,
|
|
67666
67807
|
phase,
|
|
@@ -67848,7 +67989,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
67848
67989
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
67849
67990
|
preflightTriggerManager = new PTM(automationConfig);
|
|
67850
67991
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
67851
|
-
const swarmDir =
|
|
67992
|
+
const swarmDir = path67.resolve(ctx.directory, ".swarm");
|
|
67852
67993
|
statusArtifact = new ASA(swarmDir);
|
|
67853
67994
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
67854
67995
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|