opencode-swarm 6.41.2 → 6.41.4
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 +247 -160
- package/dist/index.js +765 -612
- 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
|
@@ -32342,7 +32342,7 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
32342
32342
|
lesson,
|
|
32343
32343
|
category: "architecture",
|
|
32344
32344
|
tags: ["hidden-coupling", "co-change", "dark-matter"],
|
|
32345
|
-
scope: "
|
|
32345
|
+
scope: "global",
|
|
32346
32346
|
confidence,
|
|
32347
32347
|
status: "candidate",
|
|
32348
32348
|
confirmed_by: [],
|
|
@@ -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,
|
|
@@ -55141,15 +55228,14 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55141
55228
|
} = await Promise.resolve().then(() => (init_co_change_analyzer(), exports_co_change_analyzer));
|
|
55142
55229
|
const darkMatter = await detectDarkMatter2(directory, {
|
|
55143
55230
|
minCommits: 20,
|
|
55144
|
-
minCoChanges: 3
|
|
55145
|
-
npmiThreshold: 0.3
|
|
55231
|
+
minCoChanges: 3
|
|
55146
55232
|
});
|
|
55147
55233
|
if (darkMatter && darkMatter.length > 0) {
|
|
55148
55234
|
const darkMatterReport = formatDarkMatterOutput2(darkMatter);
|
|
55149
|
-
await
|
|
55235
|
+
await fs28.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
55150
55236
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
55151
55237
|
try {
|
|
55152
|
-
const projectName =
|
|
55238
|
+
const projectName = path40.basename(path40.resolve(directory));
|
|
55153
55239
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
55154
55240
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
55155
55241
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -55168,6 +55254,19 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55168
55254
|
}
|
|
55169
55255
|
}
|
|
55170
55256
|
}
|
|
55257
|
+
try {
|
|
55258
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
55259
|
+
const allEntries = await readKnowledge(knowledgePath);
|
|
55260
|
+
const stale = allEntries.filter((e) => e.scope === "project" && e.auto_generated === true && Array.isArray(e.tags) && e.tags.includes("dark-matter"));
|
|
55261
|
+
if (stale.length > 0) {
|
|
55262
|
+
for (const e of stale) {
|
|
55263
|
+
e.scope = "global";
|
|
55264
|
+
e.updated_at = new Date().toISOString();
|
|
55265
|
+
}
|
|
55266
|
+
await rewriteKnowledge(knowledgePath, allEntries);
|
|
55267
|
+
warn(`[system-enhancer] Repaired ${stale.length} dark matter knowledge entries (scope: 'project' \u2192 'global')`);
|
|
55268
|
+
}
|
|
55269
|
+
} catch {}
|
|
55171
55270
|
} catch {}
|
|
55172
55271
|
const scoringEnabled = config3.context_budget?.scoring?.enabled === true;
|
|
55173
55272
|
if (!scoringEnabled) {
|
|
@@ -55200,11 +55299,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
55200
55299
|
if (handoffContent) {
|
|
55201
55300
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55202
55301
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55203
|
-
if (
|
|
55302
|
+
if (fs28.existsSync(consumedPath)) {
|
|
55204
55303
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55205
|
-
|
|
55304
|
+
fs28.unlinkSync(consumedPath);
|
|
55206
55305
|
}
|
|
55207
|
-
|
|
55306
|
+
fs28.renameSync(handoffPath, consumedPath);
|
|
55208
55307
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55209
55308
|
The previous model's session ended. Here is your starting context:
|
|
55210
55309
|
|
|
@@ -55485,11 +55584,11 @@ ${budgetWarning}`);
|
|
|
55485
55584
|
if (handoffContent) {
|
|
55486
55585
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
55487
55586
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
55488
|
-
if (
|
|
55587
|
+
if (fs28.existsSync(consumedPath)) {
|
|
55489
55588
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
55490
|
-
|
|
55589
|
+
fs28.unlinkSync(consumedPath);
|
|
55491
55590
|
}
|
|
55492
|
-
|
|
55591
|
+
fs28.renameSync(handoffPath, consumedPath);
|
|
55493
55592
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
55494
55593
|
The previous model's session ended. Here is your starting context:
|
|
55495
55594
|
|
|
@@ -56259,14 +56358,14 @@ function isReadTool(toolName) {
|
|
|
56259
56358
|
}
|
|
56260
56359
|
|
|
56261
56360
|
// src/hooks/incremental-verify.ts
|
|
56262
|
-
import * as
|
|
56263
|
-
import * as
|
|
56361
|
+
import * as fs29 from "fs";
|
|
56362
|
+
import * as path41 from "path";
|
|
56264
56363
|
|
|
56265
56364
|
// src/hooks/spawn-helper.ts
|
|
56266
56365
|
import { spawn } from "child_process";
|
|
56267
56366
|
var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
|
|
56268
56367
|
function spawnAsync(command, cwd, timeoutMs) {
|
|
56269
|
-
return new Promise((
|
|
56368
|
+
return new Promise((resolve13) => {
|
|
56270
56369
|
try {
|
|
56271
56370
|
const [rawCmd, ...args2] = command;
|
|
56272
56371
|
const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
|
|
@@ -56310,24 +56409,24 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
56310
56409
|
try {
|
|
56311
56410
|
proc.kill();
|
|
56312
56411
|
} catch {}
|
|
56313
|
-
|
|
56412
|
+
resolve13(null);
|
|
56314
56413
|
}, timeoutMs);
|
|
56315
56414
|
proc.on("close", (code) => {
|
|
56316
56415
|
if (done)
|
|
56317
56416
|
return;
|
|
56318
56417
|
done = true;
|
|
56319
56418
|
clearTimeout(timer);
|
|
56320
|
-
|
|
56419
|
+
resolve13({ exitCode: code ?? 1, stdout, stderr });
|
|
56321
56420
|
});
|
|
56322
56421
|
proc.on("error", () => {
|
|
56323
56422
|
if (done)
|
|
56324
56423
|
return;
|
|
56325
56424
|
done = true;
|
|
56326
56425
|
clearTimeout(timer);
|
|
56327
|
-
|
|
56426
|
+
resolve13(null);
|
|
56328
56427
|
});
|
|
56329
56428
|
} catch {
|
|
56330
|
-
|
|
56429
|
+
resolve13(null);
|
|
56331
56430
|
}
|
|
56332
56431
|
});
|
|
56333
56432
|
}
|
|
@@ -56335,21 +56434,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
56335
56434
|
// src/hooks/incremental-verify.ts
|
|
56336
56435
|
var emittedSkipAdvisories = new Set;
|
|
56337
56436
|
function detectPackageManager(projectDir) {
|
|
56338
|
-
if (
|
|
56437
|
+
if (fs29.existsSync(path41.join(projectDir, "bun.lockb")))
|
|
56339
56438
|
return "bun";
|
|
56340
|
-
if (
|
|
56439
|
+
if (fs29.existsSync(path41.join(projectDir, "pnpm-lock.yaml")))
|
|
56341
56440
|
return "pnpm";
|
|
56342
|
-
if (
|
|
56441
|
+
if (fs29.existsSync(path41.join(projectDir, "yarn.lock")))
|
|
56343
56442
|
return "yarn";
|
|
56344
|
-
if (
|
|
56443
|
+
if (fs29.existsSync(path41.join(projectDir, "package-lock.json")))
|
|
56345
56444
|
return "npm";
|
|
56346
56445
|
return "bun";
|
|
56347
56446
|
}
|
|
56348
56447
|
function detectTypecheckCommand(projectDir) {
|
|
56349
|
-
const pkgPath =
|
|
56350
|
-
if (
|
|
56448
|
+
const pkgPath = path41.join(projectDir, "package.json");
|
|
56449
|
+
if (fs29.existsSync(pkgPath)) {
|
|
56351
56450
|
try {
|
|
56352
|
-
const pkg = JSON.parse(
|
|
56451
|
+
const pkg = JSON.parse(fs29.readFileSync(pkgPath, "utf8"));
|
|
56353
56452
|
const scripts = pkg.scripts;
|
|
56354
56453
|
if (scripts?.typecheck) {
|
|
56355
56454
|
const pm = detectPackageManager(projectDir);
|
|
@@ -56363,8 +56462,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56363
56462
|
...pkg.dependencies,
|
|
56364
56463
|
...pkg.devDependencies
|
|
56365
56464
|
};
|
|
56366
|
-
if (!deps?.typescript && !
|
|
56367
|
-
const hasTSMarkers = deps?.typescript ||
|
|
56465
|
+
if (!deps?.typescript && !fs29.existsSync(path41.join(projectDir, "tsconfig.json"))) {}
|
|
56466
|
+
const hasTSMarkers = deps?.typescript || fs29.existsSync(path41.join(projectDir, "tsconfig.json"));
|
|
56368
56467
|
if (hasTSMarkers) {
|
|
56369
56468
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
56370
56469
|
}
|
|
@@ -56372,17 +56471,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
56372
56471
|
return null;
|
|
56373
56472
|
}
|
|
56374
56473
|
}
|
|
56375
|
-
if (
|
|
56474
|
+
if (fs29.existsSync(path41.join(projectDir, "go.mod"))) {
|
|
56376
56475
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
56377
56476
|
}
|
|
56378
|
-
if (
|
|
56477
|
+
if (fs29.existsSync(path41.join(projectDir, "Cargo.toml"))) {
|
|
56379
56478
|
return { command: ["cargo", "check"], language: "rust" };
|
|
56380
56479
|
}
|
|
56381
|
-
if (
|
|
56480
|
+
if (fs29.existsSync(path41.join(projectDir, "pyproject.toml")) || fs29.existsSync(path41.join(projectDir, "requirements.txt")) || fs29.existsSync(path41.join(projectDir, "setup.py"))) {
|
|
56382
56481
|
return { command: null, language: "python" };
|
|
56383
56482
|
}
|
|
56384
56483
|
try {
|
|
56385
|
-
const entries =
|
|
56484
|
+
const entries = fs29.readdirSync(projectDir);
|
|
56386
56485
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
56387
56486
|
return {
|
|
56388
56487
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -56691,7 +56790,7 @@ ${injectionText}`;
|
|
|
56691
56790
|
// src/hooks/scope-guard.ts
|
|
56692
56791
|
init_constants();
|
|
56693
56792
|
init_schema();
|
|
56694
|
-
import * as
|
|
56793
|
+
import * as path43 from "path";
|
|
56695
56794
|
var WRITE_TOOLS = new Set([
|
|
56696
56795
|
"write",
|
|
56697
56796
|
"edit",
|
|
@@ -56753,13 +56852,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
56753
56852
|
}
|
|
56754
56853
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
56755
56854
|
const dir = directory ?? process.cwd();
|
|
56756
|
-
const resolvedFile =
|
|
56855
|
+
const resolvedFile = path43.resolve(dir, filePath);
|
|
56757
56856
|
return scopeEntries.some((scope) => {
|
|
56758
|
-
const resolvedScope =
|
|
56857
|
+
const resolvedScope = path43.resolve(dir, scope);
|
|
56759
56858
|
if (resolvedFile === resolvedScope)
|
|
56760
56859
|
return true;
|
|
56761
|
-
const rel =
|
|
56762
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
56860
|
+
const rel = path43.relative(resolvedScope, resolvedFile);
|
|
56861
|
+
return rel.length > 0 && !rel.startsWith("..") && !path43.isAbsolute(rel);
|
|
56763
56862
|
});
|
|
56764
56863
|
}
|
|
56765
56864
|
|
|
@@ -56808,8 +56907,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
56808
56907
|
}
|
|
56809
56908
|
|
|
56810
56909
|
// src/hooks/slop-detector.ts
|
|
56811
|
-
import * as
|
|
56812
|
-
import * as
|
|
56910
|
+
import * as fs31 from "fs";
|
|
56911
|
+
import * as path44 from "path";
|
|
56813
56912
|
var WRITE_EDIT_TOOLS = new Set([
|
|
56814
56913
|
"write",
|
|
56815
56914
|
"edit",
|
|
@@ -56854,12 +56953,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
56854
56953
|
function walkFiles(dir, exts, deadline) {
|
|
56855
56954
|
const results = [];
|
|
56856
56955
|
try {
|
|
56857
|
-
for (const entry of
|
|
56956
|
+
for (const entry of fs31.readdirSync(dir, { withFileTypes: true })) {
|
|
56858
56957
|
if (deadline !== undefined && Date.now() > deadline)
|
|
56859
56958
|
break;
|
|
56860
56959
|
if (entry.isSymbolicLink())
|
|
56861
56960
|
continue;
|
|
56862
|
-
const full =
|
|
56961
|
+
const full = path44.join(dir, entry.name);
|
|
56863
56962
|
if (entry.isDirectory()) {
|
|
56864
56963
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
56865
56964
|
continue;
|
|
@@ -56874,7 +56973,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
56874
56973
|
return results;
|
|
56875
56974
|
}
|
|
56876
56975
|
function checkDeadExports(content, projectDir, startTime) {
|
|
56877
|
-
const hasPackageJson =
|
|
56976
|
+
const hasPackageJson = fs31.existsSync(path44.join(projectDir, "package.json"));
|
|
56878
56977
|
if (!hasPackageJson)
|
|
56879
56978
|
return null;
|
|
56880
56979
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -56897,7 +56996,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
56897
56996
|
if (found || Date.now() - startTime > 480)
|
|
56898
56997
|
break;
|
|
56899
56998
|
try {
|
|
56900
|
-
const text =
|
|
56999
|
+
const text = fs31.readFileSync(file3, "utf-8");
|
|
56901
57000
|
if (importPattern.test(text))
|
|
56902
57001
|
found = true;
|
|
56903
57002
|
importPattern.lastIndex = 0;
|
|
@@ -57030,7 +57129,7 @@ Review before proceeding.`;
|
|
|
57030
57129
|
|
|
57031
57130
|
// src/hooks/steering-consumed.ts
|
|
57032
57131
|
init_utils2();
|
|
57033
|
-
import * as
|
|
57132
|
+
import * as fs32 from "fs";
|
|
57034
57133
|
function recordSteeringConsumed(directory, directiveId) {
|
|
57035
57134
|
try {
|
|
57036
57135
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -57039,7 +57138,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
57039
57138
|
directiveId,
|
|
57040
57139
|
timestamp: new Date().toISOString()
|
|
57041
57140
|
};
|
|
57042
|
-
|
|
57141
|
+
fs32.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57043
57142
|
`, "utf-8");
|
|
57044
57143
|
} catch {}
|
|
57045
57144
|
}
|
|
@@ -57329,21 +57428,24 @@ async function executeCommand(command) {
|
|
|
57329
57428
|
cmd = ["/bin/sh"];
|
|
57330
57429
|
args2 = ["-c", command.command];
|
|
57331
57430
|
}
|
|
57332
|
-
const result =
|
|
57431
|
+
const result = Bun.spawn({
|
|
57333
57432
|
cmd: [...cmd, ...args2],
|
|
57334
57433
|
cwd: command.cwd,
|
|
57335
57434
|
stdout: "pipe",
|
|
57336
57435
|
stderr: "pipe",
|
|
57337
57436
|
timeout: DEFAULT_TIMEOUT_MS2
|
|
57338
57437
|
});
|
|
57438
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
57439
|
+
result.exited,
|
|
57440
|
+
new Response(result.stdout).text(),
|
|
57441
|
+
new Response(result.stderr).text()
|
|
57442
|
+
]);
|
|
57339
57443
|
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
57444
|
return {
|
|
57343
57445
|
kind,
|
|
57344
57446
|
command: command.command,
|
|
57345
57447
|
cwd: command.cwd,
|
|
57346
|
-
exit_code:
|
|
57448
|
+
exit_code: exitCode ?? -1,
|
|
57347
57449
|
duration_ms,
|
|
57348
57450
|
stdout_tail: truncateOutput(stdout),
|
|
57349
57451
|
stderr_tail: truncateOutput(stderr)
|
|
@@ -57448,8 +57550,9 @@ var build_check = createSwarmTool({
|
|
|
57448
57550
|
init_dist();
|
|
57449
57551
|
init_manager();
|
|
57450
57552
|
init_create_tool();
|
|
57451
|
-
|
|
57452
|
-
import * as
|
|
57553
|
+
init_resolve_working_directory();
|
|
57554
|
+
import * as fs33 from "fs";
|
|
57555
|
+
import * as path45 from "path";
|
|
57453
57556
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
57454
57557
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
57455
57558
|
function isValidTaskId3(taskId) {
|
|
@@ -57466,18 +57569,18 @@ function isValidTaskId3(taskId) {
|
|
|
57466
57569
|
return TASK_ID_PATTERN2.test(taskId);
|
|
57467
57570
|
}
|
|
57468
57571
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
57469
|
-
const normalizedWorkspace =
|
|
57470
|
-
const swarmPath =
|
|
57471
|
-
const normalizedPath =
|
|
57572
|
+
const normalizedWorkspace = path45.resolve(workspaceRoot);
|
|
57573
|
+
const swarmPath = path45.join(normalizedWorkspace, ".swarm", "evidence");
|
|
57574
|
+
const normalizedPath = path45.resolve(filePath);
|
|
57472
57575
|
return normalizedPath.startsWith(swarmPath);
|
|
57473
57576
|
}
|
|
57474
57577
|
function readEvidenceFile(evidencePath) {
|
|
57475
|
-
if (!
|
|
57578
|
+
if (!fs33.existsSync(evidencePath)) {
|
|
57476
57579
|
return null;
|
|
57477
57580
|
}
|
|
57478
57581
|
let content;
|
|
57479
57582
|
try {
|
|
57480
|
-
content =
|
|
57583
|
+
content = fs33.readFileSync(evidencePath, "utf-8");
|
|
57481
57584
|
} catch {
|
|
57482
57585
|
return null;
|
|
57483
57586
|
}
|
|
@@ -57495,16 +57598,34 @@ function readEvidenceFile(evidencePath) {
|
|
|
57495
57598
|
var check_gate_status = createSwarmTool({
|
|
57496
57599
|
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
57600
|
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")')
|
|
57601
|
+
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")'),
|
|
57602
|
+
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
57603
|
},
|
|
57500
57604
|
async execute(args2, directory) {
|
|
57501
57605
|
let taskIdInput;
|
|
57606
|
+
let workingDirInput;
|
|
57502
57607
|
try {
|
|
57503
57608
|
if (args2 && typeof args2 === "object") {
|
|
57504
57609
|
const obj = args2;
|
|
57505
57610
|
taskIdInput = typeof obj.task_id === "string" ? obj.task_id : undefined;
|
|
57611
|
+
workingDirInput = typeof obj.working_directory === "string" ? obj.working_directory : undefined;
|
|
57506
57612
|
}
|
|
57507
57613
|
} catch {}
|
|
57614
|
+
const dirResult = resolveWorkingDirectory(workingDirInput, directory);
|
|
57615
|
+
if (!dirResult.success) {
|
|
57616
|
+
const errorResult = {
|
|
57617
|
+
taskId: taskIdInput ?? "",
|
|
57618
|
+
status: "no_evidence",
|
|
57619
|
+
required_gates: [],
|
|
57620
|
+
passed_gates: [],
|
|
57621
|
+
missing_gates: [],
|
|
57622
|
+
gates: {},
|
|
57623
|
+
message: dirResult.message,
|
|
57624
|
+
todo_scan: null
|
|
57625
|
+
};
|
|
57626
|
+
return JSON.stringify(errorResult, null, 2);
|
|
57627
|
+
}
|
|
57628
|
+
directory = dirResult.directory;
|
|
57508
57629
|
if (!taskIdInput) {
|
|
57509
57630
|
const errorResult = {
|
|
57510
57631
|
taskId: "",
|
|
@@ -57531,7 +57652,7 @@ var check_gate_status = createSwarmTool({
|
|
|
57531
57652
|
};
|
|
57532
57653
|
return JSON.stringify(errorResult, null, 2);
|
|
57533
57654
|
}
|
|
57534
|
-
const evidencePath =
|
|
57655
|
+
const evidencePath = path45.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
57535
57656
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
57536
57657
|
const errorResult = {
|
|
57537
57658
|
taskId: taskIdInput,
|
|
@@ -57624,9 +57745,10 @@ init_co_change_analyzer();
|
|
|
57624
57745
|
// src/tools/completion-verify.ts
|
|
57625
57746
|
init_dist();
|
|
57626
57747
|
init_utils2();
|
|
57627
|
-
import * as
|
|
57628
|
-
import * as
|
|
57748
|
+
import * as fs34 from "fs";
|
|
57749
|
+
import * as path46 from "path";
|
|
57629
57750
|
init_create_tool();
|
|
57751
|
+
init_resolve_working_directory();
|
|
57630
57752
|
function extractMatches(regex, text) {
|
|
57631
57753
|
return Array.from(text.matchAll(regex));
|
|
57632
57754
|
}
|
|
@@ -57720,7 +57842,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57720
57842
|
let plan;
|
|
57721
57843
|
try {
|
|
57722
57844
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
57723
|
-
const planRaw =
|
|
57845
|
+
const planRaw = fs34.readFileSync(planPath, "utf-8");
|
|
57724
57846
|
plan = JSON.parse(planRaw);
|
|
57725
57847
|
} catch {
|
|
57726
57848
|
const result2 = {
|
|
@@ -57778,10 +57900,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57778
57900
|
let hasFileReadFailure = false;
|
|
57779
57901
|
for (const filePath of fileTargets) {
|
|
57780
57902
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
57781
|
-
const resolvedPath =
|
|
57782
|
-
const projectRoot =
|
|
57783
|
-
const relative6 =
|
|
57784
|
-
const withinProject = relative6 === "" || !relative6.startsWith("..") && !
|
|
57903
|
+
const resolvedPath = path46.resolve(directory, normalizedPath);
|
|
57904
|
+
const projectRoot = path46.resolve(directory);
|
|
57905
|
+
const relative6 = path46.relative(projectRoot, resolvedPath);
|
|
57906
|
+
const withinProject = relative6 === "" || !relative6.startsWith("..") && !path46.isAbsolute(relative6);
|
|
57785
57907
|
if (!withinProject) {
|
|
57786
57908
|
blockedTasks.push({
|
|
57787
57909
|
task_id: task.id,
|
|
@@ -57794,7 +57916,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57794
57916
|
}
|
|
57795
57917
|
let fileContent;
|
|
57796
57918
|
try {
|
|
57797
|
-
fileContent =
|
|
57919
|
+
fileContent = fs34.readFileSync(resolvedPath, "utf-8");
|
|
57798
57920
|
} catch {
|
|
57799
57921
|
blockedTasks.push({
|
|
57800
57922
|
task_id: task.id,
|
|
@@ -57836,9 +57958,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57836
57958
|
blockedTasks
|
|
57837
57959
|
};
|
|
57838
57960
|
try {
|
|
57839
|
-
const evidenceDir =
|
|
57840
|
-
const evidencePath =
|
|
57841
|
-
|
|
57961
|
+
const evidenceDir = path46.join(directory, ".swarm", "evidence", `${phase}`);
|
|
57962
|
+
const evidencePath = path46.join(evidenceDir, "completion-verify.json");
|
|
57963
|
+
fs34.mkdirSync(evidenceDir, { recursive: true });
|
|
57842
57964
|
const evidenceBundle = {
|
|
57843
57965
|
schema_version: "1.0.0",
|
|
57844
57966
|
task_id: "completion-verify",
|
|
@@ -57859,7 +57981,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
57859
57981
|
}
|
|
57860
57982
|
]
|
|
57861
57983
|
};
|
|
57862
|
-
|
|
57984
|
+
fs34.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
57863
57985
|
} catch {}
|
|
57864
57986
|
return JSON.stringify(result, null, 2);
|
|
57865
57987
|
}
|
|
@@ -57867,7 +57989,8 @@ var completion_verify = createSwarmTool({
|
|
|
57867
57989
|
description: "Deterministic pre-check verifying that plan task identifiers exist in their target source files before phase completion. Blocks if obviously incomplete.",
|
|
57868
57990
|
args: {
|
|
57869
57991
|
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)")
|
|
57992
|
+
sessionID: tool.schema.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),
|
|
57993
|
+
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
57994
|
},
|
|
57872
57995
|
execute: async (args2, directory) => {
|
|
57873
57996
|
let parsedArgs;
|
|
@@ -57876,7 +57999,8 @@ var completion_verify = createSwarmTool({
|
|
|
57876
57999
|
const obj = args2;
|
|
57877
58000
|
parsedArgs = {
|
|
57878
58001
|
phase: typeof obj.phase === "number" ? obj.phase : typeof obj.phase === "string" ? Number(obj.phase) : 0,
|
|
57879
|
-
sessionID: typeof obj.sessionID === "string" ? obj.sessionID : undefined
|
|
58002
|
+
sessionID: typeof obj.sessionID === "string" ? obj.sessionID : undefined,
|
|
58003
|
+
working_directory: typeof obj.working_directory === "string" ? obj.working_directory : undefined
|
|
57880
58004
|
};
|
|
57881
58005
|
} else {
|
|
57882
58006
|
parsedArgs = { phase: 0 };
|
|
@@ -57893,17 +58017,30 @@ var completion_verify = createSwarmTool({
|
|
|
57893
58017
|
blockedTasks: []
|
|
57894
58018
|
}, null, 2);
|
|
57895
58019
|
}
|
|
57896
|
-
|
|
58020
|
+
const dirResult = resolveWorkingDirectory(parsedArgs.working_directory, directory);
|
|
58021
|
+
if (!dirResult.success) {
|
|
58022
|
+
return JSON.stringify({
|
|
58023
|
+
success: false,
|
|
58024
|
+
phase: parsedArgs.phase,
|
|
58025
|
+
status: "blocked",
|
|
58026
|
+
reason: dirResult.message,
|
|
58027
|
+
tasksChecked: 0,
|
|
58028
|
+
tasksSkipped: 0,
|
|
58029
|
+
tasksBlocked: 0,
|
|
58030
|
+
blockedTasks: []
|
|
58031
|
+
}, null, 2);
|
|
58032
|
+
}
|
|
58033
|
+
return executeCompletionVerify(parsedArgs, dirResult.directory);
|
|
57897
58034
|
}
|
|
57898
58035
|
});
|
|
57899
58036
|
// src/tools/complexity-hotspots.ts
|
|
57900
58037
|
init_dist();
|
|
57901
|
-
import * as
|
|
57902
|
-
import * as
|
|
58038
|
+
import * as fs36 from "fs";
|
|
58039
|
+
import * as path48 from "path";
|
|
57903
58040
|
|
|
57904
58041
|
// src/quality/metrics.ts
|
|
57905
|
-
import * as
|
|
57906
|
-
import * as
|
|
58042
|
+
import * as fs35 from "fs";
|
|
58043
|
+
import * as path47 from "path";
|
|
57907
58044
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
57908
58045
|
var MIN_DUPLICATION_LINES = 10;
|
|
57909
58046
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -57941,11 +58078,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
57941
58078
|
}
|
|
57942
58079
|
function getComplexityForFile(filePath) {
|
|
57943
58080
|
try {
|
|
57944
|
-
const stat2 =
|
|
58081
|
+
const stat2 = fs35.statSync(filePath);
|
|
57945
58082
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
57946
58083
|
return null;
|
|
57947
58084
|
}
|
|
57948
|
-
const content =
|
|
58085
|
+
const content = fs35.readFileSync(filePath, "utf-8");
|
|
57949
58086
|
return estimateCyclomaticComplexity(content);
|
|
57950
58087
|
} catch {
|
|
57951
58088
|
return null;
|
|
@@ -57955,8 +58092,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
57955
58092
|
let totalComplexity = 0;
|
|
57956
58093
|
const analyzedFiles = [];
|
|
57957
58094
|
for (const file3 of files) {
|
|
57958
|
-
const fullPath =
|
|
57959
|
-
if (!
|
|
58095
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58096
|
+
if (!fs35.existsSync(fullPath)) {
|
|
57960
58097
|
continue;
|
|
57961
58098
|
}
|
|
57962
58099
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -58077,8 +58214,8 @@ function countGoExports(content) {
|
|
|
58077
58214
|
}
|
|
58078
58215
|
function getExportCountForFile(filePath) {
|
|
58079
58216
|
try {
|
|
58080
|
-
const content =
|
|
58081
|
-
const ext =
|
|
58217
|
+
const content = fs35.readFileSync(filePath, "utf-8");
|
|
58218
|
+
const ext = path47.extname(filePath).toLowerCase();
|
|
58082
58219
|
switch (ext) {
|
|
58083
58220
|
case ".ts":
|
|
58084
58221
|
case ".tsx":
|
|
@@ -58104,8 +58241,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58104
58241
|
let totalExports = 0;
|
|
58105
58242
|
const analyzedFiles = [];
|
|
58106
58243
|
for (const file3 of files) {
|
|
58107
|
-
const fullPath =
|
|
58108
|
-
if (!
|
|
58244
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58245
|
+
if (!fs35.existsSync(fullPath)) {
|
|
58109
58246
|
continue;
|
|
58110
58247
|
}
|
|
58111
58248
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -58138,16 +58275,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58138
58275
|
let duplicateLines = 0;
|
|
58139
58276
|
const analyzedFiles = [];
|
|
58140
58277
|
for (const file3 of files) {
|
|
58141
|
-
const fullPath =
|
|
58142
|
-
if (!
|
|
58278
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58279
|
+
if (!fs35.existsSync(fullPath)) {
|
|
58143
58280
|
continue;
|
|
58144
58281
|
}
|
|
58145
58282
|
try {
|
|
58146
|
-
const stat2 =
|
|
58283
|
+
const stat2 = fs35.statSync(fullPath);
|
|
58147
58284
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
58148
58285
|
continue;
|
|
58149
58286
|
}
|
|
58150
|
-
const content =
|
|
58287
|
+
const content = fs35.readFileSync(fullPath, "utf-8");
|
|
58151
58288
|
const lines = content.split(`
|
|
58152
58289
|
`).filter((line) => line.trim().length > 0);
|
|
58153
58290
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -58171,8 +58308,8 @@ function countCodeLines(content) {
|
|
|
58171
58308
|
return lines.length;
|
|
58172
58309
|
}
|
|
58173
58310
|
function isTestFile(filePath) {
|
|
58174
|
-
const basename7 =
|
|
58175
|
-
const _ext =
|
|
58311
|
+
const basename7 = path47.basename(filePath);
|
|
58312
|
+
const _ext = path47.extname(filePath).toLowerCase();
|
|
58176
58313
|
const testPatterns = [
|
|
58177
58314
|
".test.",
|
|
58178
58315
|
".spec.",
|
|
@@ -58253,8 +58390,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58253
58390
|
}
|
|
58254
58391
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58255
58392
|
}
|
|
58256
|
-
function matchesGlobSegment(
|
|
58257
|
-
const normalizedPath =
|
|
58393
|
+
function matchesGlobSegment(path48, glob) {
|
|
58394
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58258
58395
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58259
58396
|
if (normalizedPath.includes("//")) {
|
|
58260
58397
|
return false;
|
|
@@ -58285,8 +58422,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58285
58422
|
function hasGlobstar(glob) {
|
|
58286
58423
|
return glob.includes("**");
|
|
58287
58424
|
}
|
|
58288
|
-
function globMatches(
|
|
58289
|
-
const normalizedPath =
|
|
58425
|
+
function globMatches(path48, glob) {
|
|
58426
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58290
58427
|
if (!glob || glob === "") {
|
|
58291
58428
|
if (normalizedPath.includes("//")) {
|
|
58292
58429
|
return false;
|
|
@@ -58322,31 +58459,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58322
58459
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58323
58460
|
let testLines = 0;
|
|
58324
58461
|
let codeLines = 0;
|
|
58325
|
-
const srcDir =
|
|
58326
|
-
if (
|
|
58462
|
+
const srcDir = path47.join(workingDir, "src");
|
|
58463
|
+
if (fs35.existsSync(srcDir)) {
|
|
58327
58464
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58328
58465
|
codeLines += lines;
|
|
58329
58466
|
});
|
|
58330
58467
|
}
|
|
58331
58468
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58332
58469
|
for (const dir of possibleSrcDirs) {
|
|
58333
|
-
const dirPath =
|
|
58334
|
-
if (
|
|
58470
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58471
|
+
if (fs35.existsSync(dirPath)) {
|
|
58335
58472
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58336
58473
|
codeLines += lines;
|
|
58337
58474
|
});
|
|
58338
58475
|
}
|
|
58339
58476
|
}
|
|
58340
|
-
const testsDir =
|
|
58341
|
-
if (
|
|
58477
|
+
const testsDir = path47.join(workingDir, "tests");
|
|
58478
|
+
if (fs35.existsSync(testsDir)) {
|
|
58342
58479
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58343
58480
|
testLines += lines;
|
|
58344
58481
|
});
|
|
58345
58482
|
}
|
|
58346
58483
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58347
58484
|
for (const dir of possibleTestDirs) {
|
|
58348
|
-
const dirPath =
|
|
58349
|
-
if (
|
|
58485
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58486
|
+
if (fs35.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58350
58487
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58351
58488
|
testLines += lines;
|
|
58352
58489
|
});
|
|
@@ -58358,9 +58495,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58358
58495
|
}
|
|
58359
58496
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
58360
58497
|
try {
|
|
58361
|
-
const entries =
|
|
58498
|
+
const entries = fs35.readdirSync(dirPath, { withFileTypes: true });
|
|
58362
58499
|
for (const entry of entries) {
|
|
58363
|
-
const fullPath =
|
|
58500
|
+
const fullPath = path47.join(dirPath, entry.name);
|
|
58364
58501
|
if (entry.isDirectory()) {
|
|
58365
58502
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58366
58503
|
continue;
|
|
@@ -58368,7 +58505,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58368
58505
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58369
58506
|
} else if (entry.isFile()) {
|
|
58370
58507
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
58371
|
-
const ext =
|
|
58508
|
+
const ext = path47.extname(entry.name).toLowerCase();
|
|
58372
58509
|
const validExts = [
|
|
58373
58510
|
".ts",
|
|
58374
58511
|
".tsx",
|
|
@@ -58404,7 +58541,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58404
58541
|
continue;
|
|
58405
58542
|
}
|
|
58406
58543
|
try {
|
|
58407
|
-
const content =
|
|
58544
|
+
const content = fs35.readFileSync(fullPath, "utf-8");
|
|
58408
58545
|
const lines = countCodeLines(content);
|
|
58409
58546
|
callback(lines);
|
|
58410
58547
|
} catch {}
|
|
@@ -58583,8 +58720,10 @@ async function getGitChurn(days, directory) {
|
|
|
58583
58720
|
stderr: "pipe",
|
|
58584
58721
|
cwd: directory
|
|
58585
58722
|
});
|
|
58586
|
-
const stdout = await
|
|
58587
|
-
|
|
58723
|
+
const [stdout] = await Promise.all([
|
|
58724
|
+
new Response(proc.stdout).text(),
|
|
58725
|
+
proc.exited
|
|
58726
|
+
]);
|
|
58588
58727
|
const lines = stdout.split(/\r?\n/);
|
|
58589
58728
|
for (const line of lines) {
|
|
58590
58729
|
const normalizedPath = line.replace(/\\/g, "/");
|
|
@@ -58603,11 +58742,11 @@ async function getGitChurn(days, directory) {
|
|
|
58603
58742
|
}
|
|
58604
58743
|
function getComplexityForFile2(filePath) {
|
|
58605
58744
|
try {
|
|
58606
|
-
const stat2 =
|
|
58745
|
+
const stat2 = fs36.statSync(filePath);
|
|
58607
58746
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
58608
58747
|
return null;
|
|
58609
58748
|
}
|
|
58610
|
-
const content =
|
|
58749
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
58611
58750
|
return estimateCyclomaticComplexity(content);
|
|
58612
58751
|
} catch {
|
|
58613
58752
|
return null;
|
|
@@ -58618,7 +58757,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58618
58757
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
58619
58758
|
const filteredChurn = new Map;
|
|
58620
58759
|
for (const [file3, count] of churnMap) {
|
|
58621
|
-
const ext =
|
|
58760
|
+
const ext = path48.extname(file3).toLowerCase();
|
|
58622
58761
|
if (extSet.has(ext)) {
|
|
58623
58762
|
filteredChurn.set(file3, count);
|
|
58624
58763
|
}
|
|
@@ -58628,8 +58767,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
58628
58767
|
let analyzedFiles = 0;
|
|
58629
58768
|
for (const [file3, churnCount] of filteredChurn) {
|
|
58630
58769
|
let fullPath = file3;
|
|
58631
|
-
if (!
|
|
58632
|
-
fullPath =
|
|
58770
|
+
if (!fs36.existsSync(fullPath)) {
|
|
58771
|
+
fullPath = path48.join(cwd, file3);
|
|
58633
58772
|
}
|
|
58634
58773
|
const complexity = getComplexityForFile2(fullPath);
|
|
58635
58774
|
if (complexity !== null) {
|
|
@@ -58837,8 +58976,8 @@ var curator_analyze = createSwarmTool({
|
|
|
58837
58976
|
});
|
|
58838
58977
|
// src/tools/declare-scope.ts
|
|
58839
58978
|
init_tool();
|
|
58840
|
-
import * as
|
|
58841
|
-
import * as
|
|
58979
|
+
import * as fs37 from "fs";
|
|
58980
|
+
import * as path49 from "path";
|
|
58842
58981
|
init_create_tool();
|
|
58843
58982
|
function validateTaskIdFormat(taskId) {
|
|
58844
58983
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -58917,8 +59056,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58917
59056
|
};
|
|
58918
59057
|
}
|
|
58919
59058
|
}
|
|
58920
|
-
normalizedDir =
|
|
58921
|
-
const pathParts = normalizedDir.split(
|
|
59059
|
+
normalizedDir = path49.normalize(args2.working_directory);
|
|
59060
|
+
const pathParts = normalizedDir.split(path49.sep);
|
|
58922
59061
|
if (pathParts.includes("..")) {
|
|
58923
59062
|
return {
|
|
58924
59063
|
success: false,
|
|
@@ -58928,11 +59067,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58928
59067
|
]
|
|
58929
59068
|
};
|
|
58930
59069
|
}
|
|
58931
|
-
const resolvedDir =
|
|
59070
|
+
const resolvedDir = path49.resolve(normalizedDir);
|
|
58932
59071
|
try {
|
|
58933
|
-
const realPath =
|
|
58934
|
-
const planPath2 =
|
|
58935
|
-
if (!
|
|
59072
|
+
const realPath = fs37.realpathSync(resolvedDir);
|
|
59073
|
+
const planPath2 = path49.join(realPath, ".swarm", "plan.json");
|
|
59074
|
+
if (!fs37.existsSync(planPath2)) {
|
|
58936
59075
|
return {
|
|
58937
59076
|
success: false,
|
|
58938
59077
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -58955,8 +59094,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58955
59094
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
58956
59095
|
}
|
|
58957
59096
|
const directory = normalizedDir || fallbackDir;
|
|
58958
|
-
const planPath =
|
|
58959
|
-
if (!
|
|
59097
|
+
const planPath = path49.resolve(directory, ".swarm", "plan.json");
|
|
59098
|
+
if (!fs37.existsSync(planPath)) {
|
|
58960
59099
|
return {
|
|
58961
59100
|
success: false,
|
|
58962
59101
|
message: "No plan found",
|
|
@@ -58965,7 +59104,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58965
59104
|
}
|
|
58966
59105
|
let planContent;
|
|
58967
59106
|
try {
|
|
58968
|
-
planContent = JSON.parse(
|
|
59107
|
+
planContent = JSON.parse(fs37.readFileSync(planPath, "utf-8"));
|
|
58969
59108
|
} catch {
|
|
58970
59109
|
return {
|
|
58971
59110
|
success: false,
|
|
@@ -58997,8 +59136,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
58997
59136
|
const normalizeErrors = [];
|
|
58998
59137
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
58999
59138
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
59000
|
-
if (
|
|
59001
|
-
const relativePath =
|
|
59139
|
+
if (path49.isAbsolute(file3)) {
|
|
59140
|
+
const relativePath = path49.relative(dir, file3).replace(/\\/g, "/");
|
|
59002
59141
|
if (relativePath.startsWith("..")) {
|
|
59003
59142
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
59004
59143
|
return file3;
|
|
@@ -59324,20 +59463,20 @@ function validateBase(base) {
|
|
|
59324
59463
|
function validatePaths(paths) {
|
|
59325
59464
|
if (!paths)
|
|
59326
59465
|
return null;
|
|
59327
|
-
for (const
|
|
59328
|
-
if (!
|
|
59466
|
+
for (const path51 of paths) {
|
|
59467
|
+
if (!path51 || path51.length === 0) {
|
|
59329
59468
|
return "empty path not allowed";
|
|
59330
59469
|
}
|
|
59331
|
-
if (
|
|
59470
|
+
if (path51.length > MAX_PATH_LENGTH) {
|
|
59332
59471
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
59333
59472
|
}
|
|
59334
|
-
if (SHELL_METACHARACTERS2.test(
|
|
59473
|
+
if (SHELL_METACHARACTERS2.test(path51)) {
|
|
59335
59474
|
return "path contains shell metacharacters";
|
|
59336
59475
|
}
|
|
59337
|
-
if (
|
|
59476
|
+
if (path51.startsWith("-")) {
|
|
59338
59477
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
59339
59478
|
}
|
|
59340
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
59479
|
+
if (CONTROL_CHAR_PATTERN2.test(path51)) {
|
|
59341
59480
|
return "path contains control characters";
|
|
59342
59481
|
}
|
|
59343
59482
|
}
|
|
@@ -59418,8 +59557,8 @@ var diff = createSwarmTool({
|
|
|
59418
59557
|
if (parts2.length >= 3) {
|
|
59419
59558
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
59420
59559
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
59421
|
-
const
|
|
59422
|
-
files.push({ path:
|
|
59560
|
+
const path51 = parts2[2];
|
|
59561
|
+
files.push({ path: path51, additions, deletions });
|
|
59423
59562
|
}
|
|
59424
59563
|
}
|
|
59425
59564
|
const contractChanges = [];
|
|
@@ -59701,8 +59840,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
59701
59840
|
// src/tools/evidence-check.ts
|
|
59702
59841
|
init_dist();
|
|
59703
59842
|
init_create_tool();
|
|
59704
|
-
import * as
|
|
59705
|
-
import * as
|
|
59843
|
+
import * as fs38 from "fs";
|
|
59844
|
+
import * as path51 from "path";
|
|
59706
59845
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
59707
59846
|
var MAX_EVIDENCE_FILES = 1000;
|
|
59708
59847
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -59729,9 +59868,9 @@ function validateRequiredTypes(input) {
|
|
|
59729
59868
|
return null;
|
|
59730
59869
|
}
|
|
59731
59870
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
59732
|
-
const normalizedCwd =
|
|
59733
|
-
const swarmPath =
|
|
59734
|
-
const normalizedPath =
|
|
59871
|
+
const normalizedCwd = path51.resolve(cwd);
|
|
59872
|
+
const swarmPath = path51.join(normalizedCwd, ".swarm");
|
|
59873
|
+
const normalizedPath = path51.resolve(filePath);
|
|
59735
59874
|
return normalizedPath.startsWith(swarmPath);
|
|
59736
59875
|
}
|
|
59737
59876
|
function parseCompletedTasks(planContent) {
|
|
@@ -59747,12 +59886,12 @@ function parseCompletedTasks(planContent) {
|
|
|
59747
59886
|
}
|
|
59748
59887
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
59749
59888
|
const evidence = [];
|
|
59750
|
-
if (!
|
|
59889
|
+
if (!fs38.existsSync(evidenceDir) || !fs38.statSync(evidenceDir).isDirectory()) {
|
|
59751
59890
|
return evidence;
|
|
59752
59891
|
}
|
|
59753
59892
|
let files;
|
|
59754
59893
|
try {
|
|
59755
|
-
files =
|
|
59894
|
+
files = fs38.readdirSync(evidenceDir);
|
|
59756
59895
|
} catch {
|
|
59757
59896
|
return evidence;
|
|
59758
59897
|
}
|
|
@@ -59761,14 +59900,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59761
59900
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
59762
59901
|
continue;
|
|
59763
59902
|
}
|
|
59764
|
-
const filePath =
|
|
59903
|
+
const filePath = path51.join(evidenceDir, filename);
|
|
59765
59904
|
try {
|
|
59766
|
-
const resolvedPath =
|
|
59767
|
-
const evidenceDirResolved =
|
|
59905
|
+
const resolvedPath = path51.resolve(filePath);
|
|
59906
|
+
const evidenceDirResolved = path51.resolve(evidenceDir);
|
|
59768
59907
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
59769
59908
|
continue;
|
|
59770
59909
|
}
|
|
59771
|
-
const stat2 =
|
|
59910
|
+
const stat2 = fs38.lstatSync(filePath);
|
|
59772
59911
|
if (!stat2.isFile()) {
|
|
59773
59912
|
continue;
|
|
59774
59913
|
}
|
|
@@ -59777,7 +59916,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59777
59916
|
}
|
|
59778
59917
|
let fileStat;
|
|
59779
59918
|
try {
|
|
59780
|
-
fileStat =
|
|
59919
|
+
fileStat = fs38.statSync(filePath);
|
|
59781
59920
|
if (fileStat.size > MAX_FILE_SIZE_BYTES4) {
|
|
59782
59921
|
continue;
|
|
59783
59922
|
}
|
|
@@ -59786,7 +59925,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
59786
59925
|
}
|
|
59787
59926
|
let content;
|
|
59788
59927
|
try {
|
|
59789
|
-
content =
|
|
59928
|
+
content = fs38.readFileSync(filePath, "utf-8");
|
|
59790
59929
|
} catch {
|
|
59791
59930
|
continue;
|
|
59792
59931
|
}
|
|
@@ -59882,7 +60021,7 @@ var evidence_check = createSwarmTool({
|
|
|
59882
60021
|
return JSON.stringify(errorResult, null, 2);
|
|
59883
60022
|
}
|
|
59884
60023
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
59885
|
-
const planPath =
|
|
60024
|
+
const planPath = path51.join(cwd, PLAN_FILE);
|
|
59886
60025
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
59887
60026
|
const errorResult = {
|
|
59888
60027
|
error: "plan file path validation failed",
|
|
@@ -59896,7 +60035,7 @@ var evidence_check = createSwarmTool({
|
|
|
59896
60035
|
}
|
|
59897
60036
|
let planContent;
|
|
59898
60037
|
try {
|
|
59899
|
-
planContent =
|
|
60038
|
+
planContent = fs38.readFileSync(planPath, "utf-8");
|
|
59900
60039
|
} catch {
|
|
59901
60040
|
const result2 = {
|
|
59902
60041
|
message: "No completed tasks found in plan.",
|
|
@@ -59914,7 +60053,7 @@ var evidence_check = createSwarmTool({
|
|
|
59914
60053
|
};
|
|
59915
60054
|
return JSON.stringify(result2, null, 2);
|
|
59916
60055
|
}
|
|
59917
|
-
const evidenceDir =
|
|
60056
|
+
const evidenceDir = path51.join(cwd, EVIDENCE_DIR2);
|
|
59918
60057
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
59919
60058
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
59920
60059
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -59931,8 +60070,8 @@ var evidence_check = createSwarmTool({
|
|
|
59931
60070
|
// src/tools/file-extractor.ts
|
|
59932
60071
|
init_tool();
|
|
59933
60072
|
init_create_tool();
|
|
59934
|
-
import * as
|
|
59935
|
-
import * as
|
|
60073
|
+
import * as fs39 from "fs";
|
|
60074
|
+
import * as path52 from "path";
|
|
59936
60075
|
var EXT_MAP = {
|
|
59937
60076
|
python: ".py",
|
|
59938
60077
|
py: ".py",
|
|
@@ -59994,8 +60133,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
59994
60133
|
execute: async (args2, directory) => {
|
|
59995
60134
|
const { content, output_dir, prefix } = args2;
|
|
59996
60135
|
const targetDir = output_dir || directory;
|
|
59997
|
-
if (!
|
|
59998
|
-
|
|
60136
|
+
if (!fs39.existsSync(targetDir)) {
|
|
60137
|
+
fs39.mkdirSync(targetDir, { recursive: true });
|
|
59999
60138
|
}
|
|
60000
60139
|
if (!content) {
|
|
60001
60140
|
return "Error: content is required";
|
|
@@ -60013,16 +60152,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
60013
60152
|
if (prefix) {
|
|
60014
60153
|
filename = `${prefix}_${filename}`;
|
|
60015
60154
|
}
|
|
60016
|
-
let filepath =
|
|
60017
|
-
const base =
|
|
60018
|
-
const ext =
|
|
60155
|
+
let filepath = path52.join(targetDir, filename);
|
|
60156
|
+
const base = path52.basename(filepath, path52.extname(filepath));
|
|
60157
|
+
const ext = path52.extname(filepath);
|
|
60019
60158
|
let counter = 1;
|
|
60020
|
-
while (
|
|
60021
|
-
filepath =
|
|
60159
|
+
while (fs39.existsSync(filepath)) {
|
|
60160
|
+
filepath = path52.join(targetDir, `${base}_${counter}${ext}`);
|
|
60022
60161
|
counter++;
|
|
60023
60162
|
}
|
|
60024
60163
|
try {
|
|
60025
|
-
|
|
60164
|
+
fs39.writeFileSync(filepath, code.trim(), "utf-8");
|
|
60026
60165
|
savedFiles.push(filepath);
|
|
60027
60166
|
} catch (error93) {
|
|
60028
60167
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -60052,7 +60191,7 @@ init_create_tool();
|
|
|
60052
60191
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
60053
60192
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
60054
60193
|
var GITINGEST_MAX_RETRIES = 2;
|
|
60055
|
-
var delay = (ms) => new Promise((
|
|
60194
|
+
var delay = (ms) => new Promise((resolve18) => setTimeout(resolve18, ms));
|
|
60056
60195
|
async function fetchGitingest(args2) {
|
|
60057
60196
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
60058
60197
|
try {
|
|
@@ -60138,8 +60277,8 @@ var gitingest = createSwarmTool({
|
|
|
60138
60277
|
// src/tools/imports.ts
|
|
60139
60278
|
init_dist();
|
|
60140
60279
|
init_create_tool();
|
|
60141
|
-
import * as
|
|
60142
|
-
import * as
|
|
60280
|
+
import * as fs40 from "fs";
|
|
60281
|
+
import * as path53 from "path";
|
|
60143
60282
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
60144
60283
|
var MAX_SYMBOL_LENGTH = 256;
|
|
60145
60284
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
@@ -60187,7 +60326,7 @@ function validateSymbolInput(symbol3) {
|
|
|
60187
60326
|
return null;
|
|
60188
60327
|
}
|
|
60189
60328
|
function isBinaryFile2(filePath, buffer) {
|
|
60190
|
-
const ext =
|
|
60329
|
+
const ext = path53.extname(filePath).toLowerCase();
|
|
60191
60330
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
60192
60331
|
return false;
|
|
60193
60332
|
}
|
|
@@ -60211,15 +60350,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60211
60350
|
const imports = [];
|
|
60212
60351
|
let _resolvedTarget;
|
|
60213
60352
|
try {
|
|
60214
|
-
_resolvedTarget =
|
|
60353
|
+
_resolvedTarget = path53.resolve(targetFile);
|
|
60215
60354
|
} catch {
|
|
60216
60355
|
_resolvedTarget = targetFile;
|
|
60217
60356
|
}
|
|
60218
|
-
const targetBasename =
|
|
60357
|
+
const targetBasename = path53.basename(targetFile, path53.extname(targetFile));
|
|
60219
60358
|
const targetWithExt = targetFile;
|
|
60220
60359
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
60221
|
-
const normalizedTargetWithExt =
|
|
60222
|
-
const normalizedTargetWithoutExt =
|
|
60360
|
+
const normalizedTargetWithExt = path53.normalize(targetWithExt).replace(/\\/g, "/");
|
|
60361
|
+
const normalizedTargetWithoutExt = path53.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
60223
60362
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
60224
60363
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
60225
60364
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -60242,9 +60381,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
60242
60381
|
}
|
|
60243
60382
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
60244
60383
|
let isMatch = false;
|
|
60245
|
-
const _targetDir =
|
|
60246
|
-
const targetExt =
|
|
60247
|
-
const targetBasenameNoExt =
|
|
60384
|
+
const _targetDir = path53.dirname(targetFile);
|
|
60385
|
+
const targetExt = path53.extname(targetFile);
|
|
60386
|
+
const targetBasenameNoExt = path53.basename(targetFile, targetExt);
|
|
60248
60387
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
60249
60388
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
60250
60389
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -60301,7 +60440,7 @@ var SKIP_DIRECTORIES3 = new Set([
|
|
|
60301
60440
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
60302
60441
|
let entries;
|
|
60303
60442
|
try {
|
|
60304
|
-
entries =
|
|
60443
|
+
entries = fs40.readdirSync(dir);
|
|
60305
60444
|
} catch (e) {
|
|
60306
60445
|
stats.fileErrors.push({
|
|
60307
60446
|
path: dir,
|
|
@@ -60312,13 +60451,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60312
60451
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
60313
60452
|
for (const entry of entries) {
|
|
60314
60453
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
60315
|
-
stats.skippedDirs.push(
|
|
60454
|
+
stats.skippedDirs.push(path53.join(dir, entry));
|
|
60316
60455
|
continue;
|
|
60317
60456
|
}
|
|
60318
|
-
const fullPath =
|
|
60457
|
+
const fullPath = path53.join(dir, entry);
|
|
60319
60458
|
let stat2;
|
|
60320
60459
|
try {
|
|
60321
|
-
stat2 =
|
|
60460
|
+
stat2 = fs40.statSync(fullPath);
|
|
60322
60461
|
} catch (e) {
|
|
60323
60462
|
stats.fileErrors.push({
|
|
60324
60463
|
path: fullPath,
|
|
@@ -60329,7 +60468,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
60329
60468
|
if (stat2.isDirectory()) {
|
|
60330
60469
|
findSourceFiles(fullPath, files, stats);
|
|
60331
60470
|
} else if (stat2.isFile()) {
|
|
60332
|
-
const ext =
|
|
60471
|
+
const ext = path53.extname(fullPath).toLowerCase();
|
|
60333
60472
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
60334
60473
|
files.push(fullPath);
|
|
60335
60474
|
}
|
|
@@ -60386,8 +60525,8 @@ var imports = createSwarmTool({
|
|
|
60386
60525
|
return JSON.stringify(errorResult, null, 2);
|
|
60387
60526
|
}
|
|
60388
60527
|
try {
|
|
60389
|
-
const targetFile =
|
|
60390
|
-
if (!
|
|
60528
|
+
const targetFile = path53.resolve(file3);
|
|
60529
|
+
if (!fs40.existsSync(targetFile)) {
|
|
60391
60530
|
const errorResult = {
|
|
60392
60531
|
error: `target file not found: ${file3}`,
|
|
60393
60532
|
target: file3,
|
|
@@ -60397,7 +60536,7 @@ var imports = createSwarmTool({
|
|
|
60397
60536
|
};
|
|
60398
60537
|
return JSON.stringify(errorResult, null, 2);
|
|
60399
60538
|
}
|
|
60400
|
-
const targetStat =
|
|
60539
|
+
const targetStat = fs40.statSync(targetFile);
|
|
60401
60540
|
if (!targetStat.isFile()) {
|
|
60402
60541
|
const errorResult = {
|
|
60403
60542
|
error: "target must be a file, not a directory",
|
|
@@ -60408,7 +60547,7 @@ var imports = createSwarmTool({
|
|
|
60408
60547
|
};
|
|
60409
60548
|
return JSON.stringify(errorResult, null, 2);
|
|
60410
60549
|
}
|
|
60411
|
-
const baseDir =
|
|
60550
|
+
const baseDir = path53.dirname(targetFile);
|
|
60412
60551
|
const scanStats = {
|
|
60413
60552
|
skippedDirs: [],
|
|
60414
60553
|
skippedFiles: 0,
|
|
@@ -60423,12 +60562,12 @@ var imports = createSwarmTool({
|
|
|
60423
60562
|
if (consumers.length >= MAX_CONSUMERS)
|
|
60424
60563
|
break;
|
|
60425
60564
|
try {
|
|
60426
|
-
const stat2 =
|
|
60565
|
+
const stat2 = fs40.statSync(filePath);
|
|
60427
60566
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
60428
60567
|
skippedFileCount++;
|
|
60429
60568
|
continue;
|
|
60430
60569
|
}
|
|
60431
|
-
const buffer =
|
|
60570
|
+
const buffer = fs40.readFileSync(filePath);
|
|
60432
60571
|
if (isBinaryFile2(filePath, buffer)) {
|
|
60433
60572
|
skippedFileCount++;
|
|
60434
60573
|
continue;
|
|
@@ -61017,11 +61156,12 @@ init_dist();
|
|
|
61017
61156
|
init_config();
|
|
61018
61157
|
init_schema();
|
|
61019
61158
|
init_manager();
|
|
61020
|
-
import * as
|
|
61021
|
-
import * as
|
|
61159
|
+
import * as fs41 from "fs";
|
|
61160
|
+
import * as path54 from "path";
|
|
61022
61161
|
init_utils2();
|
|
61023
61162
|
init_telemetry();
|
|
61024
61163
|
init_create_tool();
|
|
61164
|
+
init_resolve_working_directory();
|
|
61025
61165
|
function safeWarn(message, error93) {
|
|
61026
61166
|
try {
|
|
61027
61167
|
console.warn(message, error93 instanceof Error ? error93.message : String(error93));
|
|
@@ -61238,11 +61378,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61238
61378
|
safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
|
|
61239
61379
|
}
|
|
61240
61380
|
try {
|
|
61241
|
-
const driftEvidencePath =
|
|
61381
|
+
const driftEvidencePath = path54.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
61242
61382
|
let driftVerdictFound = false;
|
|
61243
61383
|
let driftVerdictApproved = false;
|
|
61244
61384
|
try {
|
|
61245
|
-
const driftEvidenceContent =
|
|
61385
|
+
const driftEvidenceContent = fs41.readFileSync(driftEvidencePath, "utf-8");
|
|
61246
61386
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
61247
61387
|
const entries = driftEvidence.entries ?? [];
|
|
61248
61388
|
for (const entry of entries) {
|
|
@@ -61272,14 +61412,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61272
61412
|
driftVerdictFound = false;
|
|
61273
61413
|
}
|
|
61274
61414
|
if (!driftVerdictFound) {
|
|
61275
|
-
const specPath =
|
|
61276
|
-
const specExists =
|
|
61415
|
+
const specPath = path54.join(dir, ".swarm", "spec.md");
|
|
61416
|
+
const specExists = fs41.existsSync(specPath);
|
|
61277
61417
|
if (!specExists) {
|
|
61278
61418
|
let incompleteTaskCount = 0;
|
|
61279
61419
|
let planPhaseFound = false;
|
|
61280
61420
|
try {
|
|
61281
61421
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61282
|
-
const planRaw =
|
|
61422
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61283
61423
|
const plan = JSON.parse(planRaw);
|
|
61284
61424
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61285
61425
|
if (targetPhase) {
|
|
@@ -61346,7 +61486,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61346
61486
|
};
|
|
61347
61487
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
61348
61488
|
try {
|
|
61349
|
-
const projectName =
|
|
61489
|
+
const projectName = path54.basename(dir);
|
|
61350
61490
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
61351
61491
|
if (curationResult) {
|
|
61352
61492
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -61391,7 +61531,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61391
61531
|
let phaseRequiredAgents;
|
|
61392
61532
|
try {
|
|
61393
61533
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61394
|
-
const planRaw =
|
|
61534
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61395
61535
|
const plan = JSON.parse(planRaw);
|
|
61396
61536
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61397
61537
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -61406,7 +61546,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61406
61546
|
if (agentsMissing.length > 0) {
|
|
61407
61547
|
try {
|
|
61408
61548
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61409
|
-
const planRaw =
|
|
61549
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61410
61550
|
const plan = JSON.parse(planRaw);
|
|
61411
61551
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61412
61552
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -61437,7 +61577,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61437
61577
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
61438
61578
|
try {
|
|
61439
61579
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61440
|
-
const planRaw =
|
|
61580
|
+
const planRaw = fs41.readFileSync(planPath, "utf-8");
|
|
61441
61581
|
const plan = JSON.parse(planRaw);
|
|
61442
61582
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
61443
61583
|
if (targetPhase) {
|
|
@@ -61475,7 +61615,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61475
61615
|
};
|
|
61476
61616
|
try {
|
|
61477
61617
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
61478
|
-
|
|
61618
|
+
fs41.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
61479
61619
|
`, "utf-8");
|
|
61480
61620
|
} catch (writeError) {
|
|
61481
61621
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -61499,12 +61639,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61499
61639
|
}
|
|
61500
61640
|
try {
|
|
61501
61641
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
61502
|
-
const planJson =
|
|
61642
|
+
const planJson = fs41.readFileSync(planPath, "utf-8");
|
|
61503
61643
|
const plan = JSON.parse(planJson);
|
|
61504
61644
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
61505
61645
|
if (phaseObj) {
|
|
61506
61646
|
phaseObj.status = "completed";
|
|
61507
|
-
|
|
61647
|
+
fs41.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
61508
61648
|
`, "utf-8");
|
|
61509
61649
|
}
|
|
61510
61650
|
} catch (error93) {
|
|
@@ -61531,16 +61671,19 @@ var phase_complete = createSwarmTool({
|
|
|
61531
61671
|
args: {
|
|
61532
61672
|
phase: tool.schema.number().int().min(1).describe("The phase number being completed \u2014 a positive integer (e.g., 1, 2, 3)"),
|
|
61533
61673
|
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)")
|
|
61674
|
+
sessionID: tool.schema.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),
|
|
61675
|
+
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
61676
|
},
|
|
61536
61677
|
execute: async (args2, directory, ctx) => {
|
|
61537
61678
|
let phaseCompleteArgs;
|
|
61679
|
+
let workingDirInput;
|
|
61538
61680
|
try {
|
|
61539
61681
|
phaseCompleteArgs = {
|
|
61540
61682
|
phase: Number(args2.phase),
|
|
61541
61683
|
summary: args2.summary !== undefined ? String(args2.summary) : undefined,
|
|
61542
61684
|
sessionID: ctx?.sessionID ?? (args2.sessionID !== undefined ? String(args2.sessionID) : undefined)
|
|
61543
61685
|
};
|
|
61686
|
+
workingDirInput = args2.working_directory !== undefined ? String(args2.working_directory) : undefined;
|
|
61544
61687
|
} catch {
|
|
61545
61688
|
return JSON.stringify({
|
|
61546
61689
|
success: false,
|
|
@@ -61550,7 +61693,17 @@ var phase_complete = createSwarmTool({
|
|
|
61550
61693
|
warnings: ["Failed to parse arguments"]
|
|
61551
61694
|
}, null, 2);
|
|
61552
61695
|
}
|
|
61553
|
-
|
|
61696
|
+
const dirResult = resolveWorkingDirectory(workingDirInput, directory);
|
|
61697
|
+
if (!dirResult.success) {
|
|
61698
|
+
return JSON.stringify({
|
|
61699
|
+
success: false,
|
|
61700
|
+
phase: phaseCompleteArgs.phase,
|
|
61701
|
+
message: dirResult.message,
|
|
61702
|
+
agentsDispatched: [],
|
|
61703
|
+
warnings: [dirResult.message]
|
|
61704
|
+
}, null, 2);
|
|
61705
|
+
}
|
|
61706
|
+
return executePhaseComplete(phaseCompleteArgs, dirResult.directory, dirResult.directory);
|
|
61554
61707
|
}
|
|
61555
61708
|
});
|
|
61556
61709
|
// src/tools/pkg-audit.ts
|
|
@@ -61558,8 +61711,8 @@ init_dist();
|
|
|
61558
61711
|
init_discovery();
|
|
61559
61712
|
init_utils();
|
|
61560
61713
|
init_create_tool();
|
|
61561
|
-
import * as
|
|
61562
|
-
import * as
|
|
61714
|
+
import * as fs42 from "fs";
|
|
61715
|
+
import * as path55 from "path";
|
|
61563
61716
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
61564
61717
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
61565
61718
|
function isValidEcosystem(value) {
|
|
@@ -61577,28 +61730,28 @@ function validateArgs3(args2) {
|
|
|
61577
61730
|
function detectEcosystems(directory) {
|
|
61578
61731
|
const ecosystems = [];
|
|
61579
61732
|
const cwd = directory;
|
|
61580
|
-
if (
|
|
61733
|
+
if (fs42.existsSync(path55.join(cwd, "package.json"))) {
|
|
61581
61734
|
ecosystems.push("npm");
|
|
61582
61735
|
}
|
|
61583
|
-
if (
|
|
61736
|
+
if (fs42.existsSync(path55.join(cwd, "pyproject.toml")) || fs42.existsSync(path55.join(cwd, "requirements.txt"))) {
|
|
61584
61737
|
ecosystems.push("pip");
|
|
61585
61738
|
}
|
|
61586
|
-
if (
|
|
61739
|
+
if (fs42.existsSync(path55.join(cwd, "Cargo.toml"))) {
|
|
61587
61740
|
ecosystems.push("cargo");
|
|
61588
61741
|
}
|
|
61589
|
-
if (
|
|
61742
|
+
if (fs42.existsSync(path55.join(cwd, "go.mod"))) {
|
|
61590
61743
|
ecosystems.push("go");
|
|
61591
61744
|
}
|
|
61592
61745
|
try {
|
|
61593
|
-
const files =
|
|
61746
|
+
const files = fs42.readdirSync(cwd);
|
|
61594
61747
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
61595
61748
|
ecosystems.push("dotnet");
|
|
61596
61749
|
}
|
|
61597
61750
|
} catch {}
|
|
61598
|
-
if (
|
|
61751
|
+
if (fs42.existsSync(path55.join(cwd, "Gemfile")) || fs42.existsSync(path55.join(cwd, "Gemfile.lock"))) {
|
|
61599
61752
|
ecosystems.push("ruby");
|
|
61600
61753
|
}
|
|
61601
|
-
if (
|
|
61754
|
+
if (fs42.existsSync(path55.join(cwd, "pubspec.yaml"))) {
|
|
61602
61755
|
ecosystems.push("dart");
|
|
61603
61756
|
}
|
|
61604
61757
|
return ecosystems;
|
|
@@ -61611,7 +61764,7 @@ async function runNpmAudit(directory) {
|
|
|
61611
61764
|
stderr: "pipe",
|
|
61612
61765
|
cwd: directory
|
|
61613
61766
|
});
|
|
61614
|
-
const timeoutPromise = new Promise((
|
|
61767
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61615
61768
|
const result = await Promise.race([
|
|
61616
61769
|
Promise.all([
|
|
61617
61770
|
new Response(proc.stdout).text(),
|
|
@@ -61734,7 +61887,7 @@ async function runPipAudit(directory) {
|
|
|
61734
61887
|
stderr: "pipe",
|
|
61735
61888
|
cwd: directory
|
|
61736
61889
|
});
|
|
61737
|
-
const timeoutPromise = new Promise((
|
|
61890
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61738
61891
|
const result = await Promise.race([
|
|
61739
61892
|
Promise.all([
|
|
61740
61893
|
new Response(proc.stdout).text(),
|
|
@@ -61865,7 +62018,7 @@ async function runCargoAudit(directory) {
|
|
|
61865
62018
|
stderr: "pipe",
|
|
61866
62019
|
cwd: directory
|
|
61867
62020
|
});
|
|
61868
|
-
const timeoutPromise = new Promise((
|
|
62021
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61869
62022
|
const result = await Promise.race([
|
|
61870
62023
|
Promise.all([
|
|
61871
62024
|
new Response(proc.stdout).text(),
|
|
@@ -61992,7 +62145,7 @@ async function runGoAudit(directory) {
|
|
|
61992
62145
|
stderr: "pipe",
|
|
61993
62146
|
cwd: directory
|
|
61994
62147
|
});
|
|
61995
|
-
const timeoutPromise = new Promise((
|
|
62148
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
61996
62149
|
const result = await Promise.race([
|
|
61997
62150
|
Promise.all([
|
|
61998
62151
|
new Response(proc.stdout).text(),
|
|
@@ -62128,7 +62281,7 @@ async function runDotnetAudit(directory) {
|
|
|
62128
62281
|
stderr: "pipe",
|
|
62129
62282
|
cwd: directory
|
|
62130
62283
|
});
|
|
62131
|
-
const timeoutPromise = new Promise((
|
|
62284
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
62132
62285
|
const result = await Promise.race([
|
|
62133
62286
|
Promise.all([
|
|
62134
62287
|
new Response(proc.stdout).text(),
|
|
@@ -62247,7 +62400,7 @@ async function runBundleAudit(directory) {
|
|
|
62247
62400
|
stderr: "pipe",
|
|
62248
62401
|
cwd: directory
|
|
62249
62402
|
});
|
|
62250
|
-
const timeoutPromise = new Promise((
|
|
62403
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
62251
62404
|
const result = await Promise.race([
|
|
62252
62405
|
Promise.all([
|
|
62253
62406
|
new Response(proc.stdout).text(),
|
|
@@ -62394,7 +62547,7 @@ async function runDartAudit(directory) {
|
|
|
62394
62547
|
stderr: "pipe",
|
|
62395
62548
|
cwd: directory
|
|
62396
62549
|
});
|
|
62397
|
-
const timeoutPromise = new Promise((
|
|
62550
|
+
const timeoutPromise = new Promise((resolve19) => setTimeout(() => resolve19("timeout"), AUDIT_TIMEOUT_MS));
|
|
62398
62551
|
const result = await Promise.race([
|
|
62399
62552
|
Promise.all([
|
|
62400
62553
|
new Response(proc.stdout).text(),
|
|
@@ -62619,8 +62772,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
62619
62772
|
]);
|
|
62620
62773
|
// src/tools/pre-check-batch.ts
|
|
62621
62774
|
init_dist();
|
|
62622
|
-
import * as
|
|
62623
|
-
import * as
|
|
62775
|
+
import * as fs44 from "fs";
|
|
62776
|
+
import * as path57 from "path";
|
|
62624
62777
|
|
|
62625
62778
|
// node_modules/yocto-queue/index.js
|
|
62626
62779
|
class Node2 {
|
|
@@ -62711,26 +62864,26 @@ function pLimit(concurrency) {
|
|
|
62711
62864
|
activeCount--;
|
|
62712
62865
|
resumeNext();
|
|
62713
62866
|
};
|
|
62714
|
-
const run2 = async (function_,
|
|
62867
|
+
const run2 = async (function_, resolve19, arguments_2) => {
|
|
62715
62868
|
const result = (async () => function_(...arguments_2))();
|
|
62716
|
-
|
|
62869
|
+
resolve19(result);
|
|
62717
62870
|
try {
|
|
62718
62871
|
await result;
|
|
62719
62872
|
} catch {}
|
|
62720
62873
|
next();
|
|
62721
62874
|
};
|
|
62722
|
-
const enqueue = (function_,
|
|
62875
|
+
const enqueue = (function_, resolve19, reject, arguments_2) => {
|
|
62723
62876
|
const queueItem = { reject };
|
|
62724
62877
|
new Promise((internalResolve) => {
|
|
62725
62878
|
queueItem.run = internalResolve;
|
|
62726
62879
|
queue.enqueue(queueItem);
|
|
62727
|
-
}).then(run2.bind(undefined, function_,
|
|
62880
|
+
}).then(run2.bind(undefined, function_, resolve19, arguments_2));
|
|
62728
62881
|
if (activeCount < concurrency) {
|
|
62729
62882
|
resumeNext();
|
|
62730
62883
|
}
|
|
62731
62884
|
};
|
|
62732
|
-
const generator = (function_, ...arguments_2) => new Promise((
|
|
62733
|
-
enqueue(function_,
|
|
62885
|
+
const generator = (function_, ...arguments_2) => new Promise((resolve19, reject) => {
|
|
62886
|
+
enqueue(function_, resolve19, reject, arguments_2);
|
|
62734
62887
|
});
|
|
62735
62888
|
Object.defineProperties(generator, {
|
|
62736
62889
|
activeCount: {
|
|
@@ -62894,8 +63047,8 @@ async function qualityBudget(input, directory) {
|
|
|
62894
63047
|
init_dist();
|
|
62895
63048
|
init_manager();
|
|
62896
63049
|
init_detector();
|
|
62897
|
-
import * as
|
|
62898
|
-
import * as
|
|
63050
|
+
import * as fs43 from "fs";
|
|
63051
|
+
import * as path56 from "path";
|
|
62899
63052
|
import { extname as extname10 } from "path";
|
|
62900
63053
|
|
|
62901
63054
|
// src/sast/rules/c.ts
|
|
@@ -63646,7 +63799,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
63646
63799
|
}
|
|
63647
63800
|
}
|
|
63648
63801
|
async function executeWithTimeout(command, args2, options) {
|
|
63649
|
-
return new Promise((
|
|
63802
|
+
return new Promise((resolve19) => {
|
|
63650
63803
|
const child = spawn2(command, args2, {
|
|
63651
63804
|
shell: false,
|
|
63652
63805
|
cwd: options.cwd
|
|
@@ -63655,7 +63808,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
63655
63808
|
let stderr = "";
|
|
63656
63809
|
const timeout = setTimeout(() => {
|
|
63657
63810
|
child.kill("SIGTERM");
|
|
63658
|
-
|
|
63811
|
+
resolve19({
|
|
63659
63812
|
stdout,
|
|
63660
63813
|
stderr: "Process timed out",
|
|
63661
63814
|
exitCode: 124
|
|
@@ -63669,7 +63822,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
63669
63822
|
});
|
|
63670
63823
|
child.on("close", (code) => {
|
|
63671
63824
|
clearTimeout(timeout);
|
|
63672
|
-
|
|
63825
|
+
resolve19({
|
|
63673
63826
|
stdout,
|
|
63674
63827
|
stderr,
|
|
63675
63828
|
exitCode: code ?? 0
|
|
@@ -63677,7 +63830,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
63677
63830
|
});
|
|
63678
63831
|
child.on("error", (err2) => {
|
|
63679
63832
|
clearTimeout(timeout);
|
|
63680
|
-
|
|
63833
|
+
resolve19({
|
|
63681
63834
|
stdout,
|
|
63682
63835
|
stderr: err2.message,
|
|
63683
63836
|
exitCode: 1
|
|
@@ -63765,17 +63918,17 @@ var SEVERITY_ORDER = {
|
|
|
63765
63918
|
};
|
|
63766
63919
|
function shouldSkipFile(filePath) {
|
|
63767
63920
|
try {
|
|
63768
|
-
const stats =
|
|
63921
|
+
const stats = fs43.statSync(filePath);
|
|
63769
63922
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
63770
63923
|
return { skip: true, reason: "file too large" };
|
|
63771
63924
|
}
|
|
63772
63925
|
if (stats.size === 0) {
|
|
63773
63926
|
return { skip: true, reason: "empty file" };
|
|
63774
63927
|
}
|
|
63775
|
-
const fd =
|
|
63928
|
+
const fd = fs43.openSync(filePath, "r");
|
|
63776
63929
|
const buffer = Buffer.alloc(8192);
|
|
63777
|
-
const bytesRead =
|
|
63778
|
-
|
|
63930
|
+
const bytesRead = fs43.readSync(fd, buffer, 0, 8192, 0);
|
|
63931
|
+
fs43.closeSync(fd);
|
|
63779
63932
|
if (bytesRead > 0) {
|
|
63780
63933
|
let nullCount = 0;
|
|
63781
63934
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -63814,7 +63967,7 @@ function countBySeverity(findings) {
|
|
|
63814
63967
|
}
|
|
63815
63968
|
function scanFileWithTierA(filePath, language) {
|
|
63816
63969
|
try {
|
|
63817
|
-
const content =
|
|
63970
|
+
const content = fs43.readFileSync(filePath, "utf-8");
|
|
63818
63971
|
const findings = executeRulesSync(filePath, content, language);
|
|
63819
63972
|
return findings.map((f) => ({
|
|
63820
63973
|
rule_id: f.rule_id,
|
|
@@ -63861,8 +64014,8 @@ async function sastScan(input, directory, config3) {
|
|
|
63861
64014
|
_filesSkipped++;
|
|
63862
64015
|
continue;
|
|
63863
64016
|
}
|
|
63864
|
-
const resolvedPath =
|
|
63865
|
-
if (!
|
|
64017
|
+
const resolvedPath = path56.isAbsolute(filePath) ? filePath : path56.resolve(directory, filePath);
|
|
64018
|
+
if (!fs43.existsSync(resolvedPath)) {
|
|
63866
64019
|
_filesSkipped++;
|
|
63867
64020
|
continue;
|
|
63868
64021
|
}
|
|
@@ -64060,18 +64213,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
64060
64213
|
let resolved;
|
|
64061
64214
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
64062
64215
|
if (isWinAbs) {
|
|
64063
|
-
resolved =
|
|
64064
|
-
} else if (
|
|
64065
|
-
resolved =
|
|
64216
|
+
resolved = path57.win32.resolve(inputPath);
|
|
64217
|
+
} else if (path57.isAbsolute(inputPath)) {
|
|
64218
|
+
resolved = path57.resolve(inputPath);
|
|
64066
64219
|
} else {
|
|
64067
|
-
resolved =
|
|
64220
|
+
resolved = path57.resolve(baseDir, inputPath);
|
|
64068
64221
|
}
|
|
64069
|
-
const workspaceResolved =
|
|
64222
|
+
const workspaceResolved = path57.resolve(workspaceDir);
|
|
64070
64223
|
let relative8;
|
|
64071
64224
|
if (isWinAbs) {
|
|
64072
|
-
relative8 =
|
|
64225
|
+
relative8 = path57.win32.relative(workspaceResolved, resolved);
|
|
64073
64226
|
} else {
|
|
64074
|
-
relative8 =
|
|
64227
|
+
relative8 = path57.relative(workspaceResolved, resolved);
|
|
64075
64228
|
}
|
|
64076
64229
|
if (relative8.startsWith("..")) {
|
|
64077
64230
|
return "path traversal detected";
|
|
@@ -64132,13 +64285,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
64132
64285
|
}
|
|
64133
64286
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
64134
64287
|
const isWindows = process.platform === "win32";
|
|
64135
|
-
const binDir =
|
|
64288
|
+
const binDir = path57.join(workspaceDir, "node_modules", ".bin");
|
|
64136
64289
|
const validatedFiles = [];
|
|
64137
64290
|
for (const file3 of files) {
|
|
64138
64291
|
if (typeof file3 !== "string") {
|
|
64139
64292
|
continue;
|
|
64140
64293
|
}
|
|
64141
|
-
const resolvedPath =
|
|
64294
|
+
const resolvedPath = path57.resolve(file3);
|
|
64142
64295
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
64143
64296
|
if (validationError) {
|
|
64144
64297
|
continue;
|
|
@@ -64156,10 +64309,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
64156
64309
|
}
|
|
64157
64310
|
let command;
|
|
64158
64311
|
if (linter === "biome") {
|
|
64159
|
-
const biomeBin = isWindows ?
|
|
64312
|
+
const biomeBin = isWindows ? path57.join(binDir, "biome.EXE") : path57.join(binDir, "biome");
|
|
64160
64313
|
command = [biomeBin, "check", ...validatedFiles];
|
|
64161
64314
|
} else {
|
|
64162
|
-
const eslintBin = isWindows ?
|
|
64315
|
+
const eslintBin = isWindows ? path57.join(binDir, "eslint.cmd") : path57.join(binDir, "eslint");
|
|
64163
64316
|
command = [eslintBin, ...validatedFiles];
|
|
64164
64317
|
}
|
|
64165
64318
|
try {
|
|
@@ -64296,7 +64449,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64296
64449
|
skippedFiles++;
|
|
64297
64450
|
continue;
|
|
64298
64451
|
}
|
|
64299
|
-
const resolvedPath =
|
|
64452
|
+
const resolvedPath = path57.resolve(file3);
|
|
64300
64453
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
64301
64454
|
if (validationError) {
|
|
64302
64455
|
skippedFiles++;
|
|
@@ -64314,14 +64467,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64314
64467
|
};
|
|
64315
64468
|
}
|
|
64316
64469
|
for (const file3 of validatedFiles) {
|
|
64317
|
-
const ext =
|
|
64470
|
+
const ext = path57.extname(file3).toLowerCase();
|
|
64318
64471
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
64319
64472
|
skippedFiles++;
|
|
64320
64473
|
continue;
|
|
64321
64474
|
}
|
|
64322
64475
|
let stat2;
|
|
64323
64476
|
try {
|
|
64324
|
-
stat2 =
|
|
64477
|
+
stat2 = fs44.statSync(file3);
|
|
64325
64478
|
} catch {
|
|
64326
64479
|
skippedFiles++;
|
|
64327
64480
|
continue;
|
|
@@ -64332,7 +64485,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
64332
64485
|
}
|
|
64333
64486
|
let content;
|
|
64334
64487
|
try {
|
|
64335
|
-
const buffer =
|
|
64488
|
+
const buffer = fs44.readFileSync(file3);
|
|
64336
64489
|
if (buffer.includes(0)) {
|
|
64337
64490
|
skippedFiles++;
|
|
64338
64491
|
continue;
|
|
@@ -64520,7 +64673,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
64520
64673
|
const preexistingFindings = [];
|
|
64521
64674
|
for (const finding of findings) {
|
|
64522
64675
|
const filePath = finding.location.file;
|
|
64523
|
-
const normalised =
|
|
64676
|
+
const normalised = path57.relative(directory, filePath).replace(/\\/g, "/");
|
|
64524
64677
|
const changedLines = changedLineRanges.get(normalised);
|
|
64525
64678
|
if (changedLines && changedLines.has(finding.location.line)) {
|
|
64526
64679
|
newFindings.push(finding);
|
|
@@ -64571,7 +64724,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
64571
64724
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
64572
64725
|
continue;
|
|
64573
64726
|
}
|
|
64574
|
-
changedFiles.push(
|
|
64727
|
+
changedFiles.push(path57.resolve(directory, file3));
|
|
64575
64728
|
}
|
|
64576
64729
|
if (changedFiles.length === 0) {
|
|
64577
64730
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -64759,7 +64912,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
64759
64912
|
};
|
|
64760
64913
|
return JSON.stringify(errorResult, null, 2);
|
|
64761
64914
|
}
|
|
64762
|
-
const resolvedDirectory =
|
|
64915
|
+
const resolvedDirectory = path57.resolve(typedArgs.directory);
|
|
64763
64916
|
const workspaceAnchor = resolvedDirectory;
|
|
64764
64917
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
64765
64918
|
if (dirError) {
|
|
@@ -64865,38 +65018,38 @@ ${paginatedContent}`;
|
|
|
64865
65018
|
});
|
|
64866
65019
|
// src/tools/save-plan.ts
|
|
64867
65020
|
init_tool();
|
|
64868
|
-
import * as
|
|
64869
|
-
import * as
|
|
65021
|
+
import * as fs46 from "fs";
|
|
65022
|
+
import * as path59 from "path";
|
|
64870
65023
|
|
|
64871
65024
|
// src/parallel/file-locks.ts
|
|
64872
|
-
import * as
|
|
64873
|
-
import * as
|
|
65025
|
+
import * as fs45 from "fs";
|
|
65026
|
+
import * as path58 from "path";
|
|
64874
65027
|
var LOCKS_DIR = ".swarm/locks";
|
|
64875
65028
|
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
64876
65029
|
function getLockFilePath(directory, filePath) {
|
|
64877
|
-
const normalized =
|
|
64878
|
-
if (!normalized.startsWith(
|
|
65030
|
+
const normalized = path58.resolve(directory, filePath);
|
|
65031
|
+
if (!normalized.startsWith(path58.resolve(directory))) {
|
|
64879
65032
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
64880
65033
|
}
|
|
64881
65034
|
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
64882
|
-
return
|
|
65035
|
+
return path58.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
64883
65036
|
}
|
|
64884
65037
|
function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
64885
65038
|
const lockPath = getLockFilePath(directory, filePath);
|
|
64886
|
-
const locksDir =
|
|
64887
|
-
if (!
|
|
64888
|
-
|
|
65039
|
+
const locksDir = path58.dirname(lockPath);
|
|
65040
|
+
if (!fs45.existsSync(locksDir)) {
|
|
65041
|
+
fs45.mkdirSync(locksDir, { recursive: true });
|
|
64889
65042
|
}
|
|
64890
|
-
if (
|
|
65043
|
+
if (fs45.existsSync(lockPath)) {
|
|
64891
65044
|
try {
|
|
64892
|
-
const existingLock = JSON.parse(
|
|
65045
|
+
const existingLock = JSON.parse(fs45.readFileSync(lockPath, "utf-8"));
|
|
64893
65046
|
if (Date.now() > existingLock.expiresAt) {
|
|
64894
|
-
|
|
65047
|
+
fs45.unlinkSync(lockPath);
|
|
64895
65048
|
} else {
|
|
64896
65049
|
return { acquired: false, existing: existingLock };
|
|
64897
65050
|
}
|
|
64898
65051
|
} catch {
|
|
64899
|
-
|
|
65052
|
+
fs45.unlinkSync(lockPath);
|
|
64900
65053
|
}
|
|
64901
65054
|
}
|
|
64902
65055
|
const lock = {
|
|
@@ -64907,24 +65060,24 @@ function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
|
64907
65060
|
expiresAt: Date.now() + LOCK_TIMEOUT_MS
|
|
64908
65061
|
};
|
|
64909
65062
|
const tempPath = `${lockPath}.tmp`;
|
|
64910
|
-
|
|
64911
|
-
|
|
65063
|
+
fs45.writeFileSync(tempPath, JSON.stringify(lock, null, 2), "utf-8");
|
|
65064
|
+
fs45.renameSync(tempPath, lockPath);
|
|
64912
65065
|
return { acquired: true, lock };
|
|
64913
65066
|
}
|
|
64914
65067
|
function releaseLock(directory, filePath, taskId) {
|
|
64915
65068
|
const lockPath = getLockFilePath(directory, filePath);
|
|
64916
|
-
if (!
|
|
65069
|
+
if (!fs45.existsSync(lockPath)) {
|
|
64917
65070
|
return true;
|
|
64918
65071
|
}
|
|
64919
65072
|
try {
|
|
64920
|
-
const lock = JSON.parse(
|
|
65073
|
+
const lock = JSON.parse(fs45.readFileSync(lockPath, "utf-8"));
|
|
64921
65074
|
if (lock.taskId === taskId) {
|
|
64922
|
-
|
|
65075
|
+
fs45.unlinkSync(lockPath);
|
|
64923
65076
|
return true;
|
|
64924
65077
|
}
|
|
64925
65078
|
return false;
|
|
64926
65079
|
} catch {
|
|
64927
|
-
|
|
65080
|
+
fs45.unlinkSync(lockPath);
|
|
64928
65081
|
return true;
|
|
64929
65082
|
}
|
|
64930
65083
|
}
|
|
@@ -65049,14 +65202,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65049
65202
|
try {
|
|
65050
65203
|
await savePlan(dir, plan);
|
|
65051
65204
|
try {
|
|
65052
|
-
const markerPath =
|
|
65205
|
+
const markerPath = path59.join(dir, ".swarm", ".plan-write-marker");
|
|
65053
65206
|
const marker = JSON.stringify({
|
|
65054
65207
|
source: "save_plan",
|
|
65055
65208
|
timestamp: new Date().toISOString(),
|
|
65056
65209
|
phases_count: plan.phases.length,
|
|
65057
65210
|
tasks_count: tasksCount
|
|
65058
65211
|
});
|
|
65059
|
-
await
|
|
65212
|
+
await fs46.promises.writeFile(markerPath, marker, "utf8");
|
|
65060
65213
|
} catch {}
|
|
65061
65214
|
const warnings = [];
|
|
65062
65215
|
let criticReviewFound = false;
|
|
@@ -65072,7 +65225,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
65072
65225
|
return {
|
|
65073
65226
|
success: true,
|
|
65074
65227
|
message: "Plan saved successfully",
|
|
65075
|
-
plan_path:
|
|
65228
|
+
plan_path: path59.join(dir, ".swarm", "plan.json"),
|
|
65076
65229
|
phases_count: plan.phases.length,
|
|
65077
65230
|
tasks_count: tasksCount,
|
|
65078
65231
|
...warnings.length > 0 ? { warnings } : {}
|
|
@@ -65114,8 +65267,8 @@ var save_plan = createSwarmTool({
|
|
|
65114
65267
|
// src/tools/sbom-generate.ts
|
|
65115
65268
|
init_dist();
|
|
65116
65269
|
init_manager();
|
|
65117
|
-
import * as
|
|
65118
|
-
import * as
|
|
65270
|
+
import * as fs47 from "fs";
|
|
65271
|
+
import * as path60 from "path";
|
|
65119
65272
|
|
|
65120
65273
|
// src/sbom/detectors/index.ts
|
|
65121
65274
|
init_utils();
|
|
@@ -65963,9 +66116,9 @@ function findManifestFiles(rootDir) {
|
|
|
65963
66116
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
65964
66117
|
function searchDir(dir) {
|
|
65965
66118
|
try {
|
|
65966
|
-
const entries =
|
|
66119
|
+
const entries = fs47.readdirSync(dir, { withFileTypes: true });
|
|
65967
66120
|
for (const entry of entries) {
|
|
65968
|
-
const fullPath =
|
|
66121
|
+
const fullPath = path60.join(dir, entry.name);
|
|
65969
66122
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
65970
66123
|
continue;
|
|
65971
66124
|
}
|
|
@@ -65974,7 +66127,7 @@ function findManifestFiles(rootDir) {
|
|
|
65974
66127
|
} else if (entry.isFile()) {
|
|
65975
66128
|
for (const pattern of patterns) {
|
|
65976
66129
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
65977
|
-
manifestFiles.push(
|
|
66130
|
+
manifestFiles.push(path60.relative(rootDir, fullPath));
|
|
65978
66131
|
break;
|
|
65979
66132
|
}
|
|
65980
66133
|
}
|
|
@@ -65990,13 +66143,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
65990
66143
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
65991
66144
|
for (const dir of directories) {
|
|
65992
66145
|
try {
|
|
65993
|
-
const entries =
|
|
66146
|
+
const entries = fs47.readdirSync(dir, { withFileTypes: true });
|
|
65994
66147
|
for (const entry of entries) {
|
|
65995
|
-
const fullPath =
|
|
66148
|
+
const fullPath = path60.join(dir, entry.name);
|
|
65996
66149
|
if (entry.isFile()) {
|
|
65997
66150
|
for (const pattern of patterns) {
|
|
65998
66151
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
65999
|
-
found.push(
|
|
66152
|
+
found.push(path60.relative(workingDir, fullPath));
|
|
66000
66153
|
break;
|
|
66001
66154
|
}
|
|
66002
66155
|
}
|
|
@@ -66009,11 +66162,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
66009
66162
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
66010
66163
|
const dirs = new Set;
|
|
66011
66164
|
for (const file3 of changedFiles) {
|
|
66012
|
-
let currentDir =
|
|
66165
|
+
let currentDir = path60.dirname(file3);
|
|
66013
66166
|
while (true) {
|
|
66014
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
66015
|
-
dirs.add(
|
|
66016
|
-
const parent =
|
|
66167
|
+
if (currentDir && currentDir !== "." && currentDir !== path60.sep) {
|
|
66168
|
+
dirs.add(path60.join(workingDir, currentDir));
|
|
66169
|
+
const parent = path60.dirname(currentDir);
|
|
66017
66170
|
if (parent === currentDir)
|
|
66018
66171
|
break;
|
|
66019
66172
|
currentDir = parent;
|
|
@@ -66027,7 +66180,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
66027
66180
|
}
|
|
66028
66181
|
function ensureOutputDir(outputDir) {
|
|
66029
66182
|
try {
|
|
66030
|
-
|
|
66183
|
+
fs47.mkdirSync(outputDir, { recursive: true });
|
|
66031
66184
|
} catch (error93) {
|
|
66032
66185
|
if (!error93 || error93.code !== "EEXIST") {
|
|
66033
66186
|
throw error93;
|
|
@@ -66097,7 +66250,7 @@ var sbom_generate = createSwarmTool({
|
|
|
66097
66250
|
const changedFiles = obj.changed_files;
|
|
66098
66251
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
66099
66252
|
const workingDir = directory;
|
|
66100
|
-
const outputDir =
|
|
66253
|
+
const outputDir = path60.isAbsolute(relativeOutputDir) ? relativeOutputDir : path60.join(workingDir, relativeOutputDir);
|
|
66101
66254
|
let manifestFiles = [];
|
|
66102
66255
|
if (scope === "all") {
|
|
66103
66256
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -66120,11 +66273,11 @@ var sbom_generate = createSwarmTool({
|
|
|
66120
66273
|
const processedFiles = [];
|
|
66121
66274
|
for (const manifestFile of manifestFiles) {
|
|
66122
66275
|
try {
|
|
66123
|
-
const fullPath =
|
|
66124
|
-
if (!
|
|
66276
|
+
const fullPath = path60.isAbsolute(manifestFile) ? manifestFile : path60.join(workingDir, manifestFile);
|
|
66277
|
+
if (!fs47.existsSync(fullPath)) {
|
|
66125
66278
|
continue;
|
|
66126
66279
|
}
|
|
66127
|
-
const content =
|
|
66280
|
+
const content = fs47.readFileSync(fullPath, "utf-8");
|
|
66128
66281
|
const components = detectComponents(manifestFile, content);
|
|
66129
66282
|
processedFiles.push(manifestFile);
|
|
66130
66283
|
if (components.length > 0) {
|
|
@@ -66137,8 +66290,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66137
66290
|
const bom = generateCycloneDX(allComponents);
|
|
66138
66291
|
const bomJson = serializeCycloneDX(bom);
|
|
66139
66292
|
const filename = generateSbomFilename();
|
|
66140
|
-
const outputPath =
|
|
66141
|
-
|
|
66293
|
+
const outputPath = path60.join(outputDir, filename);
|
|
66294
|
+
fs47.writeFileSync(outputPath, bomJson, "utf-8");
|
|
66142
66295
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
66143
66296
|
try {
|
|
66144
66297
|
const timestamp = new Date().toISOString();
|
|
@@ -66180,8 +66333,8 @@ var sbom_generate = createSwarmTool({
|
|
|
66180
66333
|
// src/tools/schema-drift.ts
|
|
66181
66334
|
init_dist();
|
|
66182
66335
|
init_create_tool();
|
|
66183
|
-
import * as
|
|
66184
|
-
import * as
|
|
66336
|
+
import * as fs48 from "fs";
|
|
66337
|
+
import * as path61 from "path";
|
|
66185
66338
|
var SPEC_CANDIDATES = [
|
|
66186
66339
|
"openapi.json",
|
|
66187
66340
|
"openapi.yaml",
|
|
@@ -66213,28 +66366,28 @@ function normalizePath2(p) {
|
|
|
66213
66366
|
}
|
|
66214
66367
|
function discoverSpecFile(cwd, specFileArg) {
|
|
66215
66368
|
if (specFileArg) {
|
|
66216
|
-
const resolvedPath =
|
|
66217
|
-
const normalizedCwd = cwd.endsWith(
|
|
66369
|
+
const resolvedPath = path61.resolve(cwd, specFileArg);
|
|
66370
|
+
const normalizedCwd = cwd.endsWith(path61.sep) ? cwd : cwd + path61.sep;
|
|
66218
66371
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
66219
66372
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
66220
66373
|
}
|
|
66221
|
-
const ext =
|
|
66374
|
+
const ext = path61.extname(resolvedPath).toLowerCase();
|
|
66222
66375
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
66223
66376
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
66224
66377
|
}
|
|
66225
|
-
const stats =
|
|
66378
|
+
const stats = fs48.statSync(resolvedPath);
|
|
66226
66379
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
66227
66380
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
66228
66381
|
}
|
|
66229
|
-
if (!
|
|
66382
|
+
if (!fs48.existsSync(resolvedPath)) {
|
|
66230
66383
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
66231
66384
|
}
|
|
66232
66385
|
return resolvedPath;
|
|
66233
66386
|
}
|
|
66234
66387
|
for (const candidate of SPEC_CANDIDATES) {
|
|
66235
|
-
const candidatePath =
|
|
66236
|
-
if (
|
|
66237
|
-
const stats =
|
|
66388
|
+
const candidatePath = path61.resolve(cwd, candidate);
|
|
66389
|
+
if (fs48.existsSync(candidatePath)) {
|
|
66390
|
+
const stats = fs48.statSync(candidatePath);
|
|
66238
66391
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
66239
66392
|
return candidatePath;
|
|
66240
66393
|
}
|
|
@@ -66243,8 +66396,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
66243
66396
|
return null;
|
|
66244
66397
|
}
|
|
66245
66398
|
function parseSpec(specFile) {
|
|
66246
|
-
const content =
|
|
66247
|
-
const ext =
|
|
66399
|
+
const content = fs48.readFileSync(specFile, "utf-8");
|
|
66400
|
+
const ext = path61.extname(specFile).toLowerCase();
|
|
66248
66401
|
if (ext === ".json") {
|
|
66249
66402
|
return parseJsonSpec(content);
|
|
66250
66403
|
}
|
|
@@ -66315,12 +66468,12 @@ function extractRoutes(cwd) {
|
|
|
66315
66468
|
function walkDir(dir) {
|
|
66316
66469
|
let entries;
|
|
66317
66470
|
try {
|
|
66318
|
-
entries =
|
|
66471
|
+
entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
66319
66472
|
} catch {
|
|
66320
66473
|
return;
|
|
66321
66474
|
}
|
|
66322
66475
|
for (const entry of entries) {
|
|
66323
|
-
const fullPath =
|
|
66476
|
+
const fullPath = path61.join(dir, entry.name);
|
|
66324
66477
|
if (entry.isSymbolicLink()) {
|
|
66325
66478
|
continue;
|
|
66326
66479
|
}
|
|
@@ -66330,7 +66483,7 @@ function extractRoutes(cwd) {
|
|
|
66330
66483
|
}
|
|
66331
66484
|
walkDir(fullPath);
|
|
66332
66485
|
} else if (entry.isFile()) {
|
|
66333
|
-
const ext =
|
|
66486
|
+
const ext = path61.extname(entry.name).toLowerCase();
|
|
66334
66487
|
const baseName = entry.name.toLowerCase();
|
|
66335
66488
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
66336
66489
|
continue;
|
|
@@ -66348,7 +66501,7 @@ function extractRoutes(cwd) {
|
|
|
66348
66501
|
}
|
|
66349
66502
|
function extractRoutesFromFile(filePath) {
|
|
66350
66503
|
const routes = [];
|
|
66351
|
-
const content =
|
|
66504
|
+
const content = fs48.readFileSync(filePath, "utf-8");
|
|
66352
66505
|
const lines = content.split(/\r?\n/);
|
|
66353
66506
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
66354
66507
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -66499,8 +66652,8 @@ init_secretscan();
|
|
|
66499
66652
|
// src/tools/symbols.ts
|
|
66500
66653
|
init_tool();
|
|
66501
66654
|
init_create_tool();
|
|
66502
|
-
import * as
|
|
66503
|
-
import * as
|
|
66655
|
+
import * as fs49 from "fs";
|
|
66656
|
+
import * as path62 from "path";
|
|
66504
66657
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
66505
66658
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
66506
66659
|
function containsWindowsAttacks(str) {
|
|
@@ -66517,11 +66670,11 @@ function containsWindowsAttacks(str) {
|
|
|
66517
66670
|
}
|
|
66518
66671
|
function isPathInWorkspace(filePath, workspace) {
|
|
66519
66672
|
try {
|
|
66520
|
-
const resolvedPath =
|
|
66521
|
-
const realWorkspace =
|
|
66522
|
-
const realResolvedPath =
|
|
66523
|
-
const relativePath =
|
|
66524
|
-
if (relativePath.startsWith("..") ||
|
|
66673
|
+
const resolvedPath = path62.resolve(workspace, filePath);
|
|
66674
|
+
const realWorkspace = fs49.realpathSync(workspace);
|
|
66675
|
+
const realResolvedPath = fs49.realpathSync(resolvedPath);
|
|
66676
|
+
const relativePath = path62.relative(realWorkspace, realResolvedPath);
|
|
66677
|
+
if (relativePath.startsWith("..") || path62.isAbsolute(relativePath)) {
|
|
66525
66678
|
return false;
|
|
66526
66679
|
}
|
|
66527
66680
|
return true;
|
|
@@ -66533,17 +66686,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
66533
66686
|
return isPathInWorkspace(filePath, workspace);
|
|
66534
66687
|
}
|
|
66535
66688
|
function extractTSSymbols(filePath, cwd) {
|
|
66536
|
-
const fullPath =
|
|
66689
|
+
const fullPath = path62.join(cwd, filePath);
|
|
66537
66690
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66538
66691
|
return [];
|
|
66539
66692
|
}
|
|
66540
66693
|
let content;
|
|
66541
66694
|
try {
|
|
66542
|
-
const stats =
|
|
66695
|
+
const stats = fs49.statSync(fullPath);
|
|
66543
66696
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66544
66697
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66545
66698
|
}
|
|
66546
|
-
content =
|
|
66699
|
+
content = fs49.readFileSync(fullPath, "utf-8");
|
|
66547
66700
|
} catch {
|
|
66548
66701
|
return [];
|
|
66549
66702
|
}
|
|
@@ -66685,17 +66838,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
66685
66838
|
});
|
|
66686
66839
|
}
|
|
66687
66840
|
function extractPythonSymbols(filePath, cwd) {
|
|
66688
|
-
const fullPath =
|
|
66841
|
+
const fullPath = path62.join(cwd, filePath);
|
|
66689
66842
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
66690
66843
|
return [];
|
|
66691
66844
|
}
|
|
66692
66845
|
let content;
|
|
66693
66846
|
try {
|
|
66694
|
-
const stats =
|
|
66847
|
+
const stats = fs49.statSync(fullPath);
|
|
66695
66848
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
66696
66849
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
66697
66850
|
}
|
|
66698
|
-
content =
|
|
66851
|
+
content = fs49.readFileSync(fullPath, "utf-8");
|
|
66699
66852
|
} catch {
|
|
66700
66853
|
return [];
|
|
66701
66854
|
}
|
|
@@ -66768,7 +66921,7 @@ var symbols = createSwarmTool({
|
|
|
66768
66921
|
}, null, 2);
|
|
66769
66922
|
}
|
|
66770
66923
|
const cwd = directory;
|
|
66771
|
-
const ext =
|
|
66924
|
+
const ext = path62.extname(file3);
|
|
66772
66925
|
if (containsControlChars(file3)) {
|
|
66773
66926
|
return JSON.stringify({
|
|
66774
66927
|
file: file3,
|
|
@@ -66839,8 +66992,8 @@ init_test_runner();
|
|
|
66839
66992
|
init_dist();
|
|
66840
66993
|
init_utils();
|
|
66841
66994
|
init_create_tool();
|
|
66842
|
-
import * as
|
|
66843
|
-
import * as
|
|
66995
|
+
import * as fs50 from "fs";
|
|
66996
|
+
import * as path63 from "path";
|
|
66844
66997
|
var MAX_TEXT_LENGTH = 200;
|
|
66845
66998
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
66846
66999
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -66905,9 +67058,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
66905
67058
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
66906
67059
|
}
|
|
66907
67060
|
try {
|
|
66908
|
-
const resolvedPath =
|
|
66909
|
-
const normalizedCwd =
|
|
66910
|
-
const normalizedResolved =
|
|
67061
|
+
const resolvedPath = path63.resolve(paths);
|
|
67062
|
+
const normalizedCwd = path63.resolve(cwd);
|
|
67063
|
+
const normalizedResolved = path63.resolve(resolvedPath);
|
|
66911
67064
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
66912
67065
|
return {
|
|
66913
67066
|
error: "paths must be within the current working directory",
|
|
@@ -66923,13 +67076,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
66923
67076
|
}
|
|
66924
67077
|
}
|
|
66925
67078
|
function isSupportedExtension(filePath) {
|
|
66926
|
-
const ext =
|
|
67079
|
+
const ext = path63.extname(filePath).toLowerCase();
|
|
66927
67080
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
66928
67081
|
}
|
|
66929
67082
|
function findSourceFiles2(dir, files = []) {
|
|
66930
67083
|
let entries;
|
|
66931
67084
|
try {
|
|
66932
|
-
entries =
|
|
67085
|
+
entries = fs50.readdirSync(dir);
|
|
66933
67086
|
} catch {
|
|
66934
67087
|
return files;
|
|
66935
67088
|
}
|
|
@@ -66938,10 +67091,10 @@ function findSourceFiles2(dir, files = []) {
|
|
|
66938
67091
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
66939
67092
|
continue;
|
|
66940
67093
|
}
|
|
66941
|
-
const fullPath =
|
|
67094
|
+
const fullPath = path63.join(dir, entry);
|
|
66942
67095
|
let stat2;
|
|
66943
67096
|
try {
|
|
66944
|
-
stat2 =
|
|
67097
|
+
stat2 = fs50.statSync(fullPath);
|
|
66945
67098
|
} catch {
|
|
66946
67099
|
continue;
|
|
66947
67100
|
}
|
|
@@ -67034,7 +67187,7 @@ var todo_extract = createSwarmTool({
|
|
|
67034
67187
|
return JSON.stringify(errorResult, null, 2);
|
|
67035
67188
|
}
|
|
67036
67189
|
const scanPath = resolvedPath;
|
|
67037
|
-
if (!
|
|
67190
|
+
if (!fs50.existsSync(scanPath)) {
|
|
67038
67191
|
const errorResult = {
|
|
67039
67192
|
error: `path not found: ${pathsInput}`,
|
|
67040
67193
|
total: 0,
|
|
@@ -67044,13 +67197,13 @@ var todo_extract = createSwarmTool({
|
|
|
67044
67197
|
return JSON.stringify(errorResult, null, 2);
|
|
67045
67198
|
}
|
|
67046
67199
|
const filesToScan = [];
|
|
67047
|
-
const stat2 =
|
|
67200
|
+
const stat2 = fs50.statSync(scanPath);
|
|
67048
67201
|
if (stat2.isFile()) {
|
|
67049
67202
|
if (isSupportedExtension(scanPath)) {
|
|
67050
67203
|
filesToScan.push(scanPath);
|
|
67051
67204
|
} else {
|
|
67052
67205
|
const errorResult = {
|
|
67053
|
-
error: `unsupported file extension: ${
|
|
67206
|
+
error: `unsupported file extension: ${path63.extname(scanPath)}`,
|
|
67054
67207
|
total: 0,
|
|
67055
67208
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
67056
67209
|
entries: []
|
|
@@ -67063,11 +67216,11 @@ var todo_extract = createSwarmTool({
|
|
|
67063
67216
|
const allEntries = [];
|
|
67064
67217
|
for (const filePath of filesToScan) {
|
|
67065
67218
|
try {
|
|
67066
|
-
const fileStat =
|
|
67219
|
+
const fileStat = fs50.statSync(filePath);
|
|
67067
67220
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
67068
67221
|
continue;
|
|
67069
67222
|
}
|
|
67070
|
-
const content =
|
|
67223
|
+
const content = fs50.readFileSync(filePath, "utf-8");
|
|
67071
67224
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
67072
67225
|
allEntries.push(...entries);
|
|
67073
67226
|
} catch {}
|
|
@@ -67096,18 +67249,18 @@ var todo_extract = createSwarmTool({
|
|
|
67096
67249
|
init_tool();
|
|
67097
67250
|
init_schema();
|
|
67098
67251
|
init_gate_evidence();
|
|
67099
|
-
import * as
|
|
67100
|
-
import * as
|
|
67252
|
+
import * as fs52 from "fs";
|
|
67253
|
+
import * as path65 from "path";
|
|
67101
67254
|
|
|
67102
67255
|
// src/hooks/diff-scope.ts
|
|
67103
|
-
import * as
|
|
67104
|
-
import * as
|
|
67256
|
+
import * as fs51 from "fs";
|
|
67257
|
+
import * as path64 from "path";
|
|
67105
67258
|
function getDeclaredScope(taskId, directory) {
|
|
67106
67259
|
try {
|
|
67107
|
-
const planPath =
|
|
67108
|
-
if (!
|
|
67260
|
+
const planPath = path64.join(directory, ".swarm", "plan.json");
|
|
67261
|
+
if (!fs51.existsSync(planPath))
|
|
67109
67262
|
return null;
|
|
67110
|
-
const raw =
|
|
67263
|
+
const raw = fs51.readFileSync(planPath, "utf-8");
|
|
67111
67264
|
const plan = JSON.parse(raw);
|
|
67112
67265
|
for (const phase of plan.phases ?? []) {
|
|
67113
67266
|
for (const task of phase.tasks ?? []) {
|
|
@@ -67220,7 +67373,7 @@ var TIER_3_PATTERNS = [
|
|
|
67220
67373
|
];
|
|
67221
67374
|
function matchesTier3Pattern(files) {
|
|
67222
67375
|
for (const file3 of files) {
|
|
67223
|
-
const fileName =
|
|
67376
|
+
const fileName = path65.basename(file3);
|
|
67224
67377
|
for (const pattern of TIER_3_PATTERNS) {
|
|
67225
67378
|
if (pattern.test(fileName)) {
|
|
67226
67379
|
return true;
|
|
@@ -67234,8 +67387,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67234
67387
|
if (hasActiveTurboMode()) {
|
|
67235
67388
|
const resolvedDir2 = workingDirectory;
|
|
67236
67389
|
try {
|
|
67237
|
-
const planPath =
|
|
67238
|
-
const planRaw =
|
|
67390
|
+
const planPath = path65.join(resolvedDir2, ".swarm", "plan.json");
|
|
67391
|
+
const planRaw = fs52.readFileSync(planPath, "utf-8");
|
|
67239
67392
|
const plan = JSON.parse(planRaw);
|
|
67240
67393
|
for (const planPhase of plan.phases ?? []) {
|
|
67241
67394
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67301,8 +67454,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
67301
67454
|
}
|
|
67302
67455
|
try {
|
|
67303
67456
|
const resolvedDir2 = workingDirectory;
|
|
67304
|
-
const planPath =
|
|
67305
|
-
const planRaw =
|
|
67457
|
+
const planPath = path65.join(resolvedDir2, ".swarm", "plan.json");
|
|
67458
|
+
const planRaw = fs52.readFileSync(planPath, "utf-8");
|
|
67306
67459
|
const plan = JSON.parse(planRaw);
|
|
67307
67460
|
for (const planPhase of plan.phases ?? []) {
|
|
67308
67461
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -67484,8 +67637,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67484
67637
|
};
|
|
67485
67638
|
}
|
|
67486
67639
|
}
|
|
67487
|
-
normalizedDir =
|
|
67488
|
-
const pathParts = normalizedDir.split(
|
|
67640
|
+
normalizedDir = path65.normalize(args2.working_directory);
|
|
67641
|
+
const pathParts = normalizedDir.split(path65.sep);
|
|
67489
67642
|
if (pathParts.includes("..")) {
|
|
67490
67643
|
return {
|
|
67491
67644
|
success: false,
|
|
@@ -67495,11 +67648,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67495
67648
|
]
|
|
67496
67649
|
};
|
|
67497
67650
|
}
|
|
67498
|
-
const resolvedDir =
|
|
67651
|
+
const resolvedDir = path65.resolve(normalizedDir);
|
|
67499
67652
|
try {
|
|
67500
|
-
const realPath =
|
|
67501
|
-
const planPath =
|
|
67502
|
-
if (!
|
|
67653
|
+
const realPath = fs52.realpathSync(resolvedDir);
|
|
67654
|
+
const planPath = path65.join(realPath, ".swarm", "plan.json");
|
|
67655
|
+
if (!fs52.existsSync(planPath)) {
|
|
67503
67656
|
return {
|
|
67504
67657
|
success: false,
|
|
67505
67658
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -67532,8 +67685,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
67532
67685
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
67533
67686
|
let phaseRequiresReviewer = true;
|
|
67534
67687
|
try {
|
|
67535
|
-
const planPath =
|
|
67536
|
-
const planRaw =
|
|
67688
|
+
const planPath = path65.join(directory, ".swarm", "plan.json");
|
|
67689
|
+
const planRaw = fs52.readFileSync(planPath, "utf-8");
|
|
67537
67690
|
const plan = JSON.parse(planRaw);
|
|
67538
67691
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
67539
67692
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -67596,8 +67749,8 @@ var update_task_status = createSwarmTool({
|
|
|
67596
67749
|
init_tool();
|
|
67597
67750
|
init_utils2();
|
|
67598
67751
|
init_create_tool();
|
|
67599
|
-
import
|
|
67600
|
-
import
|
|
67752
|
+
import fs53 from "fs";
|
|
67753
|
+
import path66 from "path";
|
|
67601
67754
|
function normalizeVerdict(verdict) {
|
|
67602
67755
|
switch (verdict) {
|
|
67603
67756
|
case "APPROVED":
|
|
@@ -67644,7 +67797,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67644
67797
|
entries: [evidenceEntry]
|
|
67645
67798
|
};
|
|
67646
67799
|
const filename = "drift-verifier.json";
|
|
67647
|
-
const relativePath =
|
|
67800
|
+
const relativePath = path66.join("evidence", String(phase), filename);
|
|
67648
67801
|
let validatedPath;
|
|
67649
67802
|
try {
|
|
67650
67803
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -67655,12 +67808,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
67655
67808
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
67656
67809
|
}, null, 2);
|
|
67657
67810
|
}
|
|
67658
|
-
const evidenceDir =
|
|
67811
|
+
const evidenceDir = path66.dirname(validatedPath);
|
|
67659
67812
|
try {
|
|
67660
|
-
await
|
|
67661
|
-
const tempPath =
|
|
67662
|
-
await
|
|
67663
|
-
await
|
|
67813
|
+
await fs53.promises.mkdir(evidenceDir, { recursive: true });
|
|
67814
|
+
const tempPath = path66.join(evidenceDir, `.${filename}.tmp`);
|
|
67815
|
+
await fs53.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
67816
|
+
await fs53.promises.rename(tempPath, validatedPath);
|
|
67664
67817
|
return JSON.stringify({
|
|
67665
67818
|
success: true,
|
|
67666
67819
|
phase,
|
|
@@ -67848,7 +68001,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
67848
68001
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
67849
68002
|
preflightTriggerManager = new PTM(automationConfig);
|
|
67850
68003
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
67851
|
-
const swarmDir =
|
|
68004
|
+
const swarmDir = path67.resolve(ctx.directory, ".swarm");
|
|
67852
68005
|
statusArtifact = new ASA(swarmDir);
|
|
67853
68006
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
67854
68007
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|