opencode-swarm 6.86.8 → 6.86.9
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 +277 -217
- package/dist/config/cache-paths.d.ts +11 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +688 -640
- package/dist/services/diagnose-service.d.ts +1 -1
- package/package.json +1 -1
- package/dist/tools/check-gate-status.prefix.test.d.ts +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -17669,14 +17669,14 @@ __export(exports_config_doctor, {
|
|
|
17669
17669
|
});
|
|
17670
17670
|
import * as crypto3 from "crypto";
|
|
17671
17671
|
import * as fs8 from "fs";
|
|
17672
|
-
import * as
|
|
17673
|
-
import * as
|
|
17672
|
+
import * as os6 from "os";
|
|
17673
|
+
import * as path19 from "path";
|
|
17674
17674
|
function getUserConfigDir3() {
|
|
17675
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
17675
|
+
return process.env.XDG_CONFIG_HOME || path19.join(os6.homedir(), ".config");
|
|
17676
17676
|
}
|
|
17677
17677
|
function getConfigPaths(directory) {
|
|
17678
|
-
const userConfigPath =
|
|
17679
|
-
const projectConfigPath =
|
|
17678
|
+
const userConfigPath = path19.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
17679
|
+
const projectConfigPath = path19.join(directory, ".opencode", "opencode-swarm.json");
|
|
17680
17680
|
return { userConfigPath, projectConfigPath };
|
|
17681
17681
|
}
|
|
17682
17682
|
function computeHash(content) {
|
|
@@ -17701,9 +17701,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
17701
17701
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
17702
17702
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
17703
17703
|
try {
|
|
17704
|
-
const resolvedConfig =
|
|
17705
|
-
const resolvedUser =
|
|
17706
|
-
const resolvedProject =
|
|
17704
|
+
const resolvedConfig = path19.resolve(configPath);
|
|
17705
|
+
const resolvedUser = path19.resolve(normalizedUser);
|
|
17706
|
+
const resolvedProject = path19.resolve(normalizedProject);
|
|
17707
17707
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
17708
17708
|
} catch {
|
|
17709
17709
|
return false;
|
|
@@ -17743,12 +17743,12 @@ function createConfigBackup(directory) {
|
|
|
17743
17743
|
};
|
|
17744
17744
|
}
|
|
17745
17745
|
function writeBackupArtifact(directory, backup) {
|
|
17746
|
-
const swarmDir =
|
|
17746
|
+
const swarmDir = path19.join(directory, ".swarm");
|
|
17747
17747
|
if (!fs8.existsSync(swarmDir)) {
|
|
17748
17748
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
17749
17749
|
}
|
|
17750
17750
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
17751
|
-
const backupPath =
|
|
17751
|
+
const backupPath = path19.join(swarmDir, backupFilename);
|
|
17752
17752
|
const artifact = {
|
|
17753
17753
|
createdAt: backup.createdAt,
|
|
17754
17754
|
configPath: backup.configPath,
|
|
@@ -17778,7 +17778,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
17778
17778
|
return null;
|
|
17779
17779
|
}
|
|
17780
17780
|
const targetPath = artifact.configPath;
|
|
17781
|
-
const targetDir =
|
|
17781
|
+
const targetDir = path19.dirname(targetPath);
|
|
17782
17782
|
if (!fs8.existsSync(targetDir)) {
|
|
17783
17783
|
fs8.mkdirSync(targetDir, { recursive: true });
|
|
17784
17784
|
}
|
|
@@ -17809,9 +17809,9 @@ function readConfigFromFile(directory) {
|
|
|
17809
17809
|
return null;
|
|
17810
17810
|
}
|
|
17811
17811
|
}
|
|
17812
|
-
function validateConfigKey(
|
|
17812
|
+
function validateConfigKey(path20, value, _config) {
|
|
17813
17813
|
const findings = [];
|
|
17814
|
-
switch (
|
|
17814
|
+
switch (path20) {
|
|
17815
17815
|
case "agents": {
|
|
17816
17816
|
if (value !== undefined) {
|
|
17817
17817
|
findings.push({
|
|
@@ -18058,27 +18058,27 @@ function validateConfigKey(path19, value, _config) {
|
|
|
18058
18058
|
}
|
|
18059
18059
|
return findings;
|
|
18060
18060
|
}
|
|
18061
|
-
function walkConfigAndValidate(obj,
|
|
18061
|
+
function walkConfigAndValidate(obj, path20, config3, findings) {
|
|
18062
18062
|
if (obj === null || obj === undefined) {
|
|
18063
18063
|
return;
|
|
18064
18064
|
}
|
|
18065
|
-
if (
|
|
18066
|
-
const keyFindings = validateConfigKey(
|
|
18065
|
+
if (path20 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
18066
|
+
const keyFindings = validateConfigKey(path20, obj, config3);
|
|
18067
18067
|
findings.push(...keyFindings);
|
|
18068
18068
|
}
|
|
18069
18069
|
if (typeof obj !== "object") {
|
|
18070
|
-
const keyFindings = validateConfigKey(
|
|
18070
|
+
const keyFindings = validateConfigKey(path20, obj, config3);
|
|
18071
18071
|
findings.push(...keyFindings);
|
|
18072
18072
|
return;
|
|
18073
18073
|
}
|
|
18074
18074
|
if (Array.isArray(obj)) {
|
|
18075
18075
|
obj.forEach((item, index) => {
|
|
18076
|
-
walkConfigAndValidate(item, `${
|
|
18076
|
+
walkConfigAndValidate(item, `${path20}[${index}]`, config3, findings);
|
|
18077
18077
|
});
|
|
18078
18078
|
return;
|
|
18079
18079
|
}
|
|
18080
18080
|
for (const [key, value] of Object.entries(obj)) {
|
|
18081
|
-
const newPath =
|
|
18081
|
+
const newPath = path20 ? `${path20}.${key}` : key;
|
|
18082
18082
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
18083
18083
|
}
|
|
18084
18084
|
}
|
|
@@ -18198,7 +18198,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18198
18198
|
}
|
|
18199
18199
|
}
|
|
18200
18200
|
if (appliedFixes.length > 0) {
|
|
18201
|
-
const configDir =
|
|
18201
|
+
const configDir = path19.dirname(configPath);
|
|
18202
18202
|
if (!fs8.existsSync(configDir)) {
|
|
18203
18203
|
fs8.mkdirSync(configDir, { recursive: true });
|
|
18204
18204
|
}
|
|
@@ -18208,12 +18208,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18208
18208
|
return { appliedFixes, updatedConfigPath };
|
|
18209
18209
|
}
|
|
18210
18210
|
function writeDoctorArtifact(directory, result) {
|
|
18211
|
-
const swarmDir =
|
|
18211
|
+
const swarmDir = path19.join(directory, ".swarm");
|
|
18212
18212
|
if (!fs8.existsSync(swarmDir)) {
|
|
18213
18213
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
18214
18214
|
}
|
|
18215
18215
|
const artifactFilename = "config-doctor.json";
|
|
18216
|
-
const artifactPath =
|
|
18216
|
+
const artifactPath = path19.join(swarmDir, artifactFilename);
|
|
18217
18217
|
const guiOutput = {
|
|
18218
18218
|
timestamp: result.timestamp,
|
|
18219
18219
|
summary: result.summary,
|
|
@@ -18575,12 +18575,12 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
18575
18575
|
|
|
18576
18576
|
// src/cli/index.ts
|
|
18577
18577
|
import * as fs21 from "fs";
|
|
18578
|
-
import * as
|
|
18579
|
-
import * as
|
|
18578
|
+
import * as os7 from "os";
|
|
18579
|
+
import * as path33 from "path";
|
|
18580
18580
|
// package.json
|
|
18581
18581
|
var package_default = {
|
|
18582
18582
|
name: "opencode-swarm",
|
|
18583
|
-
version: "6.86.
|
|
18583
|
+
version: "6.86.9",
|
|
18584
18584
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18585
18585
|
main: "dist/index.js",
|
|
18586
18586
|
types: "dist/index.d.ts",
|
|
@@ -36269,31 +36269,49 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36269
36269
|
// src/services/diagnose-service.ts
|
|
36270
36270
|
import * as child_process4 from "child_process";
|
|
36271
36271
|
import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
36272
|
-
import
|
|
36272
|
+
import path18 from "path";
|
|
36273
36273
|
import { fileURLToPath } from "url";
|
|
36274
|
+
|
|
36275
|
+
// src/config/cache-paths.ts
|
|
36276
|
+
import * as os5 from "os";
|
|
36277
|
+
import * as path17 from "path";
|
|
36278
|
+
function getPluginConfigDir() {
|
|
36279
|
+
return path17.join(process.env.XDG_CONFIG_HOME || path17.join(os5.homedir(), ".config"), "opencode");
|
|
36280
|
+
}
|
|
36281
|
+
function getPluginCachePaths() {
|
|
36282
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path17.join(os5.homedir(), ".cache");
|
|
36283
|
+
const configDir = getPluginConfigDir();
|
|
36284
|
+
return [
|
|
36285
|
+
path17.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
36286
|
+
path17.join(configDir, "node_modules", "opencode-swarm"),
|
|
36287
|
+
path17.join(cacheBase, "opencode", "node_modules", "opencode-swarm")
|
|
36288
|
+
];
|
|
36289
|
+
}
|
|
36290
|
+
|
|
36291
|
+
// src/services/diagnose-service.ts
|
|
36274
36292
|
init_manager2();
|
|
36275
36293
|
init_utils2();
|
|
36276
36294
|
init_manager();
|
|
36277
36295
|
|
|
36278
36296
|
// src/services/version-check.ts
|
|
36279
36297
|
import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
36280
|
-
import { homedir as
|
|
36281
|
-
import { join as
|
|
36298
|
+
import { homedir as homedir5 } from "os";
|
|
36299
|
+
import { join as join15 } from "path";
|
|
36282
36300
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
36283
36301
|
function cacheDir() {
|
|
36284
36302
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
36285
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
36286
|
-
return
|
|
36303
|
+
const base = xdg && xdg.length > 0 ? xdg : join15(homedir5(), ".cache");
|
|
36304
|
+
return join15(base, "opencode-swarm");
|
|
36287
36305
|
}
|
|
36288
36306
|
function cacheFile() {
|
|
36289
|
-
return
|
|
36307
|
+
return join15(cacheDir(), "version-check.json");
|
|
36290
36308
|
}
|
|
36291
36309
|
function readVersionCache() {
|
|
36292
36310
|
try {
|
|
36293
|
-
const
|
|
36294
|
-
if (!existsSync8(
|
|
36311
|
+
const path18 = cacheFile();
|
|
36312
|
+
if (!existsSync8(path18))
|
|
36295
36313
|
return null;
|
|
36296
|
-
const raw = readFileSync5(
|
|
36314
|
+
const raw = readFileSync5(path18, "utf-8");
|
|
36297
36315
|
const parsed = JSON.parse(raw);
|
|
36298
36316
|
if (typeof parsed?.checkedAt !== "number")
|
|
36299
36317
|
return null;
|
|
@@ -36623,7 +36641,7 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
36623
36641
|
};
|
|
36624
36642
|
}
|
|
36625
36643
|
async function checkConfigParseability(directory) {
|
|
36626
|
-
const configPath =
|
|
36644
|
+
const configPath = path18.join(directory, ".opencode/opencode-swarm.json");
|
|
36627
36645
|
if (!existsSync9(configPath)) {
|
|
36628
36646
|
return {
|
|
36629
36647
|
name: "Config Parseability",
|
|
@@ -36652,7 +36670,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
36652
36670
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
36653
36671
|
const isSource = normalized.endsWith("/src/services");
|
|
36654
36672
|
const isCliBundle = normalized.endsWith("/cli");
|
|
36655
|
-
return isSource || isCliBundle ?
|
|
36673
|
+
return isSource || isCliBundle ? path18.join(thisDir, "..", "lang", "grammars") : path18.join(thisDir, "lang", "grammars");
|
|
36656
36674
|
}
|
|
36657
36675
|
async function checkGrammarWasmFiles() {
|
|
36658
36676
|
const grammarFiles = [
|
|
@@ -36676,14 +36694,14 @@ async function checkGrammarWasmFiles() {
|
|
|
36676
36694
|
"tree-sitter-ini.wasm",
|
|
36677
36695
|
"tree-sitter-regex.wasm"
|
|
36678
36696
|
];
|
|
36679
|
-
const thisDir =
|
|
36697
|
+
const thisDir = path18.dirname(fileURLToPath(import.meta.url));
|
|
36680
36698
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
36681
36699
|
const missing = [];
|
|
36682
|
-
if (!existsSync9(
|
|
36700
|
+
if (!existsSync9(path18.join(grammarDir, "tree-sitter.wasm"))) {
|
|
36683
36701
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
36684
36702
|
}
|
|
36685
36703
|
for (const file3 of grammarFiles) {
|
|
36686
|
-
if (!existsSync9(
|
|
36704
|
+
if (!existsSync9(path18.join(grammarDir, file3))) {
|
|
36687
36705
|
missing.push(file3);
|
|
36688
36706
|
}
|
|
36689
36707
|
}
|
|
@@ -36701,7 +36719,7 @@ async function checkGrammarWasmFiles() {
|
|
|
36701
36719
|
};
|
|
36702
36720
|
}
|
|
36703
36721
|
async function checkCheckpointManifest(directory) {
|
|
36704
|
-
const manifestPath =
|
|
36722
|
+
const manifestPath = path18.join(directory, ".swarm/checkpoints.json");
|
|
36705
36723
|
if (!existsSync9(manifestPath)) {
|
|
36706
36724
|
return {
|
|
36707
36725
|
name: "Checkpoint Manifest",
|
|
@@ -36753,7 +36771,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
36753
36771
|
}
|
|
36754
36772
|
}
|
|
36755
36773
|
async function checkEventStreamIntegrity(directory) {
|
|
36756
|
-
const eventsPath =
|
|
36774
|
+
const eventsPath = path18.join(directory, ".swarm/events.jsonl");
|
|
36757
36775
|
if (!existsSync9(eventsPath)) {
|
|
36758
36776
|
return {
|
|
36759
36777
|
name: "Event Stream",
|
|
@@ -36794,7 +36812,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
36794
36812
|
}
|
|
36795
36813
|
}
|
|
36796
36814
|
async function checkSteeringDirectives(directory) {
|
|
36797
|
-
const eventsPath =
|
|
36815
|
+
const eventsPath = path18.join(directory, ".swarm/events.jsonl");
|
|
36798
36816
|
if (!existsSync9(eventsPath)) {
|
|
36799
36817
|
return {
|
|
36800
36818
|
name: "Steering Directives",
|
|
@@ -36850,7 +36868,7 @@ async function checkCurator(directory) {
|
|
|
36850
36868
|
detail: "Disabled (enable via curator.enabled)"
|
|
36851
36869
|
};
|
|
36852
36870
|
}
|
|
36853
|
-
const summaryPath =
|
|
36871
|
+
const summaryPath = path18.join(directory, ".swarm/curator-summary.json");
|
|
36854
36872
|
if (!existsSync9(summaryPath)) {
|
|
36855
36873
|
return {
|
|
36856
36874
|
name: "Curator",
|
|
@@ -37016,7 +37034,7 @@ async function getDiagnoseData(directory) {
|
|
|
37016
37034
|
checks5.push(await checkSteeringDirectives(directory));
|
|
37017
37035
|
checks5.push(await checkCurator(directory));
|
|
37018
37036
|
try {
|
|
37019
|
-
const evidenceDir =
|
|
37037
|
+
const evidenceDir = path18.join(directory, ".swarm", "evidence");
|
|
37020
37038
|
const snapshotFiles = existsSync9(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
37021
37039
|
if (snapshotFiles.length > 0) {
|
|
37022
37040
|
const latest = snapshotFiles.sort().pop();
|
|
@@ -37046,7 +37064,36 @@ async function getDiagnoseData(directory) {
|
|
|
37046
37064
|
detail: `${deferredWarnings.length} warning(s) deferred from init (run with verbose logs for details)`
|
|
37047
37065
|
});
|
|
37048
37066
|
}
|
|
37049
|
-
const
|
|
37067
|
+
const cachePaths = getPluginCachePaths();
|
|
37068
|
+
const cacheRows = [];
|
|
37069
|
+
for (const cachePath of cachePaths) {
|
|
37070
|
+
try {
|
|
37071
|
+
if (!existsSync9(cachePath)) {
|
|
37072
|
+
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
37073
|
+
continue;
|
|
37074
|
+
}
|
|
37075
|
+
const pkgJsonPath = path18.join(cachePath, "package.json");
|
|
37076
|
+
try {
|
|
37077
|
+
const raw = readFileSync6(pkgJsonPath, "utf-8");
|
|
37078
|
+
const parsed = JSON.parse(raw);
|
|
37079
|
+
const installedVersion = typeof parsed.version === "string" ? parsed.version : "?";
|
|
37080
|
+
cacheRows.push(`\u2705 ${cachePath} \u2014 v${installedVersion}`);
|
|
37081
|
+
} catch {
|
|
37082
|
+
cacheRows.push(`\u26A0\uFE0F ${cachePath} \u2014 present (package.json unreadable)`);
|
|
37083
|
+
}
|
|
37084
|
+
} catch {
|
|
37085
|
+
cacheRows.push(`\u26A0\uFE0F ${cachePath} \u2014 status unknown (read error)`);
|
|
37086
|
+
}
|
|
37087
|
+
}
|
|
37088
|
+
const hasCacheEntry = cacheRows.some((r) => r.startsWith("\u2705"));
|
|
37089
|
+
const hasCacheWarning = cacheRows.some((r) => r.startsWith("\u26A0\uFE0F"));
|
|
37090
|
+
const cacheStatus = hasCacheWarning ? "\u26A0\uFE0F" : hasCacheEntry ? "\u2705" : "\u2B1C";
|
|
37091
|
+
checks5.push({
|
|
37092
|
+
name: "Plugin Caches",
|
|
37093
|
+
status: cacheStatus,
|
|
37094
|
+
detail: cacheRows.join(" | ")
|
|
37095
|
+
});
|
|
37096
|
+
const passCount = checks5.filter((c) => c.status === "\u2705" || c.status === "\u2B1C").length;
|
|
37050
37097
|
const totalCount = checks5.length;
|
|
37051
37098
|
const allPassed = passCount === totalCount;
|
|
37052
37099
|
return {
|
|
@@ -37084,15 +37131,15 @@ init_config_doctor();
|
|
|
37084
37131
|
|
|
37085
37132
|
// src/services/tool-doctor.ts
|
|
37086
37133
|
import * as fs10 from "fs";
|
|
37087
|
-
import * as
|
|
37134
|
+
import * as path21 from "path";
|
|
37088
37135
|
|
|
37089
37136
|
// src/build/discovery.ts
|
|
37090
37137
|
import * as fs9 from "fs";
|
|
37091
|
-
import * as
|
|
37138
|
+
import * as path20 from "path";
|
|
37092
37139
|
|
|
37093
37140
|
// src/lang/detector.ts
|
|
37094
37141
|
import { access as access2, readdir as readdir2 } from "fs/promises";
|
|
37095
|
-
import { extname as extname2, join as
|
|
37142
|
+
import { extname as extname2, join as join17 } from "path";
|
|
37096
37143
|
|
|
37097
37144
|
// src/lang/profiles.ts
|
|
37098
37145
|
class LanguageRegistry {
|
|
@@ -38072,7 +38119,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
38072
38119
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
38073
38120
|
continue;
|
|
38074
38121
|
try {
|
|
38075
|
-
await access2(
|
|
38122
|
+
await access2(join17(dir, detectFile));
|
|
38076
38123
|
detected.add(profile.id);
|
|
38077
38124
|
break;
|
|
38078
38125
|
} catch {}
|
|
@@ -38093,7 +38140,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
38093
38140
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
38094
38141
|
for (const entry of topEntries) {
|
|
38095
38142
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
38096
|
-
await scanDir(
|
|
38143
|
+
await scanDir(join17(projectDir, entry.name));
|
|
38097
38144
|
}
|
|
38098
38145
|
}
|
|
38099
38146
|
} catch {}
|
|
@@ -38252,11 +38299,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38252
38299
|
const regex = simpleGlobToRegex(pattern);
|
|
38253
38300
|
const matches = files.filter((f) => regex.test(f));
|
|
38254
38301
|
if (matches.length > 0) {
|
|
38255
|
-
return
|
|
38302
|
+
return path20.join(dir, matches[0]);
|
|
38256
38303
|
}
|
|
38257
38304
|
} catch {}
|
|
38258
38305
|
} else {
|
|
38259
|
-
const filePath =
|
|
38306
|
+
const filePath = path20.join(workingDir, pattern);
|
|
38260
38307
|
if (fs9.existsSync(filePath)) {
|
|
38261
38308
|
return filePath;
|
|
38262
38309
|
}
|
|
@@ -38265,7 +38312,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38265
38312
|
return null;
|
|
38266
38313
|
}
|
|
38267
38314
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
38268
|
-
const packageJsonPath =
|
|
38315
|
+
const packageJsonPath = path20.join(workingDir, "package.json");
|
|
38269
38316
|
if (!fs9.existsSync(packageJsonPath)) {
|
|
38270
38317
|
return [];
|
|
38271
38318
|
}
|
|
@@ -38306,7 +38353,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
38306
38353
|
const regex = simpleGlobToRegex(pattern);
|
|
38307
38354
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
38308
38355
|
} else {
|
|
38309
|
-
const filePath =
|
|
38356
|
+
const filePath = path20.join(workingDir, pattern);
|
|
38310
38357
|
if (fs9.existsSync(filePath)) {
|
|
38311
38358
|
allBuildFiles.add(filePath);
|
|
38312
38359
|
}
|
|
@@ -38319,7 +38366,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
38319
38366
|
try {
|
|
38320
38367
|
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
38321
38368
|
for (const entry of entries) {
|
|
38322
|
-
const fullPath =
|
|
38369
|
+
const fullPath = path20.join(dir, entry.name);
|
|
38323
38370
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
38324
38371
|
findFilesRecursive(fullPath, regex, results);
|
|
38325
38372
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -38342,7 +38389,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
38342
38389
|
let foundCommand = false;
|
|
38343
38390
|
for (const cmd of sortedCommands) {
|
|
38344
38391
|
if (cmd.detectFile) {
|
|
38345
|
-
const detectFilePath =
|
|
38392
|
+
const detectFilePath = path20.join(workingDir, cmd.detectFile);
|
|
38346
38393
|
if (!fs9.existsSync(detectFilePath)) {
|
|
38347
38394
|
continue;
|
|
38348
38395
|
}
|
|
@@ -38517,8 +38564,8 @@ function checkBinaryReadiness() {
|
|
|
38517
38564
|
}
|
|
38518
38565
|
function runToolDoctor(_directory, pluginRoot) {
|
|
38519
38566
|
const findings = [];
|
|
38520
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
38521
|
-
const indexPath =
|
|
38567
|
+
const resolvedPluginRoot = pluginRoot ?? path21.resolve(import.meta.dir, "..", "..");
|
|
38568
|
+
const indexPath = path21.join(resolvedPluginRoot, "src", "index.ts");
|
|
38522
38569
|
if (!fs10.existsSync(indexPath)) {
|
|
38523
38570
|
return {
|
|
38524
38571
|
findings: [
|
|
@@ -39441,10 +39488,10 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
39441
39488
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
39442
39489
|
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
39443
39490
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
39444
|
-
import * as
|
|
39491
|
+
import * as path22 from "path";
|
|
39445
39492
|
async function migrateContextToKnowledge(directory, config3) {
|
|
39446
|
-
const sentinelPath =
|
|
39447
|
-
const contextPath =
|
|
39493
|
+
const sentinelPath = path22.join(directory, ".swarm", ".knowledge-migrated");
|
|
39494
|
+
const contextPath = path22.join(directory, ".swarm", "context.md");
|
|
39448
39495
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
39449
39496
|
if (existsSync13(sentinelPath)) {
|
|
39450
39497
|
return {
|
|
@@ -39640,7 +39687,7 @@ function truncateLesson(text) {
|
|
|
39640
39687
|
return `${text.slice(0, 277)}...`;
|
|
39641
39688
|
}
|
|
39642
39689
|
function inferProjectName(directory) {
|
|
39643
|
-
const packageJsonPath =
|
|
39690
|
+
const packageJsonPath = path22.join(directory, "package.json");
|
|
39644
39691
|
if (existsSync13(packageJsonPath)) {
|
|
39645
39692
|
try {
|
|
39646
39693
|
const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
@@ -39649,7 +39696,7 @@ function inferProjectName(directory) {
|
|
|
39649
39696
|
}
|
|
39650
39697
|
} catch {}
|
|
39651
39698
|
}
|
|
39652
|
-
return
|
|
39699
|
+
return path22.basename(directory);
|
|
39653
39700
|
}
|
|
39654
39701
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
39655
39702
|
const sentinel = {
|
|
@@ -39661,7 +39708,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
39661
39708
|
schema_version: 1,
|
|
39662
39709
|
migration_tool: "knowledge-migrator.ts"
|
|
39663
39710
|
};
|
|
39664
|
-
await mkdir3(
|
|
39711
|
+
await mkdir3(path22.dirname(sentinelPath), { recursive: true });
|
|
39665
39712
|
await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
39666
39713
|
}
|
|
39667
39714
|
|
|
@@ -39898,12 +39945,12 @@ async function handlePlanCommand(directory, args) {
|
|
|
39898
39945
|
init_manager2();
|
|
39899
39946
|
init_manager();
|
|
39900
39947
|
import * as fs17 from "fs";
|
|
39901
|
-
import * as
|
|
39948
|
+
import * as path29 from "path";
|
|
39902
39949
|
|
|
39903
39950
|
// src/tools/lint.ts
|
|
39904
39951
|
init_zod();
|
|
39905
39952
|
import * as fs11 from "fs";
|
|
39906
|
-
import * as
|
|
39953
|
+
import * as path23 from "path";
|
|
39907
39954
|
init_utils();
|
|
39908
39955
|
|
|
39909
39956
|
// src/utils/path-security.ts
|
|
@@ -39949,9 +39996,9 @@ function validateArgs(args) {
|
|
|
39949
39996
|
}
|
|
39950
39997
|
function getLinterCommand(linter, mode, projectDir) {
|
|
39951
39998
|
const isWindows = process.platform === "win32";
|
|
39952
|
-
const binDir =
|
|
39953
|
-
const biomeBin = isWindows ?
|
|
39954
|
-
const eslintBin = isWindows ?
|
|
39999
|
+
const binDir = path23.join(projectDir, "node_modules", ".bin");
|
|
40000
|
+
const biomeBin = isWindows ? path23.join(binDir, "biome.EXE") : path23.join(binDir, "biome");
|
|
40001
|
+
const eslintBin = isWindows ? path23.join(binDir, "eslint.cmd") : path23.join(binDir, "eslint");
|
|
39955
40002
|
switch (linter) {
|
|
39956
40003
|
case "biome":
|
|
39957
40004
|
if (mode === "fix") {
|
|
@@ -39967,7 +40014,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
39967
40014
|
}
|
|
39968
40015
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
39969
40016
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
39970
|
-
const gradlew = fs11.existsSync(
|
|
40017
|
+
const gradlew = fs11.existsSync(path23.join(cwd, gradlewName)) ? path23.join(cwd, gradlewName) : null;
|
|
39971
40018
|
switch (linter) {
|
|
39972
40019
|
case "ruff":
|
|
39973
40020
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -40001,10 +40048,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
40001
40048
|
}
|
|
40002
40049
|
}
|
|
40003
40050
|
function detectRuff(cwd) {
|
|
40004
|
-
if (fs11.existsSync(
|
|
40051
|
+
if (fs11.existsSync(path23.join(cwd, "ruff.toml")))
|
|
40005
40052
|
return isCommandAvailable("ruff");
|
|
40006
40053
|
try {
|
|
40007
|
-
const pyproject =
|
|
40054
|
+
const pyproject = path23.join(cwd, "pyproject.toml");
|
|
40008
40055
|
if (fs11.existsSync(pyproject)) {
|
|
40009
40056
|
const content = fs11.readFileSync(pyproject, "utf-8");
|
|
40010
40057
|
if (content.includes("[tool.ruff]"))
|
|
@@ -40014,19 +40061,19 @@ function detectRuff(cwd) {
|
|
|
40014
40061
|
return false;
|
|
40015
40062
|
}
|
|
40016
40063
|
function detectClippy(cwd) {
|
|
40017
|
-
return fs11.existsSync(
|
|
40064
|
+
return fs11.existsSync(path23.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
40018
40065
|
}
|
|
40019
40066
|
function detectGolangciLint(cwd) {
|
|
40020
|
-
return fs11.existsSync(
|
|
40067
|
+
return fs11.existsSync(path23.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
40021
40068
|
}
|
|
40022
40069
|
function detectCheckstyle(cwd) {
|
|
40023
|
-
const hasMaven = fs11.existsSync(
|
|
40024
|
-
const hasGradle = fs11.existsSync(
|
|
40025
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(
|
|
40070
|
+
const hasMaven = fs11.existsSync(path23.join(cwd, "pom.xml"));
|
|
40071
|
+
const hasGradle = fs11.existsSync(path23.join(cwd, "build.gradle")) || fs11.existsSync(path23.join(cwd, "build.gradle.kts"));
|
|
40072
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path23.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
40026
40073
|
return (hasMaven || hasGradle) && hasBinary;
|
|
40027
40074
|
}
|
|
40028
40075
|
function detectKtlint(cwd) {
|
|
40029
|
-
const hasKotlin = fs11.existsSync(
|
|
40076
|
+
const hasKotlin = fs11.existsSync(path23.join(cwd, "build.gradle.kts")) || fs11.existsSync(path23.join(cwd, "build.gradle")) || (() => {
|
|
40030
40077
|
try {
|
|
40031
40078
|
return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
40032
40079
|
} catch {
|
|
@@ -40045,11 +40092,11 @@ function detectDotnetFormat(cwd) {
|
|
|
40045
40092
|
}
|
|
40046
40093
|
}
|
|
40047
40094
|
function detectCppcheck(cwd) {
|
|
40048
|
-
if (fs11.existsSync(
|
|
40095
|
+
if (fs11.existsSync(path23.join(cwd, "CMakeLists.txt"))) {
|
|
40049
40096
|
return isCommandAvailable("cppcheck");
|
|
40050
40097
|
}
|
|
40051
40098
|
try {
|
|
40052
|
-
const dirsToCheck = [cwd,
|
|
40099
|
+
const dirsToCheck = [cwd, path23.join(cwd, "src")];
|
|
40053
40100
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
40054
40101
|
try {
|
|
40055
40102
|
return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -40063,13 +40110,13 @@ function detectCppcheck(cwd) {
|
|
|
40063
40110
|
}
|
|
40064
40111
|
}
|
|
40065
40112
|
function detectSwiftlint(cwd) {
|
|
40066
|
-
return fs11.existsSync(
|
|
40113
|
+
return fs11.existsSync(path23.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
40067
40114
|
}
|
|
40068
40115
|
function detectDartAnalyze(cwd) {
|
|
40069
|
-
return fs11.existsSync(
|
|
40116
|
+
return fs11.existsSync(path23.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
40070
40117
|
}
|
|
40071
40118
|
function detectRubocop(cwd) {
|
|
40072
|
-
return (fs11.existsSync(
|
|
40119
|
+
return (fs11.existsSync(path23.join(cwd, "Gemfile")) || fs11.existsSync(path23.join(cwd, "gems.rb")) || fs11.existsSync(path23.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
40073
40120
|
}
|
|
40074
40121
|
function detectAdditionalLinter(cwd) {
|
|
40075
40122
|
if (detectRuff(cwd))
|
|
@@ -40097,10 +40144,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
40097
40144
|
function findBinInAncestors(startDir, binName) {
|
|
40098
40145
|
let dir = startDir;
|
|
40099
40146
|
while (true) {
|
|
40100
|
-
const candidate =
|
|
40147
|
+
const candidate = path23.join(dir, "node_modules", ".bin", binName);
|
|
40101
40148
|
if (fs11.existsSync(candidate))
|
|
40102
40149
|
return candidate;
|
|
40103
|
-
const parent =
|
|
40150
|
+
const parent = path23.dirname(dir);
|
|
40104
40151
|
if (parent === dir)
|
|
40105
40152
|
break;
|
|
40106
40153
|
dir = parent;
|
|
@@ -40109,10 +40156,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
40109
40156
|
}
|
|
40110
40157
|
function findBinInEnvPath(binName) {
|
|
40111
40158
|
const searchPath = process.env.PATH ?? "";
|
|
40112
|
-
for (const dir of searchPath.split(
|
|
40159
|
+
for (const dir of searchPath.split(path23.delimiter)) {
|
|
40113
40160
|
if (!dir)
|
|
40114
40161
|
continue;
|
|
40115
|
-
const candidate =
|
|
40162
|
+
const candidate = path23.join(dir, binName);
|
|
40116
40163
|
if (fs11.existsSync(candidate))
|
|
40117
40164
|
return candidate;
|
|
40118
40165
|
}
|
|
@@ -40125,13 +40172,13 @@ async function detectAvailableLinter(directory) {
|
|
|
40125
40172
|
return null;
|
|
40126
40173
|
const projectDir = directory;
|
|
40127
40174
|
const isWindows = process.platform === "win32";
|
|
40128
|
-
const biomeBin = isWindows ?
|
|
40129
|
-
const eslintBin = isWindows ?
|
|
40175
|
+
const biomeBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "biome.EXE") : path23.join(projectDir, "node_modules", ".bin", "biome");
|
|
40176
|
+
const eslintBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path23.join(projectDir, "node_modules", ".bin", "eslint");
|
|
40130
40177
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
40131
40178
|
if (localResult)
|
|
40132
40179
|
return localResult;
|
|
40133
|
-
const biomeAncestor = findBinInAncestors(
|
|
40134
|
-
const eslintAncestor = findBinInAncestors(
|
|
40180
|
+
const biomeAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
40181
|
+
const eslintAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
40135
40182
|
if (biomeAncestor || eslintAncestor) {
|
|
40136
40183
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
40137
40184
|
}
|
|
@@ -40340,7 +40387,7 @@ For Rust: rustup component add clippy`
|
|
|
40340
40387
|
// src/tools/secretscan.ts
|
|
40341
40388
|
init_zod();
|
|
40342
40389
|
import * as fs12 from "fs";
|
|
40343
|
-
import * as
|
|
40390
|
+
import * as path24 from "path";
|
|
40344
40391
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
40345
40392
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
40346
40393
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -40567,7 +40614,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
40567
40614
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
40568
40615
|
}
|
|
40569
40616
|
function loadSecretScanIgnore(scanDir) {
|
|
40570
|
-
const ignorePath =
|
|
40617
|
+
const ignorePath = path24.join(scanDir, ".secretscanignore");
|
|
40571
40618
|
try {
|
|
40572
40619
|
if (!fs12.existsSync(ignorePath))
|
|
40573
40620
|
return [];
|
|
@@ -40590,7 +40637,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
40590
40637
|
if (exactNames.has(entry))
|
|
40591
40638
|
return true;
|
|
40592
40639
|
for (const pattern of globPatterns) {
|
|
40593
|
-
if (
|
|
40640
|
+
if (path24.matchesGlob(relPath, pattern))
|
|
40594
40641
|
return true;
|
|
40595
40642
|
}
|
|
40596
40643
|
return false;
|
|
@@ -40611,7 +40658,7 @@ function validateDirectoryInput(dir) {
|
|
|
40611
40658
|
return null;
|
|
40612
40659
|
}
|
|
40613
40660
|
function isBinaryFile(filePath, buffer) {
|
|
40614
|
-
const ext =
|
|
40661
|
+
const ext = path24.extname(filePath).toLowerCase();
|
|
40615
40662
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
40616
40663
|
return true;
|
|
40617
40664
|
}
|
|
@@ -40748,9 +40795,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
40748
40795
|
return false;
|
|
40749
40796
|
}
|
|
40750
40797
|
function isPathWithinScope(realPath, scanDir) {
|
|
40751
|
-
const resolvedScanDir =
|
|
40752
|
-
const resolvedRealPath =
|
|
40753
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
40798
|
+
const resolvedScanDir = path24.resolve(scanDir);
|
|
40799
|
+
const resolvedRealPath = path24.resolve(realPath);
|
|
40800
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path24.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
40754
40801
|
}
|
|
40755
40802
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
40756
40803
|
skippedDirs: 0,
|
|
@@ -40776,8 +40823,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40776
40823
|
return a.localeCompare(b);
|
|
40777
40824
|
});
|
|
40778
40825
|
for (const entry of entries) {
|
|
40779
|
-
const fullPath =
|
|
40780
|
-
const relPath =
|
|
40826
|
+
const fullPath = path24.join(dir, entry);
|
|
40827
|
+
const relPath = path24.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
40781
40828
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
40782
40829
|
stats.skippedDirs++;
|
|
40783
40830
|
continue;
|
|
@@ -40812,7 +40859,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40812
40859
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
40813
40860
|
files.push(...subFiles);
|
|
40814
40861
|
} else if (lstat.isFile()) {
|
|
40815
|
-
const ext =
|
|
40862
|
+
const ext = path24.extname(fullPath).toLowerCase();
|
|
40816
40863
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
40817
40864
|
files.push(fullPath);
|
|
40818
40865
|
} else {
|
|
@@ -40878,7 +40925,7 @@ var secretscan = createSwarmTool({
|
|
|
40878
40925
|
}
|
|
40879
40926
|
}
|
|
40880
40927
|
try {
|
|
40881
|
-
const _scanDirRaw =
|
|
40928
|
+
const _scanDirRaw = path24.resolve(directory);
|
|
40882
40929
|
const scanDir = (() => {
|
|
40883
40930
|
try {
|
|
40884
40931
|
return fs12.realpathSync(_scanDirRaw);
|
|
@@ -41038,11 +41085,11 @@ async function runSecretscan(directory) {
|
|
|
41038
41085
|
// src/tools/test-runner.ts
|
|
41039
41086
|
init_zod();
|
|
41040
41087
|
import * as fs16 from "fs";
|
|
41041
|
-
import * as
|
|
41088
|
+
import * as path28 from "path";
|
|
41042
41089
|
|
|
41043
41090
|
// src/test-impact/analyzer.ts
|
|
41044
41091
|
import fs13 from "fs";
|
|
41045
|
-
import
|
|
41092
|
+
import path25 from "path";
|
|
41046
41093
|
var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
41047
41094
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
41048
41095
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -41067,8 +41114,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
41067
41114
|
if (!importPath.startsWith(".")) {
|
|
41068
41115
|
return null;
|
|
41069
41116
|
}
|
|
41070
|
-
const resolved =
|
|
41071
|
-
if (
|
|
41117
|
+
const resolved = path25.resolve(fromDir, importPath);
|
|
41118
|
+
if (path25.extname(resolved)) {
|
|
41072
41119
|
if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
|
|
41073
41120
|
return normalizePath(resolved);
|
|
41074
41121
|
}
|
|
@@ -41113,12 +41160,12 @@ function findTestFilesSync(cwd) {
|
|
|
41113
41160
|
for (const entry of entries) {
|
|
41114
41161
|
if (entry.isDirectory()) {
|
|
41115
41162
|
if (!skipDirs.has(entry.name)) {
|
|
41116
|
-
walk(
|
|
41163
|
+
walk(path25.join(dir, entry.name), visitedInodes);
|
|
41117
41164
|
}
|
|
41118
41165
|
} else if (entry.isFile()) {
|
|
41119
41166
|
const name = entry.name;
|
|
41120
41167
|
if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
|
|
41121
|
-
testFiles.push(normalizePath(
|
|
41168
|
+
testFiles.push(normalizePath(path25.join(dir, entry.name)));
|
|
41122
41169
|
}
|
|
41123
41170
|
}
|
|
41124
41171
|
}
|
|
@@ -41156,7 +41203,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
41156
41203
|
continue;
|
|
41157
41204
|
}
|
|
41158
41205
|
const imports = extractImports(content);
|
|
41159
|
-
const testDir =
|
|
41206
|
+
const testDir = path25.dirname(testFile);
|
|
41160
41207
|
for (const importPath of imports) {
|
|
41161
41208
|
const resolvedSource = resolveRelativeImport(testDir, importPath);
|
|
41162
41209
|
if (resolvedSource === null) {
|
|
@@ -41178,7 +41225,7 @@ async function buildImpactMap(cwd) {
|
|
|
41178
41225
|
return impactMap;
|
|
41179
41226
|
}
|
|
41180
41227
|
async function loadImpactMap(cwd) {
|
|
41181
|
-
const cachePath =
|
|
41228
|
+
const cachePath = path25.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
41182
41229
|
if (fs13.existsSync(cachePath)) {
|
|
41183
41230
|
try {
|
|
41184
41231
|
const content = fs13.readFileSync(cachePath, "utf-8");
|
|
@@ -41193,8 +41240,8 @@ async function loadImpactMap(cwd) {
|
|
|
41193
41240
|
return buildImpactMap(cwd);
|
|
41194
41241
|
}
|
|
41195
41242
|
async function saveImpactMap(cwd, impactMap) {
|
|
41196
|
-
const cacheDir2 =
|
|
41197
|
-
const cachePath =
|
|
41243
|
+
const cacheDir2 = path25.join(cwd, ".swarm", "cache");
|
|
41244
|
+
const cachePath = path25.join(cacheDir2, "impact-map.json");
|
|
41198
41245
|
if (!fs13.existsSync(cacheDir2)) {
|
|
41199
41246
|
fs13.mkdirSync(cacheDir2, { recursive: true });
|
|
41200
41247
|
}
|
|
@@ -41220,7 +41267,7 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
41220
41267
|
const impactedTestsSet = new Set;
|
|
41221
41268
|
const untestedFiles = [];
|
|
41222
41269
|
for (const changedFile of validFiles) {
|
|
41223
|
-
const normalizedChanged = normalizePath(
|
|
41270
|
+
const normalizedChanged = normalizePath(path25.resolve(changedFile));
|
|
41224
41271
|
const tests = impactMap[normalizedChanged];
|
|
41225
41272
|
if (tests && tests.length > 0) {
|
|
41226
41273
|
for (const test of tests) {
|
|
@@ -41467,13 +41514,13 @@ function detectFlakyTests(allHistory) {
|
|
|
41467
41514
|
|
|
41468
41515
|
// src/test-impact/history-store.ts
|
|
41469
41516
|
import fs14 from "fs";
|
|
41470
|
-
import
|
|
41517
|
+
import path26 from "path";
|
|
41471
41518
|
var MAX_HISTORY_PER_TEST = 20;
|
|
41472
41519
|
var MAX_ERROR_LENGTH = 500;
|
|
41473
41520
|
var MAX_STACK_LENGTH = 200;
|
|
41474
41521
|
var MAX_CHANGED_FILES = 50;
|
|
41475
41522
|
function getHistoryPath(workingDir) {
|
|
41476
|
-
return
|
|
41523
|
+
return path26.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
|
|
41477
41524
|
}
|
|
41478
41525
|
function sanitizeErrorMessage(errorMessage) {
|
|
41479
41526
|
if (errorMessage === undefined) {
|
|
@@ -41533,7 +41580,7 @@ function appendTestRun(record3, workingDir) {
|
|
|
41533
41580
|
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
41534
41581
|
};
|
|
41535
41582
|
const historyPath = getHistoryPath(workingDir);
|
|
41536
|
-
const historyDir =
|
|
41583
|
+
const historyDir = path26.dirname(historyPath);
|
|
41537
41584
|
if (!fs14.existsSync(historyDir)) {
|
|
41538
41585
|
fs14.mkdirSync(historyDir, { recursive: true });
|
|
41539
41586
|
}
|
|
@@ -41607,7 +41654,7 @@ function getAllHistory(workingDir) {
|
|
|
41607
41654
|
|
|
41608
41655
|
// src/tools/resolve-working-directory.ts
|
|
41609
41656
|
import * as fs15 from "fs";
|
|
41610
|
-
import * as
|
|
41657
|
+
import * as path27 from "path";
|
|
41611
41658
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
41612
41659
|
if (workingDirectory == null || workingDirectory === "") {
|
|
41613
41660
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -41627,15 +41674,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41627
41674
|
};
|
|
41628
41675
|
}
|
|
41629
41676
|
}
|
|
41630
|
-
const normalizedDir =
|
|
41631
|
-
const pathParts = normalizedDir.split(
|
|
41677
|
+
const normalizedDir = path27.normalize(workingDirectory);
|
|
41678
|
+
const pathParts = normalizedDir.split(path27.sep);
|
|
41632
41679
|
if (pathParts.includes("..")) {
|
|
41633
41680
|
return {
|
|
41634
41681
|
success: false,
|
|
41635
41682
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
41636
41683
|
};
|
|
41637
41684
|
}
|
|
41638
|
-
const resolvedDir =
|
|
41685
|
+
const resolvedDir = path27.resolve(normalizedDir);
|
|
41639
41686
|
let statResult;
|
|
41640
41687
|
try {
|
|
41641
41688
|
statResult = fs15.statSync(resolvedDir);
|
|
@@ -41651,7 +41698,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41651
41698
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
41652
41699
|
};
|
|
41653
41700
|
}
|
|
41654
|
-
const resolvedFallback =
|
|
41701
|
+
const resolvedFallback = path27.resolve(fallbackDirectory);
|
|
41655
41702
|
let fallbackExists = false;
|
|
41656
41703
|
try {
|
|
41657
41704
|
fs15.statSync(resolvedFallback);
|
|
@@ -41661,7 +41708,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41661
41708
|
}
|
|
41662
41709
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
41663
41710
|
if (fallbackExists) {
|
|
41664
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
41711
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path27.sep);
|
|
41665
41712
|
if (isSubdirectory) {
|
|
41666
41713
|
return {
|
|
41667
41714
|
success: false,
|
|
@@ -41751,14 +41798,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
41751
41798
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
41752
41799
|
}
|
|
41753
41800
|
function detectGoTest(cwd) {
|
|
41754
|
-
return fs16.existsSync(
|
|
41801
|
+
return fs16.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
41755
41802
|
}
|
|
41756
41803
|
function detectJavaMaven(cwd) {
|
|
41757
|
-
return fs16.existsSync(
|
|
41804
|
+
return fs16.existsSync(path28.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
41758
41805
|
}
|
|
41759
41806
|
function detectGradle(cwd) {
|
|
41760
|
-
const hasBuildFile = fs16.existsSync(
|
|
41761
|
-
const hasGradlew = fs16.existsSync(
|
|
41807
|
+
const hasBuildFile = fs16.existsSync(path28.join(cwd, "build.gradle")) || fs16.existsSync(path28.join(cwd, "build.gradle.kts"));
|
|
41808
|
+
const hasGradlew = fs16.existsSync(path28.join(cwd, "gradlew")) || fs16.existsSync(path28.join(cwd, "gradlew.bat"));
|
|
41762
41809
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
41763
41810
|
}
|
|
41764
41811
|
function detectDotnetTest(cwd) {
|
|
@@ -41771,30 +41818,30 @@ function detectDotnetTest(cwd) {
|
|
|
41771
41818
|
}
|
|
41772
41819
|
}
|
|
41773
41820
|
function detectCTest(cwd) {
|
|
41774
|
-
const hasSource = fs16.existsSync(
|
|
41775
|
-
const hasBuildCache = fs16.existsSync(
|
|
41821
|
+
const hasSource = fs16.existsSync(path28.join(cwd, "CMakeLists.txt"));
|
|
41822
|
+
const hasBuildCache = fs16.existsSync(path28.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path28.join(cwd, "build", "CMakeCache.txt"));
|
|
41776
41823
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
41777
41824
|
}
|
|
41778
41825
|
function detectSwiftTest(cwd) {
|
|
41779
|
-
return fs16.existsSync(
|
|
41826
|
+
return fs16.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
41780
41827
|
}
|
|
41781
41828
|
function detectDartTest(cwd) {
|
|
41782
|
-
return fs16.existsSync(
|
|
41829
|
+
return fs16.existsSync(path28.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
41783
41830
|
}
|
|
41784
41831
|
function detectRSpec(cwd) {
|
|
41785
|
-
const hasRSpecFile = fs16.existsSync(
|
|
41786
|
-
const hasGemfile = fs16.existsSync(
|
|
41787
|
-
const hasSpecDir = fs16.existsSync(
|
|
41832
|
+
const hasRSpecFile = fs16.existsSync(path28.join(cwd, ".rspec"));
|
|
41833
|
+
const hasGemfile = fs16.existsSync(path28.join(cwd, "Gemfile"));
|
|
41834
|
+
const hasSpecDir = fs16.existsSync(path28.join(cwd, "spec"));
|
|
41788
41835
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
41789
41836
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
41790
41837
|
}
|
|
41791
41838
|
function detectMinitest(cwd) {
|
|
41792
|
-
return fs16.existsSync(
|
|
41839
|
+
return fs16.existsSync(path28.join(cwd, "test")) && (fs16.existsSync(path28.join(cwd, "Gemfile")) || fs16.existsSync(path28.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
41793
41840
|
}
|
|
41794
41841
|
async function detectTestFramework(cwd) {
|
|
41795
41842
|
const baseDir = cwd;
|
|
41796
41843
|
try {
|
|
41797
|
-
const packageJsonPath =
|
|
41844
|
+
const packageJsonPath = path28.join(baseDir, "package.json");
|
|
41798
41845
|
if (fs16.existsSync(packageJsonPath)) {
|
|
41799
41846
|
const content = fs16.readFileSync(packageJsonPath, "utf-8");
|
|
41800
41847
|
const pkg = JSON.parse(content);
|
|
@@ -41815,16 +41862,16 @@ async function detectTestFramework(cwd) {
|
|
|
41815
41862
|
return "jest";
|
|
41816
41863
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
41817
41864
|
return "mocha";
|
|
41818
|
-
if (fs16.existsSync(
|
|
41865
|
+
if (fs16.existsSync(path28.join(baseDir, "bun.lockb")) || fs16.existsSync(path28.join(baseDir, "bun.lock"))) {
|
|
41819
41866
|
if (scripts.test?.includes("bun"))
|
|
41820
41867
|
return "bun";
|
|
41821
41868
|
}
|
|
41822
41869
|
}
|
|
41823
41870
|
} catch {}
|
|
41824
41871
|
try {
|
|
41825
|
-
const pyprojectTomlPath =
|
|
41826
|
-
const setupCfgPath =
|
|
41827
|
-
const requirementsTxtPath =
|
|
41872
|
+
const pyprojectTomlPath = path28.join(baseDir, "pyproject.toml");
|
|
41873
|
+
const setupCfgPath = path28.join(baseDir, "setup.cfg");
|
|
41874
|
+
const requirementsTxtPath = path28.join(baseDir, "requirements.txt");
|
|
41828
41875
|
if (fs16.existsSync(pyprojectTomlPath)) {
|
|
41829
41876
|
const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
|
|
41830
41877
|
if (content.includes("[tool.pytest"))
|
|
@@ -41844,7 +41891,7 @@ async function detectTestFramework(cwd) {
|
|
|
41844
41891
|
}
|
|
41845
41892
|
} catch {}
|
|
41846
41893
|
try {
|
|
41847
|
-
const cargoTomlPath =
|
|
41894
|
+
const cargoTomlPath = path28.join(baseDir, "Cargo.toml");
|
|
41848
41895
|
if (fs16.existsSync(cargoTomlPath)) {
|
|
41849
41896
|
const content = fs16.readFileSync(cargoTomlPath, "utf-8");
|
|
41850
41897
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -41855,9 +41902,9 @@ async function detectTestFramework(cwd) {
|
|
|
41855
41902
|
}
|
|
41856
41903
|
} catch {}
|
|
41857
41904
|
try {
|
|
41858
|
-
const pesterConfigPath =
|
|
41859
|
-
const pesterConfigJsonPath =
|
|
41860
|
-
const pesterPs1Path =
|
|
41905
|
+
const pesterConfigPath = path28.join(baseDir, "pester.config.ps1");
|
|
41906
|
+
const pesterConfigJsonPath = path28.join(baseDir, "pester.config.ps1.json");
|
|
41907
|
+
const pesterPs1Path = path28.join(baseDir, "tests.ps1");
|
|
41861
41908
|
if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
|
|
41862
41909
|
return "pester";
|
|
41863
41910
|
}
|
|
@@ -41900,12 +41947,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
41900
41947
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
41901
41948
|
}
|
|
41902
41949
|
function resolveWorkspacePath(file3, workingDir) {
|
|
41903
|
-
return
|
|
41950
|
+
return path28.isAbsolute(file3) ? path28.resolve(file3) : path28.resolve(workingDir, file3);
|
|
41904
41951
|
}
|
|
41905
41952
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
41906
41953
|
if (!preferRelative)
|
|
41907
41954
|
return absolutePath;
|
|
41908
|
-
return
|
|
41955
|
+
return path28.relative(workingDir, absolutePath);
|
|
41909
41956
|
}
|
|
41910
41957
|
function dedupePush(target, value) {
|
|
41911
41958
|
if (!target.includes(value)) {
|
|
@@ -41942,18 +41989,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
41942
41989
|
}
|
|
41943
41990
|
}
|
|
41944
41991
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
41945
|
-
const relativeDir =
|
|
41992
|
+
const relativeDir = path28.dirname(relativePath);
|
|
41946
41993
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
41947
41994
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
41948
|
-
const rootDir =
|
|
41949
|
-
return nestedRelativeDir ? [rootDir,
|
|
41995
|
+
const rootDir = path28.join(workingDir, dirName);
|
|
41996
|
+
return nestedRelativeDir ? [rootDir, path28.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
41950
41997
|
});
|
|
41951
41998
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
41952
41999
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
41953
|
-
directories.push(
|
|
42000
|
+
directories.push(path28.join(workingDir, "src/test/java", path28.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
41954
42001
|
}
|
|
41955
42002
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
41956
|
-
directories.push(
|
|
42003
|
+
directories.push(path28.join(workingDir, "src/test/kotlin", path28.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
41957
42004
|
}
|
|
41958
42005
|
return [...new Set(directories)];
|
|
41959
42006
|
}
|
|
@@ -41981,23 +42028,23 @@ function isLanguageSpecificTestFile(basename4) {
|
|
|
41981
42028
|
}
|
|
41982
42029
|
function isConventionTestFilePath(filePath) {
|
|
41983
42030
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
41984
|
-
const basename4 =
|
|
42031
|
+
const basename4 = path28.basename(filePath);
|
|
41985
42032
|
return hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || isLanguageSpecificTestFile(basename4) || isTestDirectoryPath(normalizedPath);
|
|
41986
42033
|
}
|
|
41987
42034
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
41988
42035
|
const testFiles = [];
|
|
41989
42036
|
for (const file3 of sourceFiles) {
|
|
41990
42037
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
41991
|
-
const relativeFile =
|
|
41992
|
-
const basename4 =
|
|
41993
|
-
const dirname11 =
|
|
41994
|
-
const preferRelativeOutput = !
|
|
42038
|
+
const relativeFile = path28.relative(workingDir, absoluteFile);
|
|
42039
|
+
const basename4 = path28.basename(absoluteFile);
|
|
42040
|
+
const dirname11 = path28.dirname(absoluteFile);
|
|
42041
|
+
const preferRelativeOutput = !path28.isAbsolute(file3);
|
|
41995
42042
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
41996
42043
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
41997
42044
|
continue;
|
|
41998
42045
|
}
|
|
41999
42046
|
const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
|
|
42000
|
-
const ext =
|
|
42047
|
+
const ext = path28.extname(basename4);
|
|
42001
42048
|
const genericTestNames = [
|
|
42002
42049
|
`${nameWithoutExt}.spec${ext}`,
|
|
42003
42050
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -42006,7 +42053,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
42006
42053
|
const colocatedCandidates = [
|
|
42007
42054
|
...genericTestNames,
|
|
42008
42055
|
...languageSpecificTestNames
|
|
42009
|
-
].map((candidateName) =>
|
|
42056
|
+
].map((candidateName) => path28.join(dirname11, candidateName));
|
|
42010
42057
|
const testDirectoryNames = [
|
|
42011
42058
|
basename4,
|
|
42012
42059
|
...genericTestNames,
|
|
@@ -42015,8 +42062,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
42015
42062
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
42016
42063
|
const possibleTestFiles = [
|
|
42017
42064
|
...colocatedCandidates,
|
|
42018
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
42019
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
42065
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path28.join(dirname11, dirName, candidateName))),
|
|
42066
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path28.join(candidateDir, candidateName)))
|
|
42020
42067
|
];
|
|
42021
42068
|
for (const testFile of possibleTestFiles) {
|
|
42022
42069
|
if (fs16.existsSync(testFile)) {
|
|
@@ -42037,7 +42084,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42037
42084
|
try {
|
|
42038
42085
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
42039
42086
|
const content = fs16.readFileSync(absoluteTestFile, "utf-8");
|
|
42040
|
-
const testDir =
|
|
42087
|
+
const testDir = path28.dirname(absoluteTestFile);
|
|
42041
42088
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
42042
42089
|
let match;
|
|
42043
42090
|
match = importRegex.exec(content);
|
|
@@ -42045,8 +42092,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42045
42092
|
const importPath = match[1];
|
|
42046
42093
|
let resolvedImport;
|
|
42047
42094
|
if (importPath.startsWith(".")) {
|
|
42048
|
-
resolvedImport =
|
|
42049
|
-
const existingExt =
|
|
42095
|
+
resolvedImport = path28.resolve(testDir, importPath);
|
|
42096
|
+
const existingExt = path28.extname(resolvedImport);
|
|
42050
42097
|
if (!existingExt) {
|
|
42051
42098
|
for (const extToTry of [
|
|
42052
42099
|
".ts",
|
|
@@ -42066,12 +42113,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42066
42113
|
} else {
|
|
42067
42114
|
continue;
|
|
42068
42115
|
}
|
|
42069
|
-
const importBasename =
|
|
42070
|
-
const importDir =
|
|
42116
|
+
const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
|
|
42117
|
+
const importDir = path28.dirname(resolvedImport);
|
|
42071
42118
|
for (const sourceFile of absoluteSourceFiles) {
|
|
42072
|
-
const sourceDir =
|
|
42073
|
-
const sourceBasename =
|
|
42074
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
42119
|
+
const sourceDir = path28.dirname(sourceFile);
|
|
42120
|
+
const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
|
|
42121
|
+
const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
|
|
42075
42122
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
42076
42123
|
dedupePush(testFiles, testFile);
|
|
42077
42124
|
break;
|
|
@@ -42084,8 +42131,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42084
42131
|
while (match !== null) {
|
|
42085
42132
|
const importPath = match[1];
|
|
42086
42133
|
if (importPath.startsWith(".")) {
|
|
42087
|
-
let resolvedImport =
|
|
42088
|
-
const existingExt =
|
|
42134
|
+
let resolvedImport = path28.resolve(testDir, importPath);
|
|
42135
|
+
const existingExt = path28.extname(resolvedImport);
|
|
42089
42136
|
if (!existingExt) {
|
|
42090
42137
|
for (const extToTry of [
|
|
42091
42138
|
".ts",
|
|
@@ -42102,12 +42149,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42102
42149
|
}
|
|
42103
42150
|
}
|
|
42104
42151
|
}
|
|
42105
|
-
const importDir =
|
|
42106
|
-
const importBasename =
|
|
42152
|
+
const importDir = path28.dirname(resolvedImport);
|
|
42153
|
+
const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
|
|
42107
42154
|
for (const sourceFile of absoluteSourceFiles) {
|
|
42108
|
-
const sourceDir =
|
|
42109
|
-
const sourceBasename =
|
|
42110
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
42155
|
+
const sourceDir = path28.dirname(sourceFile);
|
|
42156
|
+
const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
|
|
42157
|
+
const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
|
|
42111
42158
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
42112
42159
|
dedupePush(testFiles, testFile);
|
|
42113
42160
|
break;
|
|
@@ -42210,8 +42257,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
42210
42257
|
return ["mvn", "test"];
|
|
42211
42258
|
case "gradle": {
|
|
42212
42259
|
const isWindows = process.platform === "win32";
|
|
42213
|
-
const hasGradlewBat = fs16.existsSync(
|
|
42214
|
-
const hasGradlew = fs16.existsSync(
|
|
42260
|
+
const hasGradlewBat = fs16.existsSync(path28.join(baseDir, "gradlew.bat"));
|
|
42261
|
+
const hasGradlew = fs16.existsSync(path28.join(baseDir, "gradlew"));
|
|
42215
42262
|
if (hasGradlewBat && isWindows)
|
|
42216
42263
|
return ["gradlew.bat", "test"];
|
|
42217
42264
|
if (hasGradlew)
|
|
@@ -42228,7 +42275,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
42228
42275
|
"cmake-build-release",
|
|
42229
42276
|
"out"
|
|
42230
42277
|
];
|
|
42231
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(
|
|
42278
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path28.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
42232
42279
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
42233
42280
|
}
|
|
42234
42281
|
case "swift-test":
|
|
@@ -42856,7 +42903,7 @@ var test_runner = createSwarmTool({
|
|
|
42856
42903
|
const sourceFiles = args.files.filter((file3) => {
|
|
42857
42904
|
if (directTestFiles.includes(file3))
|
|
42858
42905
|
return false;
|
|
42859
|
-
const ext =
|
|
42906
|
+
const ext = path28.extname(file3).toLowerCase();
|
|
42860
42907
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42861
42908
|
});
|
|
42862
42909
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -42891,7 +42938,7 @@ var test_runner = createSwarmTool({
|
|
|
42891
42938
|
if (isConventionTestFilePath(f)) {
|
|
42892
42939
|
return false;
|
|
42893
42940
|
}
|
|
42894
|
-
const ext =
|
|
42941
|
+
const ext = path28.extname(f).toLowerCase();
|
|
42895
42942
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42896
42943
|
});
|
|
42897
42944
|
if (sourceFiles.length === 0) {
|
|
@@ -42918,7 +42965,7 @@ var test_runner = createSwarmTool({
|
|
|
42918
42965
|
if (isConventionTestFilePath(f)) {
|
|
42919
42966
|
return false;
|
|
42920
42967
|
}
|
|
42921
|
-
const ext =
|
|
42968
|
+
const ext = path28.extname(f).toLowerCase();
|
|
42922
42969
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42923
42970
|
});
|
|
42924
42971
|
if (sourceFiles.length === 0) {
|
|
@@ -42936,8 +42983,8 @@ var test_runner = createSwarmTool({
|
|
|
42936
42983
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
42937
42984
|
if (impactResult.impactedTests.length > 0) {
|
|
42938
42985
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
42939
|
-
const relativePath =
|
|
42940
|
-
return
|
|
42986
|
+
const relativePath = path28.relative(workingDir, absPath);
|
|
42987
|
+
return path28.isAbsolute(relativePath) ? absPath : relativePath;
|
|
42941
42988
|
});
|
|
42942
42989
|
} else {
|
|
42943
42990
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -43030,8 +43077,8 @@ function validateDirectoryPath(dir) {
|
|
|
43030
43077
|
if (dir.includes("..")) {
|
|
43031
43078
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
43032
43079
|
}
|
|
43033
|
-
const normalized =
|
|
43034
|
-
const absolutePath =
|
|
43080
|
+
const normalized = path29.normalize(dir);
|
|
43081
|
+
const absolutePath = path29.isAbsolute(normalized) ? normalized : path29.resolve(normalized);
|
|
43035
43082
|
return absolutePath;
|
|
43036
43083
|
}
|
|
43037
43084
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -43054,7 +43101,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
43054
43101
|
}
|
|
43055
43102
|
function getPackageVersion(dir) {
|
|
43056
43103
|
try {
|
|
43057
|
-
const packagePath =
|
|
43104
|
+
const packagePath = path29.join(dir, "package.json");
|
|
43058
43105
|
if (fs17.existsSync(packagePath)) {
|
|
43059
43106
|
const content = fs17.readFileSync(packagePath, "utf-8");
|
|
43060
43107
|
const pkg = JSON.parse(content);
|
|
@@ -43065,7 +43112,7 @@ function getPackageVersion(dir) {
|
|
|
43065
43112
|
}
|
|
43066
43113
|
function getChangelogVersion(dir) {
|
|
43067
43114
|
try {
|
|
43068
|
-
const changelogPath =
|
|
43115
|
+
const changelogPath = path29.join(dir, "CHANGELOG.md");
|
|
43069
43116
|
if (fs17.existsSync(changelogPath)) {
|
|
43070
43117
|
const content = fs17.readFileSync(changelogPath, "utf-8");
|
|
43071
43118
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -43079,7 +43126,7 @@ function getChangelogVersion(dir) {
|
|
|
43079
43126
|
function getVersionFileVersion(dir) {
|
|
43080
43127
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
43081
43128
|
for (const file3 of possibleFiles) {
|
|
43082
|
-
const filePath =
|
|
43129
|
+
const filePath = path29.join(dir, file3);
|
|
43083
43130
|
if (fs17.existsSync(filePath)) {
|
|
43084
43131
|
try {
|
|
43085
43132
|
const content = fs17.readFileSync(filePath, "utf-8").trim();
|
|
@@ -43406,7 +43453,7 @@ async function runEvidenceCheck(dir) {
|
|
|
43406
43453
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
43407
43454
|
const startTime = Date.now();
|
|
43408
43455
|
try {
|
|
43409
|
-
const specPath =
|
|
43456
|
+
const specPath = path29.join(dir, ".swarm", "spec.md");
|
|
43410
43457
|
if (!fs17.existsSync(specPath)) {
|
|
43411
43458
|
return {
|
|
43412
43459
|
type: "req_coverage",
|
|
@@ -44529,7 +44576,7 @@ async function handleResetCommand(directory, args) {
|
|
|
44529
44576
|
// src/commands/reset-session.ts
|
|
44530
44577
|
init_utils2();
|
|
44531
44578
|
import * as fs19 from "fs";
|
|
44532
|
-
import * as
|
|
44579
|
+
import * as path30 from "path";
|
|
44533
44580
|
async function handleResetSessionCommand(directory, _args) {
|
|
44534
44581
|
const results = [];
|
|
44535
44582
|
try {
|
|
@@ -44544,13 +44591,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
44544
44591
|
results.push("\u274C Failed to delete state.json");
|
|
44545
44592
|
}
|
|
44546
44593
|
try {
|
|
44547
|
-
const sessionDir =
|
|
44594
|
+
const sessionDir = path30.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
44548
44595
|
if (fs19.existsSync(sessionDir)) {
|
|
44549
44596
|
const files = fs19.readdirSync(sessionDir);
|
|
44550
44597
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
44551
44598
|
let deletedCount = 0;
|
|
44552
44599
|
for (const file3 of otherFiles) {
|
|
44553
|
-
const filePath =
|
|
44600
|
+
const filePath = path30.join(sessionDir, file3);
|
|
44554
44601
|
if (fs19.lstatSync(filePath).isFile()) {
|
|
44555
44602
|
fs19.unlinkSync(filePath);
|
|
44556
44603
|
deletedCount++;
|
|
@@ -44580,7 +44627,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
44580
44627
|
// src/summaries/manager.ts
|
|
44581
44628
|
init_utils2();
|
|
44582
44629
|
init_utils();
|
|
44583
|
-
import * as
|
|
44630
|
+
import * as path31 from "path";
|
|
44584
44631
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
44585
44632
|
function sanitizeSummaryId(id) {
|
|
44586
44633
|
if (!id || id.length === 0) {
|
|
@@ -44604,7 +44651,7 @@ function sanitizeSummaryId(id) {
|
|
|
44604
44651
|
}
|
|
44605
44652
|
async function loadFullOutput(directory, id) {
|
|
44606
44653
|
const sanitizedId = sanitizeSummaryId(id);
|
|
44607
|
-
const relativePath =
|
|
44654
|
+
const relativePath = path31.join("summaries", `${sanitizedId}.json`);
|
|
44608
44655
|
validateSwarmPath(directory, relativePath);
|
|
44609
44656
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
44610
44657
|
if (content === null) {
|
|
@@ -44660,7 +44707,7 @@ init_plan_schema();
|
|
|
44660
44707
|
init_utils2();
|
|
44661
44708
|
init_ledger();
|
|
44662
44709
|
import * as fs20 from "fs";
|
|
44663
|
-
import * as
|
|
44710
|
+
import * as path32 from "path";
|
|
44664
44711
|
async function handleRollbackCommand(directory, args) {
|
|
44665
44712
|
const phaseArg = args[0];
|
|
44666
44713
|
if (!phaseArg) {
|
|
@@ -44725,8 +44772,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44725
44772
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
44726
44773
|
continue;
|
|
44727
44774
|
}
|
|
44728
|
-
const src =
|
|
44729
|
-
const dest =
|
|
44775
|
+
const src = path32.join(checkpointDir, file3);
|
|
44776
|
+
const dest = path32.join(swarmDir, file3);
|
|
44730
44777
|
try {
|
|
44731
44778
|
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
44732
44779
|
successes.push(file3);
|
|
@@ -44745,12 +44792,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44745
44792
|
].join(`
|
|
44746
44793
|
`);
|
|
44747
44794
|
}
|
|
44748
|
-
const existingLedgerPath =
|
|
44795
|
+
const existingLedgerPath = path32.join(swarmDir, "plan-ledger.jsonl");
|
|
44749
44796
|
if (fs20.existsSync(existingLedgerPath)) {
|
|
44750
44797
|
fs20.unlinkSync(existingLedgerPath);
|
|
44751
44798
|
}
|
|
44752
44799
|
try {
|
|
44753
|
-
const planJsonPath =
|
|
44800
|
+
const planJsonPath = path32.join(swarmDir, "plan.json");
|
|
44754
44801
|
if (fs20.existsSync(planJsonPath)) {
|
|
44755
44802
|
const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
|
|
44756
44803
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -44823,9 +44870,9 @@ async function handleSimulateCommand(directory, args) {
|
|
|
44823
44870
|
const report = reportLines.filter(Boolean).join(`
|
|
44824
44871
|
`);
|
|
44825
44872
|
const fs21 = await import("fs/promises");
|
|
44826
|
-
const
|
|
44827
|
-
const reportPath =
|
|
44828
|
-
await fs21.mkdir(
|
|
44873
|
+
const path33 = await import("path");
|
|
44874
|
+
const reportPath = path33.join(directory, ".swarm", "simulate-report.md");
|
|
44875
|
+
await fs21.mkdir(path33.dirname(reportPath), { recursive: true });
|
|
44829
44876
|
await fs21.writeFile(reportPath, report, "utf-8");
|
|
44830
44877
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
44831
44878
|
}
|
|
@@ -45360,21 +45407,34 @@ function resolveCommand(tokens) {
|
|
|
45360
45407
|
|
|
45361
45408
|
// src/cli/index.ts
|
|
45362
45409
|
var { version: version4 } = package_default;
|
|
45363
|
-
var CONFIG_DIR =
|
|
45364
|
-
var OPENCODE_CONFIG_PATH =
|
|
45365
|
-
var PLUGIN_CONFIG_PATH =
|
|
45366
|
-
var PROMPTS_DIR =
|
|
45367
|
-
var OPENCODE_PLUGIN_CACHE_PATHS =
|
|
45368
|
-
path32.join(process.env.XDG_CACHE_HOME || path32.join(os6.homedir(), ".cache"), "opencode", "packages", "opencode-swarm@latest"),
|
|
45369
|
-
path32.join(CONFIG_DIR, "node_modules", "opencode-swarm")
|
|
45370
|
-
];
|
|
45410
|
+
var CONFIG_DIR = getPluginConfigDir();
|
|
45411
|
+
var OPENCODE_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode.json");
|
|
45412
|
+
var PLUGIN_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode-swarm.json");
|
|
45413
|
+
var PROMPTS_DIR = path33.join(CONFIG_DIR, "opencode-swarm");
|
|
45414
|
+
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
45371
45415
|
function isSafeCachePath(p) {
|
|
45372
|
-
const resolved =
|
|
45373
|
-
const home =
|
|
45374
|
-
if (resolved === "/" || resolved === home || resolved.length <= home.length)
|
|
45416
|
+
const resolved = path33.resolve(p);
|
|
45417
|
+
const home = path33.resolve(os7.homedir());
|
|
45418
|
+
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
45419
|
+
return false;
|
|
45420
|
+
}
|
|
45421
|
+
const segments = resolved.split(path33.sep).filter((s) => s.length > 0);
|
|
45422
|
+
if (segments.length < 4) {
|
|
45423
|
+
return false;
|
|
45424
|
+
}
|
|
45425
|
+
const leaf = path33.basename(resolved);
|
|
45426
|
+
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
45427
|
+
return false;
|
|
45428
|
+
}
|
|
45429
|
+
const parent = path33.basename(path33.dirname(resolved));
|
|
45430
|
+
if (parent !== "packages" && parent !== "node_modules") {
|
|
45375
45431
|
return false;
|
|
45376
|
-
|
|
45377
|
-
|
|
45432
|
+
}
|
|
45433
|
+
const grandparent = path33.basename(path33.dirname(path33.dirname(resolved)));
|
|
45434
|
+
if (grandparent !== "opencode") {
|
|
45435
|
+
return false;
|
|
45436
|
+
}
|
|
45437
|
+
return true;
|
|
45378
45438
|
}
|
|
45379
45439
|
function ensureDir(dir) {
|
|
45380
45440
|
if (!fs21.existsSync(dir)) {
|
|
@@ -45396,8 +45456,8 @@ function saveJson(filepath, data) {
|
|
|
45396
45456
|
}
|
|
45397
45457
|
function writeProjectConfigIfMissing(cwd) {
|
|
45398
45458
|
try {
|
|
45399
|
-
const opencodeDir =
|
|
45400
|
-
const projectConfigPath =
|
|
45459
|
+
const opencodeDir = path33.join(cwd, ".opencode");
|
|
45460
|
+
const projectConfigPath = path33.join(opencodeDir, "opencode-swarm.json");
|
|
45401
45461
|
if (fs21.existsSync(projectConfigPath)) {
|
|
45402
45462
|
return;
|
|
45403
45463
|
}
|
|
@@ -45415,7 +45475,7 @@ async function install() {
|
|
|
45415
45475
|
`);
|
|
45416
45476
|
ensureDir(CONFIG_DIR);
|
|
45417
45477
|
ensureDir(PROMPTS_DIR);
|
|
45418
|
-
const LEGACY_CONFIG_PATH =
|
|
45478
|
+
const LEGACY_CONFIG_PATH = path33.join(CONFIG_DIR, "config.json");
|
|
45419
45479
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
45420
45480
|
if (!opencodeConfig) {
|
|
45421
45481
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|