opencode-swarm 7.49.1 → 7.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/index.js +30 -9
- package/dist/hooks/scope-guard.d.ts +24 -0
- package/dist/index.js +1315 -440
- package/dist/tools/apply-patch.d.ts +48 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var package_default;
|
|
|
69
69
|
var init_package = __esm(() => {
|
|
70
70
|
package_default = {
|
|
71
71
|
name: "opencode-swarm",
|
|
72
|
-
version: "7.
|
|
72
|
+
version: "7.50.1",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -679,6 +679,10 @@ var init_tool_metadata = __esm(() => {
|
|
|
679
679
|
lean_turbo_status: {
|
|
680
680
|
description: "returns Lean Turbo configuration and active status for the current session",
|
|
681
681
|
agents: ["architect"]
|
|
682
|
+
},
|
|
683
|
+
apply_patch: {
|
|
684
|
+
description: "Apply a unified diff patch to workspace files with exact context matching, atomic writes, and path validation",
|
|
685
|
+
agents: ["coder"]
|
|
682
686
|
}
|
|
683
687
|
};
|
|
684
688
|
TOOL_NAMES = Object.keys(TOOL_METADATA);
|
|
@@ -75780,10 +75784,33 @@ function classifyAndCluster(testResults, history) {
|
|
|
75780
75784
|
}
|
|
75781
75785
|
|
|
75782
75786
|
// src/test-impact/flaky-detector.ts
|
|
75787
|
+
function computeCombinedFlakyScore(recent) {
|
|
75788
|
+
const totalRuns = recent.length;
|
|
75789
|
+
if (totalRuns < 2) {
|
|
75790
|
+
return { alternationCount: 0, flakyScore: 0 };
|
|
75791
|
+
}
|
|
75792
|
+
let alternationCount = 0;
|
|
75793
|
+
let passCount = 0;
|
|
75794
|
+
for (let i2 = 0;i2 < recent.length; i2++) {
|
|
75795
|
+
if (recent[i2].result === "pass") {
|
|
75796
|
+
passCount++;
|
|
75797
|
+
}
|
|
75798
|
+
if (i2 > 0 && recent[i2].result !== recent[i2 - 1].result) {
|
|
75799
|
+
alternationCount++;
|
|
75800
|
+
}
|
|
75801
|
+
}
|
|
75802
|
+
const alternationScore = alternationCount / totalRuns;
|
|
75803
|
+
const passRate = passCount / totalRuns;
|
|
75804
|
+
const passRateVarianceScore = 4 * passRate * (1 - passRate);
|
|
75805
|
+
return {
|
|
75806
|
+
alternationCount,
|
|
75807
|
+
flakyScore: (alternationScore + passRateVarianceScore) / 2
|
|
75808
|
+
};
|
|
75809
|
+
}
|
|
75783
75810
|
function detectFlakyTests(allHistory) {
|
|
75784
75811
|
const grouped = new Map;
|
|
75785
75812
|
for (const record3 of allHistory) {
|
|
75786
|
-
const key = `${record3.testFile.toLowerCase()}
|
|
75813
|
+
const key = `${record3.testFile.toLowerCase()}\x00${record3.testName.toLowerCase()}`;
|
|
75787
75814
|
if (!grouped.has(key)) {
|
|
75788
75815
|
grouped.set(key, {
|
|
75789
75816
|
records: [],
|
|
@@ -75805,13 +75832,7 @@ function detectFlakyTests(allHistory) {
|
|
|
75805
75832
|
if (totalRuns < 2) {
|
|
75806
75833
|
continue;
|
|
75807
75834
|
}
|
|
75808
|
-
|
|
75809
|
-
for (let i2 = 1;i2 < recent.length; i2++) {
|
|
75810
|
-
if (recent[i2].result !== recent[i2 - 1].result) {
|
|
75811
|
-
alternationCount++;
|
|
75812
|
-
}
|
|
75813
|
-
}
|
|
75814
|
-
const flakyScore = totalRuns >= 2 ? alternationCount / totalRuns : 0;
|
|
75835
|
+
const { alternationCount, flakyScore } = computeCombinedFlakyScore(recent);
|
|
75815
75836
|
const isQuarantined = flakyScore > FLAKY_THRESHOLD && totalRuns >= MIN_RUNS_FOR_QUARANTINE;
|
|
75816
75837
|
const recentResults = recent.map((r) => r.result);
|
|
75817
75838
|
const testFile = entry.originalFile;
|
|
@@ -92314,7 +92335,7 @@ __export(exports_design_doc_drift, {
|
|
|
92314
92335
|
_internals: () => _internals60
|
|
92315
92336
|
});
|
|
92316
92337
|
import * as fs98 from "node:fs";
|
|
92317
|
-
import * as
|
|
92338
|
+
import * as path137 from "node:path";
|
|
92318
92339
|
function mtimeMsOrNull(absPath) {
|
|
92319
92340
|
try {
|
|
92320
92341
|
return fs98.statSync(absPath).mtimeMs;
|
|
@@ -92325,35 +92346,35 @@ function mtimeMsOrNull(absPath) {
|
|
|
92325
92346
|
function resolveAnchorWithin(directory, anchor) {
|
|
92326
92347
|
if (!anchor || typeof anchor !== "string")
|
|
92327
92348
|
return null;
|
|
92328
|
-
const root =
|
|
92329
|
-
const resolved =
|
|
92330
|
-
const rel =
|
|
92331
|
-
if (rel.startsWith("..") ||
|
|
92349
|
+
const root = path137.resolve(directory);
|
|
92350
|
+
const resolved = path137.resolve(root, anchor);
|
|
92351
|
+
const rel = path137.relative(root, resolved);
|
|
92352
|
+
if (rel.startsWith("..") || path137.isAbsolute(rel))
|
|
92332
92353
|
return null;
|
|
92333
92354
|
return resolved;
|
|
92334
92355
|
}
|
|
92335
92356
|
async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
92336
92357
|
try {
|
|
92337
|
-
const root =
|
|
92338
|
-
const outAbs =
|
|
92339
|
-
const outRel =
|
|
92340
|
-
if (outRel.startsWith("..") ||
|
|
92358
|
+
const root = path137.resolve(directory);
|
|
92359
|
+
const outAbs = path137.resolve(root, outDir);
|
|
92360
|
+
const outRel = path137.relative(root, outAbs);
|
|
92361
|
+
if (outRel.startsWith("..") || path137.isAbsolute(outRel)) {
|
|
92341
92362
|
return null;
|
|
92342
92363
|
}
|
|
92343
92364
|
const docMtimes = new Map;
|
|
92344
92365
|
const checkedDocs = [];
|
|
92345
92366
|
const missingDocs = [];
|
|
92346
92367
|
for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
|
|
92347
|
-
const abs =
|
|
92368
|
+
const abs = path137.join(outAbs, relFile);
|
|
92348
92369
|
const mtime = mtimeMsOrNull(abs);
|
|
92349
92370
|
docMtimes.set(docName, mtime);
|
|
92350
92371
|
if (mtime === null) {
|
|
92351
|
-
missingDocs.push(
|
|
92372
|
+
missingDocs.push(path137.join(outDir, relFile));
|
|
92352
92373
|
} else {
|
|
92353
|
-
checkedDocs.push(
|
|
92374
|
+
checkedDocs.push(path137.join(outDir, relFile));
|
|
92354
92375
|
}
|
|
92355
92376
|
}
|
|
92356
|
-
const traceabilityAbs =
|
|
92377
|
+
const traceabilityAbs = path137.join(outAbs, TRACEABILITY_REL);
|
|
92357
92378
|
let registry3 = null;
|
|
92358
92379
|
try {
|
|
92359
92380
|
const stat9 = await fs98.promises.stat(traceabilityAbs);
|
|
@@ -92366,7 +92387,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
92366
92387
|
registry3 = null;
|
|
92367
92388
|
}
|
|
92368
92389
|
const noDocs = checkedDocs.length === 0 || registry3 === null;
|
|
92369
|
-
const specMtime = mtimeMsOrNull(
|
|
92390
|
+
const specMtime = mtimeMsOrNull(path137.join(root, ".swarm", "spec.md"));
|
|
92370
92391
|
const staleSections = [];
|
|
92371
92392
|
if (!noDocs && Array.isArray(registry3?.sections)) {
|
|
92372
92393
|
for (const section of registry3.sections) {
|
|
@@ -92422,7 +92443,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
92422
92443
|
};
|
|
92423
92444
|
const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
|
|
92424
92445
|
const filePath = validateSwarmPath(directory, filename);
|
|
92425
|
-
await fs98.promises.mkdir(
|
|
92446
|
+
await fs98.promises.mkdir(path137.dirname(filePath), { recursive: true });
|
|
92426
92447
|
await fs98.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
92427
92448
|
getGlobalEventBus().publish("curator.docdrift.completed", {
|
|
92428
92449
|
phase,
|
|
@@ -92453,10 +92474,10 @@ var init_design_doc_drift = __esm(() => {
|
|
|
92453
92474
|
domain: "domain.md",
|
|
92454
92475
|
"technical-spec": "technical-spec.md",
|
|
92455
92476
|
"behavior-spec": "behavior-spec.md",
|
|
92456
|
-
"reference-impl":
|
|
92457
|
-
"idiom-notes":
|
|
92477
|
+
"reference-impl": path137.join("reference", "reference-impl.md"),
|
|
92478
|
+
"idiom-notes": path137.join("reference", "idiom-notes.md")
|
|
92458
92479
|
};
|
|
92459
|
-
TRACEABILITY_REL =
|
|
92480
|
+
TRACEABILITY_REL = path137.join("reference", "traceability.json");
|
|
92460
92481
|
_internals60 = {
|
|
92461
92482
|
mtimeMsOrNull,
|
|
92462
92483
|
resolveAnchorWithin,
|
|
@@ -92472,7 +92493,7 @@ __export(exports_project_context, {
|
|
|
92472
92493
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
92473
92494
|
});
|
|
92474
92495
|
import * as fs122 from "node:fs";
|
|
92475
|
-
import * as
|
|
92496
|
+
import * as path166 from "node:path";
|
|
92476
92497
|
function detectFileExists2(directory, pattern) {
|
|
92477
92498
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
92478
92499
|
try {
|
|
@@ -92484,7 +92505,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92484
92505
|
}
|
|
92485
92506
|
}
|
|
92486
92507
|
try {
|
|
92487
|
-
fs122.accessSync(
|
|
92508
|
+
fs122.accessSync(path166.join(directory, pattern));
|
|
92488
92509
|
return true;
|
|
92489
92510
|
} catch {
|
|
92490
92511
|
return false;
|
|
@@ -92493,7 +92514,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92493
92514
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
92494
92515
|
let pkgRaw;
|
|
92495
92516
|
try {
|
|
92496
|
-
pkgRaw = fs122.readFileSync(
|
|
92517
|
+
pkgRaw = fs122.readFileSync(path166.join(directory, "package.json"), "utf-8");
|
|
92497
92518
|
} catch {
|
|
92498
92519
|
return null;
|
|
92499
92520
|
}
|
|
@@ -92602,7 +92623,7 @@ var init_project_context = __esm(() => {
|
|
|
92602
92623
|
init_package();
|
|
92603
92624
|
init_agents2();
|
|
92604
92625
|
init_critic();
|
|
92605
|
-
import * as
|
|
92626
|
+
import * as path167 from "node:path";
|
|
92606
92627
|
|
|
92607
92628
|
// src/background/index.ts
|
|
92608
92629
|
init_event_bus();
|
|
@@ -103467,29 +103488,34 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
103467
103488
|
if (!declaredScope || declaredScope.length === 0)
|
|
103468
103489
|
return;
|
|
103469
103490
|
const argsObj = output.args;
|
|
103470
|
-
const
|
|
103471
|
-
|
|
103472
|
-
|
|
103473
|
-
|
|
103474
|
-
|
|
103475
|
-
|
|
103476
|
-
|
|
103477
|
-
|
|
103478
|
-
|
|
103479
|
-
|
|
103480
|
-
|
|
103481
|
-
|
|
103482
|
-
|
|
103483
|
-
|
|
103484
|
-
|
|
103485
|
-
|
|
103486
|
-
|
|
103487
|
-
} catch {}
|
|
103488
|
-
break;
|
|
103491
|
+
const candidatePaths = [];
|
|
103492
|
+
const singlePathKeys = ["path", "filePath", "file"];
|
|
103493
|
+
for (const key of singlePathKeys) {
|
|
103494
|
+
const val = argsObj?.[key];
|
|
103495
|
+
if (typeof val === "string" && val) {
|
|
103496
|
+
candidatePaths.push(val);
|
|
103497
|
+
}
|
|
103498
|
+
}
|
|
103499
|
+
let hasArrayKeys = false;
|
|
103500
|
+
const arrayPathKeys = ["files", "paths", "targetFiles"];
|
|
103501
|
+
for (const key of arrayPathKeys) {
|
|
103502
|
+
const val = argsObj?.[key];
|
|
103503
|
+
if (Array.isArray(val)) {
|
|
103504
|
+
hasArrayKeys = true;
|
|
103505
|
+
for (const item of val) {
|
|
103506
|
+
if (typeof item === "string" && item) {
|
|
103507
|
+
candidatePaths.push(item);
|
|
103489
103508
|
}
|
|
103490
103509
|
}
|
|
103491
103510
|
}
|
|
103492
|
-
|
|
103511
|
+
}
|
|
103512
|
+
if (candidatePaths.length === 0 && !hasArrayKeys)
|
|
103513
|
+
return;
|
|
103514
|
+
for (const rawPath of candidatePaths) {
|
|
103515
|
+
const filePath = sanitizePath(rawPath);
|
|
103516
|
+
if (!isFileInScope(filePath, declaredScope, directory)) {
|
|
103517
|
+
reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, swarmState, declaredScope);
|
|
103518
|
+
}
|
|
103493
103519
|
}
|
|
103494
103520
|
}
|
|
103495
103521
|
};
|
|
@@ -103497,7 +103523,7 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
103497
103523
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
103498
103524
|
const dir = directory ?? process.cwd();
|
|
103499
103525
|
const resolvedFile = path102.resolve(dir, filePath);
|
|
103500
|
-
return scopeEntries.some((scope) => {
|
|
103526
|
+
return scopeEntries.filter((scope) => scope.length > 0).some((scope) => {
|
|
103501
103527
|
const resolvedScope = path102.resolve(dir, scope);
|
|
103502
103528
|
if (resolvedFile === resolvedScope)
|
|
103503
103529
|
return true;
|
|
@@ -103505,6 +103531,38 @@ function isFileInScope(filePath, scopeEntries, directory) {
|
|
|
103505
103531
|
return rel.length > 0 && !rel.startsWith("..") && !path102.isAbsolute(rel);
|
|
103506
103532
|
});
|
|
103507
103533
|
}
|
|
103534
|
+
function sanitizePath(raw) {
|
|
103535
|
+
let result = "";
|
|
103536
|
+
for (let i2 = 0;i2 < raw.length; i2++) {
|
|
103537
|
+
const c = raw.charCodeAt(i2);
|
|
103538
|
+
if (c <= 31 || c === 127 || c >= 128 && c <= 159) {
|
|
103539
|
+
result += "_";
|
|
103540
|
+
continue;
|
|
103541
|
+
}
|
|
103542
|
+
result += raw[i2];
|
|
103543
|
+
}
|
|
103544
|
+
return result.replace(/\[[\d;]*m/g, "");
|
|
103545
|
+
}
|
|
103546
|
+
function reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, state, scopeEntries) {
|
|
103547
|
+
const taskLabel = taskId ?? "unknown";
|
|
103548
|
+
const violationMessage = `SCOPE VIOLATION: ${agentName} attempted to modify '${filePath}' which is not in declared scope for task ${taskLabel}. Declared scope: [${scopeEntries.slice(0, 3).join(", ")}${scopeEntries.length > 3 ? "..." : ""}]`;
|
|
103549
|
+
if (session) {
|
|
103550
|
+
session.lastScopeViolation = violationMessage;
|
|
103551
|
+
session.scopeViolationDetected = true;
|
|
103552
|
+
}
|
|
103553
|
+
if (injectAdvisory) {
|
|
103554
|
+
for (const [archSessionId, archSession] of state.agentSessions) {
|
|
103555
|
+
const archAgent = state.activeAgent.get(archSessionId) ?? archSession.agentName;
|
|
103556
|
+
if (stripKnownSwarmPrefix(archAgent) === ORCHESTRATOR_NAME) {
|
|
103557
|
+
try {
|
|
103558
|
+
injectAdvisory(archSessionId, `[SCOPE GUARD] ${violationMessage}`);
|
|
103559
|
+
} catch {}
|
|
103560
|
+
break;
|
|
103561
|
+
}
|
|
103562
|
+
}
|
|
103563
|
+
}
|
|
103564
|
+
throw new Error(violationMessage);
|
|
103565
|
+
}
|
|
103508
103566
|
|
|
103509
103567
|
// src/hooks/self-review.ts
|
|
103510
103568
|
init_constants();
|
|
@@ -105997,20 +106055,836 @@ init_snapshot_writer();
|
|
|
105997
106055
|
init_state();
|
|
105998
106056
|
init_telemetry();
|
|
105999
106057
|
|
|
106058
|
+
// src/tools/apply-patch.ts
|
|
106059
|
+
init_zod();
|
|
106060
|
+
init_path_security();
|
|
106061
|
+
init_create_tool();
|
|
106062
|
+
import {
|
|
106063
|
+
existsSync as existsSync58,
|
|
106064
|
+
mkdirSync as mkdirSync27,
|
|
106065
|
+
mkdtempSync as mkdtempSync2,
|
|
106066
|
+
readFileSync as readFileSync39,
|
|
106067
|
+
realpathSync as realpathSync13,
|
|
106068
|
+
renameSync as renameSync20,
|
|
106069
|
+
rmdirSync,
|
|
106070
|
+
unlinkSync as unlinkSync17,
|
|
106071
|
+
writeFileSync as writeFileSync20
|
|
106072
|
+
} from "node:fs";
|
|
106073
|
+
import * as path109 from "node:path";
|
|
106074
|
+
var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
106075
|
+
var MAX_PATCH_SIZE = 500000;
|
|
106076
|
+
function containsWindowsAttacks2(filePath) {
|
|
106077
|
+
if (/:[^\\/]/.test(filePath))
|
|
106078
|
+
return true;
|
|
106079
|
+
const parts2 = filePath.split(/[/\\]/);
|
|
106080
|
+
for (const part of parts2) {
|
|
106081
|
+
if (WINDOWS_RESERVED_NAMES2.test(part))
|
|
106082
|
+
return true;
|
|
106083
|
+
}
|
|
106084
|
+
return false;
|
|
106085
|
+
}
|
|
106086
|
+
function isProtectedPath2(filePath) {
|
|
106087
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
106088
|
+
const segments = normalized.split("/");
|
|
106089
|
+
return segments.some((seg) => seg === ".git" || seg === ".swarm");
|
|
106090
|
+
}
|
|
106091
|
+
function containsStrictControlChars(str) {
|
|
106092
|
+
for (let i2 = 0;i2 < str.length; i2++) {
|
|
106093
|
+
const c = str.charCodeAt(i2);
|
|
106094
|
+
if (c <= 31 && c !== 9 && c !== 10 && c !== 13)
|
|
106095
|
+
return true;
|
|
106096
|
+
}
|
|
106097
|
+
return false;
|
|
106098
|
+
}
|
|
106099
|
+
function isCanonicalProtectedPath(targetPath, workspace) {
|
|
106100
|
+
try {
|
|
106101
|
+
const canonicalTarget = realpathSync13(targetPath);
|
|
106102
|
+
const canonicalWorkspace = realpathSync13(workspace);
|
|
106103
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalTarget).replace(/\\/g, "/");
|
|
106104
|
+
const segments = relative21.split("/").filter(Boolean);
|
|
106105
|
+
return segments.some((seg) => seg === ".git" || seg === ".swarm");
|
|
106106
|
+
} catch {
|
|
106107
|
+
const parentDir = path109.dirname(targetPath);
|
|
106108
|
+
if (parentDir === targetPath)
|
|
106109
|
+
return false;
|
|
106110
|
+
try {
|
|
106111
|
+
const canonicalParent = realpathSync13(parentDir);
|
|
106112
|
+
const canonicalWorkspace = realpathSync13(workspace);
|
|
106113
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalParent).replace(/\\/g, "/");
|
|
106114
|
+
const segments = relative21.split("/").filter(Boolean);
|
|
106115
|
+
return segments.some((seg) => seg === ".git" || seg === ".swarm");
|
|
106116
|
+
} catch {
|
|
106117
|
+
return false;
|
|
106118
|
+
}
|
|
106119
|
+
}
|
|
106120
|
+
}
|
|
106121
|
+
function isCanonicalPathWithinWorkspace(targetPath, workspaceRoot) {
|
|
106122
|
+
try {
|
|
106123
|
+
const canonicalTarget = realpathSync13(targetPath);
|
|
106124
|
+
const canonicalWorkspace = realpathSync13(workspaceRoot);
|
|
106125
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalTarget);
|
|
106126
|
+
if (relative21.startsWith("..") || path109.isAbsolute(relative21))
|
|
106127
|
+
return false;
|
|
106128
|
+
const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
106129
|
+
if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
|
|
106130
|
+
return false;
|
|
106131
|
+
return true;
|
|
106132
|
+
} catch {
|
|
106133
|
+
const parentDir = path109.dirname(targetPath);
|
|
106134
|
+
if (parentDir === targetPath) {
|
|
106135
|
+
return false;
|
|
106136
|
+
}
|
|
106137
|
+
try {
|
|
106138
|
+
const canonicalParent = realpathSync13(parentDir);
|
|
106139
|
+
const canonicalWorkspace = realpathSync13(workspaceRoot);
|
|
106140
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalParent);
|
|
106141
|
+
if (relative21.startsWith("..") || path109.isAbsolute(relative21))
|
|
106142
|
+
return false;
|
|
106143
|
+
const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
106144
|
+
if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
|
|
106145
|
+
return false;
|
|
106146
|
+
return true;
|
|
106147
|
+
} catch {
|
|
106148
|
+
return false;
|
|
106149
|
+
}
|
|
106150
|
+
}
|
|
106151
|
+
}
|
|
106152
|
+
function validatePatchTargetPath(filePath, workspace) {
|
|
106153
|
+
if (!filePath || filePath.trim() === "") {
|
|
106154
|
+
return "Empty file path";
|
|
106155
|
+
}
|
|
106156
|
+
if (path109.isAbsolute(filePath) || /^[A-Za-z]:[/\\]/.test(filePath)) {
|
|
106157
|
+
return `Absolute path rejected: ${filePath}`;
|
|
106158
|
+
}
|
|
106159
|
+
if (containsPathTraversal(filePath)) {
|
|
106160
|
+
return `Path traversal detected: ${filePath}`;
|
|
106161
|
+
}
|
|
106162
|
+
if (containsStrictControlChars(filePath)) {
|
|
106163
|
+
return `Control characters detected in path: ${filePath}`;
|
|
106164
|
+
}
|
|
106165
|
+
if (containsControlChars(filePath)) {
|
|
106166
|
+
return `Control characters detected in path: ${filePath}`;
|
|
106167
|
+
}
|
|
106168
|
+
if (containsWindowsAttacks2(filePath)) {
|
|
106169
|
+
return `Windows reserved name or invalid path: ${filePath}`;
|
|
106170
|
+
}
|
|
106171
|
+
if (isProtectedPath2(filePath)) {
|
|
106172
|
+
return `Protected directory target rejected: ${filePath}`;
|
|
106173
|
+
}
|
|
106174
|
+
const resolved = path109.resolve(workspace, filePath);
|
|
106175
|
+
const relative21 = path109.relative(workspace, resolved);
|
|
106176
|
+
if (relative21.startsWith("..") || path109.isAbsolute(relative21)) {
|
|
106177
|
+
return `Path escapes workspace: ${filePath}`;
|
|
106178
|
+
}
|
|
106179
|
+
if (!isCanonicalPathWithinWorkspace(resolved, workspace)) {
|
|
106180
|
+
return `Path escapes workspace via symlink/junction: ${filePath}`;
|
|
106181
|
+
}
|
|
106182
|
+
return null;
|
|
106183
|
+
}
|
|
106184
|
+
function extractHeaderPath(header, prefix) {
|
|
106185
|
+
const trimmed = header.trim();
|
|
106186
|
+
if (!trimmed.startsWith(prefix))
|
|
106187
|
+
return null;
|
|
106188
|
+
const rest = trimmed.slice(prefix.length).trim();
|
|
106189
|
+
if (rest === "/dev/null")
|
|
106190
|
+
return "/dev/null";
|
|
106191
|
+
if (rest.startsWith("a/") || rest.startsWith("b/")) {
|
|
106192
|
+
const stripped = rest.slice(2);
|
|
106193
|
+
if (stripped.length === 0)
|
|
106194
|
+
return null;
|
|
106195
|
+
return stripped;
|
|
106196
|
+
}
|
|
106197
|
+
return rest.length > 0 ? rest : null;
|
|
106198
|
+
}
|
|
106199
|
+
function parseHunkHeader(line) {
|
|
106200
|
+
const match = line.match(/^@@\s*-(\d+)(?:,(\d+))?\s*\+(\d+)(?:,(\d+))?\s*@@/);
|
|
106201
|
+
if (!match)
|
|
106202
|
+
return null;
|
|
106203
|
+
return {
|
|
106204
|
+
oldStart: parseInt(match[1], 10),
|
|
106205
|
+
oldCount: match[2] !== undefined ? parseInt(match[2], 10) : 1,
|
|
106206
|
+
newStart: parseInt(match[3], 10),
|
|
106207
|
+
newCount: match[4] !== undefined ? parseInt(match[4], 10) : 1
|
|
106208
|
+
};
|
|
106209
|
+
}
|
|
106210
|
+
function parseUnifiedDiff(patchText) {
|
|
106211
|
+
if (patchText.length > MAX_PATCH_SIZE) {
|
|
106212
|
+
return {
|
|
106213
|
+
files: [],
|
|
106214
|
+
error: `Patch exceeds maximum size of ${MAX_PATCH_SIZE} characters`
|
|
106215
|
+
};
|
|
106216
|
+
}
|
|
106217
|
+
if (patchText.includes("\x00")) {
|
|
106218
|
+
return {
|
|
106219
|
+
files: [],
|
|
106220
|
+
error: "Binary content detected (null byte) — binary patches are not supported (FR-013)"
|
|
106221
|
+
};
|
|
106222
|
+
}
|
|
106223
|
+
const normalized = patchText.replace(/\r\n/g, `
|
|
106224
|
+
`).replace(/\r/g, `
|
|
106225
|
+
`);
|
|
106226
|
+
let lines = normalized.split(`
|
|
106227
|
+
`);
|
|
106228
|
+
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
106229
|
+
lines = lines.slice(0, -1);
|
|
106230
|
+
}
|
|
106231
|
+
for (const line of lines) {
|
|
106232
|
+
if (line === "GIT binary patch" || line.startsWith("Binary files ")) {
|
|
106233
|
+
return { files: [], error: "Binary patches are not supported (FR-013)" };
|
|
106234
|
+
}
|
|
106235
|
+
if (line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("copy from") || line.startsWith("copy to")) {
|
|
106236
|
+
return {
|
|
106237
|
+
files: [],
|
|
106238
|
+
error: "Rename/copy patches are not supported (FR-013)"
|
|
106239
|
+
};
|
|
106240
|
+
}
|
|
106241
|
+
}
|
|
106242
|
+
const fileDiffs = [];
|
|
106243
|
+
let i2 = 0;
|
|
106244
|
+
while (i2 < lines.length) {
|
|
106245
|
+
let oldHeaderPath = null;
|
|
106246
|
+
let newHeaderPath = null;
|
|
106247
|
+
if (lines[i2].startsWith("diff --git ")) {
|
|
106248
|
+
i2++;
|
|
106249
|
+
while (i2 < lines.length && (lines[i2].startsWith("index ") || lines[i2].startsWith("old mode ") || lines[i2].startsWith("new mode ") || lines[i2].startsWith("deleted file ") || lines[i2].startsWith("new file ") || lines[i2].startsWith("similarity index ") || lines[i2].startsWith("dissimilarity index "))) {
|
|
106250
|
+
i2++;
|
|
106251
|
+
}
|
|
106252
|
+
}
|
|
106253
|
+
if (i2 < lines.length && lines[i2].startsWith("--- ")) {
|
|
106254
|
+
oldHeaderPath = extractHeaderPath(lines[i2], "--- ");
|
|
106255
|
+
i2++;
|
|
106256
|
+
} else if (oldHeaderPath === null) {
|
|
106257
|
+
i2++;
|
|
106258
|
+
continue;
|
|
106259
|
+
}
|
|
106260
|
+
if (i2 < lines.length && lines[i2].startsWith("+++ ")) {
|
|
106261
|
+
newHeaderPath = extractHeaderPath(lines[i2], "+++ ");
|
|
106262
|
+
i2++;
|
|
106263
|
+
} else {
|
|
106264
|
+
continue;
|
|
106265
|
+
}
|
|
106266
|
+
if (oldHeaderPath === null || newHeaderPath === null) {
|
|
106267
|
+
continue;
|
|
106268
|
+
}
|
|
106269
|
+
const isNewFile = oldHeaderPath === "/dev/null";
|
|
106270
|
+
const isDelete = newHeaderPath === "/dev/null";
|
|
106271
|
+
const targetPath = isDelete ? oldHeaderPath : newHeaderPath;
|
|
106272
|
+
if (targetPath === "/dev/null") {
|
|
106273
|
+
continue;
|
|
106274
|
+
}
|
|
106275
|
+
const hunks = [];
|
|
106276
|
+
while (i2 < lines.length && lines[i2].startsWith("@@")) {
|
|
106277
|
+
const header = parseHunkHeader(lines[i2]);
|
|
106278
|
+
if (!header) {
|
|
106279
|
+
i2++;
|
|
106280
|
+
continue;
|
|
106281
|
+
}
|
|
106282
|
+
i2++;
|
|
106283
|
+
const hunkLines = [];
|
|
106284
|
+
while (i2 < lines.length) {
|
|
106285
|
+
const line = lines[i2];
|
|
106286
|
+
if (line.startsWith("@@") || line.startsWith("diff --git ") || line.startsWith("--- ") || line.startsWith("+++ ")) {
|
|
106287
|
+
break;
|
|
106288
|
+
}
|
|
106289
|
+
if (line.startsWith("\\")) {
|
|
106290
|
+
i2++;
|
|
106291
|
+
continue;
|
|
106292
|
+
}
|
|
106293
|
+
if (line.length === 0) {
|
|
106294
|
+
break;
|
|
106295
|
+
}
|
|
106296
|
+
const firstChar = line[0];
|
|
106297
|
+
if (firstChar !== " " && firstChar !== "+" && firstChar !== "-") {
|
|
106298
|
+
break;
|
|
106299
|
+
}
|
|
106300
|
+
if (firstChar === "+") {
|
|
106301
|
+
hunkLines.push({ type: "addition", content: line.slice(1) });
|
|
106302
|
+
} else if (firstChar === "-") {
|
|
106303
|
+
hunkLines.push({ type: "removal", content: line.slice(1) });
|
|
106304
|
+
} else {
|
|
106305
|
+
hunkLines.push({ type: "context", content: line.slice(1) });
|
|
106306
|
+
}
|
|
106307
|
+
i2++;
|
|
106308
|
+
}
|
|
106309
|
+
hunks.push({
|
|
106310
|
+
oldStart: header.oldStart,
|
|
106311
|
+
oldCount: header.oldCount,
|
|
106312
|
+
newStart: header.newStart,
|
|
106313
|
+
newCount: header.newCount,
|
|
106314
|
+
lines: hunkLines
|
|
106315
|
+
});
|
|
106316
|
+
}
|
|
106317
|
+
if (hunks.length > 0) {
|
|
106318
|
+
fileDiffs.push({
|
|
106319
|
+
oldPath: oldHeaderPath,
|
|
106320
|
+
newPath: newHeaderPath,
|
|
106321
|
+
isNewFile,
|
|
106322
|
+
isDelete,
|
|
106323
|
+
hunks
|
|
106324
|
+
});
|
|
106325
|
+
} else {
|
|
106326
|
+
fileDiffs.push({
|
|
106327
|
+
oldPath: oldHeaderPath,
|
|
106328
|
+
newPath: newHeaderPath,
|
|
106329
|
+
isNewFile,
|
|
106330
|
+
isDelete,
|
|
106331
|
+
hunks: []
|
|
106332
|
+
});
|
|
106333
|
+
}
|
|
106334
|
+
}
|
|
106335
|
+
return { files: fileDiffs, error: null };
|
|
106336
|
+
}
|
|
106337
|
+
function arraysEqual(a, b) {
|
|
106338
|
+
if (a.length !== b.length)
|
|
106339
|
+
return false;
|
|
106340
|
+
for (let idx = 0;idx < a.length; idx++) {
|
|
106341
|
+
if (a[idx] !== b[idx])
|
|
106342
|
+
return false;
|
|
106343
|
+
}
|
|
106344
|
+
return true;
|
|
106345
|
+
}
|
|
106346
|
+
function applyHunks(content, fileDiff) {
|
|
106347
|
+
const normalizedContent = content.replace(/\r\n/g, `
|
|
106348
|
+
`);
|
|
106349
|
+
const fileLines = normalizedContent.split(`
|
|
106350
|
+
`);
|
|
106351
|
+
if (fileDiff.isNewFile) {
|
|
106352
|
+
const newLines = [];
|
|
106353
|
+
for (const hunk of fileDiff.hunks) {
|
|
106354
|
+
for (const line of hunk.lines) {
|
|
106355
|
+
if (line.type === "addition" || line.type === "context") {
|
|
106356
|
+
newLines.push(line.content);
|
|
106357
|
+
}
|
|
106358
|
+
}
|
|
106359
|
+
}
|
|
106360
|
+
return { success: true, appliedLines: newLines };
|
|
106361
|
+
}
|
|
106362
|
+
if (fileDiff.isDelete) {
|
|
106363
|
+
return { success: true, appliedLines: [] };
|
|
106364
|
+
}
|
|
106365
|
+
let accumulatedDelta = 0;
|
|
106366
|
+
for (let hunkIdx = 0;hunkIdx < fileDiff.hunks.length; hunkIdx++) {
|
|
106367
|
+
const hunk = fileDiff.hunks[hunkIdx];
|
|
106368
|
+
const searchStart = Math.max(0, hunk.oldStart - 1 + accumulatedDelta);
|
|
106369
|
+
const expectedOldLines = [];
|
|
106370
|
+
const newLinesForHunk = [];
|
|
106371
|
+
for (const line of hunk.lines) {
|
|
106372
|
+
if (line.type === "context") {
|
|
106373
|
+
expectedOldLines.push(line.content);
|
|
106374
|
+
newLinesForHunk.push(line.content);
|
|
106375
|
+
} else if (line.type === "removal") {
|
|
106376
|
+
expectedOldLines.push(line.content);
|
|
106377
|
+
} else if (line.type === "addition") {
|
|
106378
|
+
newLinesForHunk.push(line.content);
|
|
106379
|
+
}
|
|
106380
|
+
}
|
|
106381
|
+
const exactOffset = searchStart;
|
|
106382
|
+
const matchFound = exactOffset <= fileLines.length - expectedOldLines.length && arraysEqual(fileLines.slice(exactOffset, exactOffset + expectedOldLines.length), expectedOldLines);
|
|
106383
|
+
if (matchFound) {
|
|
106384
|
+
fileLines.splice(exactOffset, expectedOldLines.length, ...newLinesForHunk);
|
|
106385
|
+
const delta = newLinesForHunk.length - expectedOldLines.length;
|
|
106386
|
+
accumulatedDelta += delta;
|
|
106387
|
+
}
|
|
106388
|
+
if (!matchFound) {
|
|
106389
|
+
const diagStart = Math.min(searchStart, fileLines.length);
|
|
106390
|
+
const diagEnd = Math.min(diagStart + expectedOldLines.length, fileLines.length);
|
|
106391
|
+
const actualContent = fileLines.slice(diagStart, diagEnd).join(`
|
|
106392
|
+
`);
|
|
106393
|
+
const expectedContent = expectedOldLines.join(`
|
|
106394
|
+
`);
|
|
106395
|
+
return {
|
|
106396
|
+
success: false,
|
|
106397
|
+
failedHunkIndex: hunkIdx,
|
|
106398
|
+
error: {
|
|
106399
|
+
hunkIndex: hunkIdx,
|
|
106400
|
+
type: "context-mismatch",
|
|
106401
|
+
message: `Context mismatch in hunk ${hunkIdx + 1} at line ${searchStart + 1}: expected context does not match file content`,
|
|
106402
|
+
expected: expectedContent.length > 200 ? `${expectedContent.slice(0, 200)}... (truncated)` : expectedContent,
|
|
106403
|
+
actual: actualContent.length > 200 ? `${actualContent.slice(0, 200)}... (truncated)` : actualContent,
|
|
106404
|
+
line: searchStart + 1
|
|
106405
|
+
}
|
|
106406
|
+
};
|
|
106407
|
+
}
|
|
106408
|
+
}
|
|
106409
|
+
return { success: true, appliedLines: fileLines };
|
|
106410
|
+
}
|
|
106411
|
+
function atomicWriteFileSync(targetPath, content) {
|
|
106412
|
+
const dir = path109.dirname(targetPath);
|
|
106413
|
+
mkdirSync27(dir, { recursive: true });
|
|
106414
|
+
const tempPrefix = `.apply-patch-${Date.now()}-${process.pid}`;
|
|
106415
|
+
let tempPath;
|
|
106416
|
+
try {
|
|
106417
|
+
const tempDir = realpathSync13(mkdtempSync2(path109.join(dir, tempPrefix)));
|
|
106418
|
+
tempPath = path109.join(tempDir, "content");
|
|
106419
|
+
} catch {
|
|
106420
|
+
tempPath = path109.join(dir, `${tempPrefix}.tmp`);
|
|
106421
|
+
}
|
|
106422
|
+
try {
|
|
106423
|
+
writeFileSync20(tempPath, content, "utf-8");
|
|
106424
|
+
renameSync20(tempPath, targetPath);
|
|
106425
|
+
} finally {
|
|
106426
|
+
if (existsSync58(tempPath)) {
|
|
106427
|
+
try {
|
|
106428
|
+
unlinkSync17(tempPath);
|
|
106429
|
+
} catch {}
|
|
106430
|
+
}
|
|
106431
|
+
const tempDir = path109.dirname(tempPath);
|
|
106432
|
+
if (tempDir !== dir && existsSync58(tempDir)) {
|
|
106433
|
+
try {
|
|
106434
|
+
rmdirSync(tempDir);
|
|
106435
|
+
} catch {}
|
|
106436
|
+
}
|
|
106437
|
+
}
|
|
106438
|
+
}
|
|
106439
|
+
function detectLineEnding(content) {
|
|
106440
|
+
return content.includes(`\r
|
|
106441
|
+
`) ? `\r
|
|
106442
|
+
` : `
|
|
106443
|
+
`;
|
|
106444
|
+
}
|
|
106445
|
+
function ensureFinalNewline(content, originalEndsWithNewline) {
|
|
106446
|
+
if (originalEndsWithNewline && !content.endsWith(`
|
|
106447
|
+
`)) {
|
|
106448
|
+
return `${content}
|
|
106449
|
+
`;
|
|
106450
|
+
}
|
|
106451
|
+
if (!originalEndsWithNewline && content.endsWith(`
|
|
106452
|
+
`)) {
|
|
106453
|
+
return content.slice(0, -1);
|
|
106454
|
+
}
|
|
106455
|
+
return content;
|
|
106456
|
+
}
|
|
106457
|
+
function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allowCreates, allowDeletes) {
|
|
106458
|
+
const hunksTotal = fileDiff.hunks.length;
|
|
106459
|
+
if (!isCanonicalPathWithinWorkspace(fullPath, workspace)) {
|
|
106460
|
+
return {
|
|
106461
|
+
file: targetPath,
|
|
106462
|
+
status: "error",
|
|
106463
|
+
hunks: hunksTotal,
|
|
106464
|
+
hunksApplied: 0,
|
|
106465
|
+
hunksFailed: hunksTotal,
|
|
106466
|
+
errors: [
|
|
106467
|
+
{
|
|
106468
|
+
hunkIndex: 0,
|
|
106469
|
+
type: "context-mismatch",
|
|
106470
|
+
message: `Path escapes workspace via symlink/junction: ${targetPath}`
|
|
106471
|
+
}
|
|
106472
|
+
]
|
|
106473
|
+
};
|
|
106474
|
+
}
|
|
106475
|
+
if (isCanonicalProtectedPath(fullPath, workspace)) {
|
|
106476
|
+
return {
|
|
106477
|
+
file: targetPath,
|
|
106478
|
+
status: "error",
|
|
106479
|
+
hunks: hunksTotal,
|
|
106480
|
+
hunksApplied: 0,
|
|
106481
|
+
hunksFailed: hunksTotal,
|
|
106482
|
+
errors: [
|
|
106483
|
+
{
|
|
106484
|
+
hunkIndex: 0,
|
|
106485
|
+
type: "context-mismatch",
|
|
106486
|
+
message: `Protected directory target rejected via symlink: ${targetPath}`
|
|
106487
|
+
}
|
|
106488
|
+
]
|
|
106489
|
+
};
|
|
106490
|
+
}
|
|
106491
|
+
if (fileDiff.isNewFile) {
|
|
106492
|
+
if (!allowCreates) {
|
|
106493
|
+
return {
|
|
106494
|
+
file: targetPath,
|
|
106495
|
+
status: "error",
|
|
106496
|
+
hunks: hunksTotal,
|
|
106497
|
+
hunksApplied: 0,
|
|
106498
|
+
hunksFailed: hunksTotal,
|
|
106499
|
+
errors: [
|
|
106500
|
+
{
|
|
106501
|
+
hunkIndex: 0,
|
|
106502
|
+
type: "create-not-allowed",
|
|
106503
|
+
message: `New file creation not allowed: ${targetPath} (set allowCreates to true)`
|
|
106504
|
+
}
|
|
106505
|
+
]
|
|
106506
|
+
};
|
|
106507
|
+
}
|
|
106508
|
+
const parentDir = path109.dirname(fullPath);
|
|
106509
|
+
if (!existsSync58(parentDir)) {
|
|
106510
|
+
return {
|
|
106511
|
+
file: targetPath,
|
|
106512
|
+
status: "error",
|
|
106513
|
+
hunks: hunksTotal,
|
|
106514
|
+
hunksApplied: 0,
|
|
106515
|
+
hunksFailed: hunksTotal,
|
|
106516
|
+
errors: [
|
|
106517
|
+
{
|
|
106518
|
+
hunkIndex: 0,
|
|
106519
|
+
type: "file-not-found",
|
|
106520
|
+
message: `Parent directory does not exist: ${parentDir}`
|
|
106521
|
+
}
|
|
106522
|
+
]
|
|
106523
|
+
};
|
|
106524
|
+
}
|
|
106525
|
+
if (existsSync58(fullPath)) {
|
|
106526
|
+
return {
|
|
106527
|
+
file: targetPath,
|
|
106528
|
+
status: "error",
|
|
106529
|
+
hunks: hunksTotal,
|
|
106530
|
+
hunksApplied: 0,
|
|
106531
|
+
hunksFailed: hunksTotal,
|
|
106532
|
+
errors: [
|
|
106533
|
+
{
|
|
106534
|
+
hunkIndex: 0,
|
|
106535
|
+
type: "file-not-found",
|
|
106536
|
+
message: `File already exists: ${targetPath} (cannot create — patch may be stale)`
|
|
106537
|
+
}
|
|
106538
|
+
]
|
|
106539
|
+
};
|
|
106540
|
+
}
|
|
106541
|
+
if (hunksTotal === 0) {
|
|
106542
|
+
return {
|
|
106543
|
+
file: targetPath,
|
|
106544
|
+
status: "no-changes",
|
|
106545
|
+
hunks: 0,
|
|
106546
|
+
hunksApplied: 0,
|
|
106547
|
+
hunksFailed: 0
|
|
106548
|
+
};
|
|
106549
|
+
}
|
|
106550
|
+
const hunkResult2 = applyHunks("", fileDiff);
|
|
106551
|
+
if (!hunkResult2.success || !hunkResult2.appliedLines) {
|
|
106552
|
+
return {
|
|
106553
|
+
file: targetPath,
|
|
106554
|
+
status: "error",
|
|
106555
|
+
hunks: hunksTotal,
|
|
106556
|
+
hunksApplied: 0,
|
|
106557
|
+
hunksFailed: hunksTotal,
|
|
106558
|
+
errors: hunkResult2.error ? [hunkResult2.error] : []
|
|
106559
|
+
};
|
|
106560
|
+
}
|
|
106561
|
+
if (!dryRun) {
|
|
106562
|
+
const content2 = ensureFinalNewline(hunkResult2.appliedLines.join(`
|
|
106563
|
+
`), true);
|
|
106564
|
+
atomicWriteFileSync(fullPath, content2);
|
|
106565
|
+
}
|
|
106566
|
+
return {
|
|
106567
|
+
file: targetPath,
|
|
106568
|
+
status: "created",
|
|
106569
|
+
hunks: hunksTotal,
|
|
106570
|
+
hunksApplied: hunksTotal,
|
|
106571
|
+
hunksFailed: 0
|
|
106572
|
+
};
|
|
106573
|
+
}
|
|
106574
|
+
if (fileDiff.isDelete) {
|
|
106575
|
+
if (hunksTotal === 0) {
|
|
106576
|
+
return {
|
|
106577
|
+
file: targetPath,
|
|
106578
|
+
status: "no-changes",
|
|
106579
|
+
hunks: 0,
|
|
106580
|
+
hunksApplied: 0,
|
|
106581
|
+
hunksFailed: 0
|
|
106582
|
+
};
|
|
106583
|
+
}
|
|
106584
|
+
if (!allowDeletes) {
|
|
106585
|
+
return {
|
|
106586
|
+
file: targetPath,
|
|
106587
|
+
status: "error",
|
|
106588
|
+
hunks: hunksTotal,
|
|
106589
|
+
hunksApplied: 0,
|
|
106590
|
+
hunksFailed: hunksTotal,
|
|
106591
|
+
errors: [
|
|
106592
|
+
{
|
|
106593
|
+
hunkIndex: 0,
|
|
106594
|
+
type: "delete-not-allowed",
|
|
106595
|
+
message: `File deletion not allowed: ${targetPath} (set allowDeletes to true)`
|
|
106596
|
+
}
|
|
106597
|
+
]
|
|
106598
|
+
};
|
|
106599
|
+
}
|
|
106600
|
+
if (!existsSync58(fullPath)) {
|
|
106601
|
+
return {
|
|
106602
|
+
file: targetPath,
|
|
106603
|
+
status: "error",
|
|
106604
|
+
hunks: hunksTotal,
|
|
106605
|
+
hunksApplied: 0,
|
|
106606
|
+
hunksFailed: hunksTotal,
|
|
106607
|
+
errors: [
|
|
106608
|
+
{
|
|
106609
|
+
hunkIndex: 0,
|
|
106610
|
+
type: "file-not-found",
|
|
106611
|
+
message: `File not found for deletion: ${targetPath}`
|
|
106612
|
+
}
|
|
106613
|
+
]
|
|
106614
|
+
};
|
|
106615
|
+
}
|
|
106616
|
+
if (!dryRun) {
|
|
106617
|
+
try {
|
|
106618
|
+
unlinkSync17(fullPath);
|
|
106619
|
+
} catch (err2) {
|
|
106620
|
+
return {
|
|
106621
|
+
file: targetPath,
|
|
106622
|
+
status: "error",
|
|
106623
|
+
hunks: hunksTotal,
|
|
106624
|
+
hunksApplied: 0,
|
|
106625
|
+
hunksFailed: hunksTotal,
|
|
106626
|
+
errors: [
|
|
106627
|
+
{
|
|
106628
|
+
hunkIndex: 0,
|
|
106629
|
+
type: "file-not-found",
|
|
106630
|
+
message: `Failed to delete file: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
106631
|
+
}
|
|
106632
|
+
]
|
|
106633
|
+
};
|
|
106634
|
+
}
|
|
106635
|
+
}
|
|
106636
|
+
return {
|
|
106637
|
+
file: targetPath,
|
|
106638
|
+
status: "applied",
|
|
106639
|
+
hunks: hunksTotal,
|
|
106640
|
+
hunksApplied: hunksTotal,
|
|
106641
|
+
hunksFailed: 0
|
|
106642
|
+
};
|
|
106643
|
+
}
|
|
106644
|
+
if (!existsSync58(fullPath)) {
|
|
106645
|
+
return {
|
|
106646
|
+
file: targetPath,
|
|
106647
|
+
status: "error",
|
|
106648
|
+
hunks: hunksTotal,
|
|
106649
|
+
hunksApplied: 0,
|
|
106650
|
+
hunksFailed: hunksTotal,
|
|
106651
|
+
errors: [
|
|
106652
|
+
{
|
|
106653
|
+
hunkIndex: 0,
|
|
106654
|
+
type: "file-not-found",
|
|
106655
|
+
message: `File not found: ${targetPath}`
|
|
106656
|
+
}
|
|
106657
|
+
]
|
|
106658
|
+
};
|
|
106659
|
+
}
|
|
106660
|
+
let content;
|
|
106661
|
+
try {
|
|
106662
|
+
content = readFileSync39(fullPath, "utf-8");
|
|
106663
|
+
} catch (err2) {
|
|
106664
|
+
return {
|
|
106665
|
+
file: targetPath,
|
|
106666
|
+
status: "error",
|
|
106667
|
+
hunks: hunksTotal,
|
|
106668
|
+
hunksApplied: 0,
|
|
106669
|
+
hunksFailed: hunksTotal,
|
|
106670
|
+
errors: [
|
|
106671
|
+
{
|
|
106672
|
+
hunkIndex: 0,
|
|
106673
|
+
type: "file-not-found",
|
|
106674
|
+
message: `Could not read file: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
106675
|
+
}
|
|
106676
|
+
]
|
|
106677
|
+
};
|
|
106678
|
+
}
|
|
106679
|
+
if (hunksTotal === 0) {
|
|
106680
|
+
return {
|
|
106681
|
+
file: targetPath,
|
|
106682
|
+
status: "no-changes",
|
|
106683
|
+
hunks: 0,
|
|
106684
|
+
hunksApplied: 0,
|
|
106685
|
+
hunksFailed: 0
|
|
106686
|
+
};
|
|
106687
|
+
}
|
|
106688
|
+
const originalEndsWithNewline = content.endsWith(`
|
|
106689
|
+
`);
|
|
106690
|
+
const originalLineEnding = detectLineEnding(content);
|
|
106691
|
+
const hunkResult = applyHunks(content, fileDiff);
|
|
106692
|
+
if (!hunkResult.success) {
|
|
106693
|
+
return {
|
|
106694
|
+
file: targetPath,
|
|
106695
|
+
status: "error",
|
|
106696
|
+
hunks: hunksTotal,
|
|
106697
|
+
hunksApplied: 0,
|
|
106698
|
+
hunksFailed: hunksTotal,
|
|
106699
|
+
errors: hunkResult.error ? [hunkResult.error] : []
|
|
106700
|
+
};
|
|
106701
|
+
}
|
|
106702
|
+
const resultContent = hunkResult.appliedLines.join(`
|
|
106703
|
+
`);
|
|
106704
|
+
if (resultContent === "" && !dryRun && !allowDeletes && content.length > 0) {
|
|
106705
|
+
return {
|
|
106706
|
+
file: targetPath,
|
|
106707
|
+
status: "error",
|
|
106708
|
+
hunks: hunksTotal,
|
|
106709
|
+
hunksApplied: hunksTotal,
|
|
106710
|
+
hunksFailed: 0,
|
|
106711
|
+
errors: [
|
|
106712
|
+
{
|
|
106713
|
+
hunkIndex: 0,
|
|
106714
|
+
type: "delete-not-allowed",
|
|
106715
|
+
message: `Patch would delete all content from ${targetPath}. Set allowDeletes to true to permit file deletion.`
|
|
106716
|
+
}
|
|
106717
|
+
]
|
|
106718
|
+
};
|
|
106719
|
+
}
|
|
106720
|
+
let finalContent;
|
|
106721
|
+
if (resultContent === "") {
|
|
106722
|
+
finalContent = "";
|
|
106723
|
+
} else {
|
|
106724
|
+
const withLineEnding = originalLineEnding === `\r
|
|
106725
|
+
` ? resultContent.replace(/\n/g, `\r
|
|
106726
|
+
`) : resultContent;
|
|
106727
|
+
finalContent = ensureFinalNewline(withLineEnding, originalEndsWithNewline);
|
|
106728
|
+
}
|
|
106729
|
+
if (finalContent === content) {
|
|
106730
|
+
return {
|
|
106731
|
+
file: targetPath,
|
|
106732
|
+
status: "no-changes",
|
|
106733
|
+
hunks: hunksTotal,
|
|
106734
|
+
hunksApplied: hunksTotal,
|
|
106735
|
+
hunksFailed: 0
|
|
106736
|
+
};
|
|
106737
|
+
}
|
|
106738
|
+
if (!dryRun) {
|
|
106739
|
+
atomicWriteFileSync(fullPath, finalContent);
|
|
106740
|
+
}
|
|
106741
|
+
return {
|
|
106742
|
+
file: targetPath,
|
|
106743
|
+
status: "applied",
|
|
106744
|
+
hunks: hunksTotal,
|
|
106745
|
+
hunksApplied: hunksTotal,
|
|
106746
|
+
hunksFailed: 0
|
|
106747
|
+
};
|
|
106748
|
+
}
|
|
106749
|
+
function buildErrorResult(message) {
|
|
106750
|
+
return {
|
|
106751
|
+
success: false,
|
|
106752
|
+
files: [
|
|
106753
|
+
{
|
|
106754
|
+
file: "",
|
|
106755
|
+
status: "error",
|
|
106756
|
+
hunks: 0,
|
|
106757
|
+
hunksApplied: 0,
|
|
106758
|
+
hunksFailed: 0,
|
|
106759
|
+
errors: [
|
|
106760
|
+
{
|
|
106761
|
+
hunkIndex: 0,
|
|
106762
|
+
type: "context-mismatch",
|
|
106763
|
+
message
|
|
106764
|
+
}
|
|
106765
|
+
]
|
|
106766
|
+
}
|
|
106767
|
+
],
|
|
106768
|
+
summary: {
|
|
106769
|
+
totalFiles: 0,
|
|
106770
|
+
applied: 0,
|
|
106771
|
+
failed: 1,
|
|
106772
|
+
totalHunks: 0
|
|
106773
|
+
}
|
|
106774
|
+
};
|
|
106775
|
+
}
|
|
106776
|
+
var applyPatch = createSwarmTool({
|
|
106777
|
+
description: "Apply a unified diff patch to workspace files. Validates paths, matches context exactly, and writes atomically. Coder-scoped write tool.",
|
|
106778
|
+
args: {
|
|
106779
|
+
patch: exports_external.string().min(1).describe("Unified diff text to parse and apply"),
|
|
106780
|
+
files: exports_external.array(exports_external.string()).min(1).describe("Array of target file paths the patch is expected to touch. Every parsed target must appear in this list."),
|
|
106781
|
+
dryRun: exports_external.boolean().optional().default(false).describe("Validate without writing files (default: false)"),
|
|
106782
|
+
allowCreates: exports_external.boolean().optional().default(false).describe("Allow creating new files from patches with --- /dev/null (default: false)"),
|
|
106783
|
+
allowDeletes: exports_external.boolean().optional().default(false).describe("Allow deleting files from patches with +++ /dev/null (default: false)")
|
|
106784
|
+
},
|
|
106785
|
+
execute: async (args2, directory) => {
|
|
106786
|
+
if (!args2 || typeof args2 !== "object") {
|
|
106787
|
+
return JSON.stringify(buildErrorResult("Could not parse apply_patch arguments"), null, 2);
|
|
106788
|
+
}
|
|
106789
|
+
const obj = args2;
|
|
106790
|
+
const patchText = obj.patch ?? "";
|
|
106791
|
+
const files = obj.files ?? [];
|
|
106792
|
+
const dryRun = obj.dryRun ?? false;
|
|
106793
|
+
const allowCreates = obj.allowCreates ?? false;
|
|
106794
|
+
const allowDeletes = obj.allowDeletes ?? false;
|
|
106795
|
+
if (!existsSync58(directory)) {
|
|
106796
|
+
return JSON.stringify(buildErrorResult("Workspace directory does not exist"), null, 2);
|
|
106797
|
+
}
|
|
106798
|
+
if (files.length === 0) {
|
|
106799
|
+
return JSON.stringify(buildErrorResult("files array cannot be empty"), null, 2);
|
|
106800
|
+
}
|
|
106801
|
+
if (!patchText || patchText.trim() === "") {
|
|
106802
|
+
return JSON.stringify(buildErrorResult("patch text cannot be empty"), null, 2);
|
|
106803
|
+
}
|
|
106804
|
+
for (const filePath of files) {
|
|
106805
|
+
const validationError = validatePatchTargetPath(filePath, directory);
|
|
106806
|
+
if (validationError) {
|
|
106807
|
+
return JSON.stringify(buildErrorResult(validationError), null, 2);
|
|
106808
|
+
}
|
|
106809
|
+
}
|
|
106810
|
+
const { files: parsedFiles, error: parseError } = parseUnifiedDiff(patchText);
|
|
106811
|
+
if (parseError) {
|
|
106812
|
+
return JSON.stringify(buildErrorResult(parseError), null, 2);
|
|
106813
|
+
}
|
|
106814
|
+
if (parsedFiles.length === 0) {
|
|
106815
|
+
return JSON.stringify({
|
|
106816
|
+
success: true,
|
|
106817
|
+
dryRun,
|
|
106818
|
+
files: [],
|
|
106819
|
+
summary: { totalFiles: 0, applied: 0, failed: 0, totalHunks: 0 }
|
|
106820
|
+
}, null, 2);
|
|
106821
|
+
}
|
|
106822
|
+
const declaredFileSet = new Set(files);
|
|
106823
|
+
const undeclaredTargets = [];
|
|
106824
|
+
for (const fileDiff of parsedFiles) {
|
|
106825
|
+
const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
|
|
106826
|
+
if (targetPath && targetPath !== "/dev/null" && !declaredFileSet.has(targetPath)) {
|
|
106827
|
+
undeclaredTargets.push(targetPath);
|
|
106828
|
+
}
|
|
106829
|
+
}
|
|
106830
|
+
if (undeclaredTargets.length > 0) {
|
|
106831
|
+
return JSON.stringify(buildErrorResult(`Patch targets files not in the declared files array: ${undeclaredTargets.join(", ")}`), null, 2);
|
|
106832
|
+
}
|
|
106833
|
+
const parsedTargetSet = new Set(parsedFiles.map((fd) => fd.isDelete ? fd.oldPath : fd.newPath).filter(Boolean));
|
|
106834
|
+
const extraFiles = files.filter((f) => !parsedTargetSet.has(f));
|
|
106835
|
+
const fileResults = [];
|
|
106836
|
+
let totalApplied = 0;
|
|
106837
|
+
let totalFailed = 0;
|
|
106838
|
+
let totalHunks = 0;
|
|
106839
|
+
for (const fileDiff of parsedFiles) {
|
|
106840
|
+
const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
|
|
106841
|
+
const fullPath = path109.resolve(directory, targetPath);
|
|
106842
|
+
totalHunks += fileDiff.hunks.length;
|
|
106843
|
+
const result = processFileDiff(fileDiff, targetPath, fullPath, directory, dryRun, allowCreates, allowDeletes);
|
|
106844
|
+
fileResults.push(result);
|
|
106845
|
+
if (result.status === "applied" || result.status === "created") {
|
|
106846
|
+
totalApplied++;
|
|
106847
|
+
} else if (result.status === "error") {
|
|
106848
|
+
totalFailed++;
|
|
106849
|
+
}
|
|
106850
|
+
}
|
|
106851
|
+
const output = {
|
|
106852
|
+
success: totalFailed === 0,
|
|
106853
|
+
dryRun,
|
|
106854
|
+
files: fileResults,
|
|
106855
|
+
summary: {
|
|
106856
|
+
totalFiles: fileResults.length,
|
|
106857
|
+
applied: totalApplied,
|
|
106858
|
+
failed: totalFailed,
|
|
106859
|
+
totalHunks
|
|
106860
|
+
}
|
|
106861
|
+
};
|
|
106862
|
+
if (extraFiles.length > 0) {
|
|
106863
|
+
return JSON.stringify({
|
|
106864
|
+
...output,
|
|
106865
|
+
warnings: [
|
|
106866
|
+
`files[] contains entries not targeted by the patch: ${extraFiles.join(", ")}`
|
|
106867
|
+
]
|
|
106868
|
+
}, null, 2);
|
|
106869
|
+
}
|
|
106870
|
+
return JSON.stringify(output, null, 2);
|
|
106871
|
+
}
|
|
106872
|
+
});
|
|
106873
|
+
|
|
106000
106874
|
// src/tools/batch-symbols.ts
|
|
106001
106875
|
init_dist();
|
|
106002
106876
|
init_create_tool();
|
|
106003
106877
|
import * as fs72 from "node:fs";
|
|
106004
|
-
import * as
|
|
106878
|
+
import * as path110 from "node:path";
|
|
106005
106879
|
init_path_security();
|
|
106006
|
-
var
|
|
106007
|
-
function
|
|
106880
|
+
var WINDOWS_RESERVED_NAMES3 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
106881
|
+
function containsWindowsAttacks3(str) {
|
|
106008
106882
|
if (/:[^\\/]/.test(str)) {
|
|
106009
106883
|
return true;
|
|
106010
106884
|
}
|
|
106011
106885
|
const parts2 = str.split(/[/\\]/);
|
|
106012
106886
|
for (const part of parts2) {
|
|
106013
|
-
if (
|
|
106887
|
+
if (WINDOWS_RESERVED_NAMES3.test(part)) {
|
|
106014
106888
|
return true;
|
|
106015
106889
|
}
|
|
106016
106890
|
}
|
|
@@ -106018,14 +106892,14 @@ function containsWindowsAttacks2(str) {
|
|
|
106018
106892
|
}
|
|
106019
106893
|
function isPathInWorkspace2(filePath, workspace) {
|
|
106020
106894
|
try {
|
|
106021
|
-
const resolvedPath =
|
|
106895
|
+
const resolvedPath = path110.resolve(workspace, filePath);
|
|
106022
106896
|
if (!fs72.existsSync(resolvedPath)) {
|
|
106023
106897
|
return true;
|
|
106024
106898
|
}
|
|
106025
106899
|
const realWorkspace = fs72.realpathSync(workspace);
|
|
106026
106900
|
const realResolvedPath = fs72.realpathSync(resolvedPath);
|
|
106027
|
-
const relativePath =
|
|
106028
|
-
if (relativePath.startsWith("..") ||
|
|
106901
|
+
const relativePath = path110.relative(realWorkspace, realResolvedPath);
|
|
106902
|
+
if (relativePath.startsWith("..") || path110.isAbsolute(relativePath)) {
|
|
106029
106903
|
return false;
|
|
106030
106904
|
}
|
|
106031
106905
|
return true;
|
|
@@ -106034,7 +106908,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
106034
106908
|
}
|
|
106035
106909
|
}
|
|
106036
106910
|
function processFile2(file3, cwd, exportedOnly) {
|
|
106037
|
-
const ext =
|
|
106911
|
+
const ext = path110.extname(file3);
|
|
106038
106912
|
if (containsControlChars(file3)) {
|
|
106039
106913
|
return {
|
|
106040
106914
|
file: file3,
|
|
@@ -106051,7 +106925,7 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
106051
106925
|
errorType: "path-traversal"
|
|
106052
106926
|
};
|
|
106053
106927
|
}
|
|
106054
|
-
if (
|
|
106928
|
+
if (containsWindowsAttacks3(file3)) {
|
|
106055
106929
|
return {
|
|
106056
106930
|
file: file3,
|
|
106057
106931
|
success: false,
|
|
@@ -106067,7 +106941,7 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
106067
106941
|
errorType: "path-outside-workspace"
|
|
106068
106942
|
};
|
|
106069
106943
|
}
|
|
106070
|
-
const fullPath =
|
|
106944
|
+
const fullPath = path110.join(cwd, file3);
|
|
106071
106945
|
if (!fs72.existsSync(fullPath)) {
|
|
106072
106946
|
return {
|
|
106073
106947
|
file: file3,
|
|
@@ -106361,15 +107235,15 @@ init_task_id();
|
|
|
106361
107235
|
init_create_tool();
|
|
106362
107236
|
init_resolve_working_directory();
|
|
106363
107237
|
import * as fs73 from "node:fs";
|
|
106364
|
-
import * as
|
|
107238
|
+
import * as path111 from "node:path";
|
|
106365
107239
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
106366
107240
|
function isValidTaskId3(taskId) {
|
|
106367
107241
|
return isStrictTaskId(taskId);
|
|
106368
107242
|
}
|
|
106369
107243
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
106370
|
-
const normalizedWorkspace =
|
|
106371
|
-
const swarmPath =
|
|
106372
|
-
const normalizedPath =
|
|
107244
|
+
const normalizedWorkspace = path111.resolve(workspaceRoot);
|
|
107245
|
+
const swarmPath = path111.join(normalizedWorkspace, ".swarm", "evidence");
|
|
107246
|
+
const normalizedPath = path111.resolve(filePath);
|
|
106373
107247
|
return normalizedPath.startsWith(swarmPath);
|
|
106374
107248
|
}
|
|
106375
107249
|
function readEvidenceFile(evidencePath) {
|
|
@@ -106450,7 +107324,7 @@ var check_gate_status = createSwarmTool({
|
|
|
106450
107324
|
};
|
|
106451
107325
|
return JSON.stringify(errorResult, null, 2);
|
|
106452
107326
|
}
|
|
106453
|
-
const evidencePath =
|
|
107327
|
+
const evidencePath = path111.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
106454
107328
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
106455
107329
|
const errorResult = {
|
|
106456
107330
|
taskId: taskIdInput,
|
|
@@ -106547,7 +107421,7 @@ init_state();
|
|
|
106547
107421
|
init_create_tool();
|
|
106548
107422
|
init_resolve_working_directory();
|
|
106549
107423
|
import * as fs74 from "node:fs";
|
|
106550
|
-
import * as
|
|
107424
|
+
import * as path112 from "node:path";
|
|
106551
107425
|
function extractMatches(regex, text) {
|
|
106552
107426
|
return Array.from(text.matchAll(regex));
|
|
106553
107427
|
}
|
|
@@ -106699,10 +107573,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
106699
107573
|
let hasFileReadFailure = false;
|
|
106700
107574
|
for (const filePath of fileTargets) {
|
|
106701
107575
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
106702
|
-
const resolvedPath =
|
|
106703
|
-
const projectRoot =
|
|
106704
|
-
const
|
|
106705
|
-
const withinProject =
|
|
107576
|
+
const resolvedPath = path112.resolve(directory, normalizedPath);
|
|
107577
|
+
const projectRoot = path112.resolve(directory);
|
|
107578
|
+
const relative23 = path112.relative(projectRoot, resolvedPath);
|
|
107579
|
+
const withinProject = relative23 === "" || !relative23.startsWith("..") && !path112.isAbsolute(relative23);
|
|
106706
107580
|
if (!withinProject) {
|
|
106707
107581
|
blockedTasks.push({
|
|
106708
107582
|
task_id: task.id,
|
|
@@ -106757,8 +107631,8 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
106757
107631
|
blockedTasks
|
|
106758
107632
|
};
|
|
106759
107633
|
try {
|
|
106760
|
-
const evidenceDir =
|
|
106761
|
-
const evidencePath =
|
|
107634
|
+
const evidenceDir = path112.join(directory, ".swarm", "evidence", `${phase}`);
|
|
107635
|
+
const evidencePath = path112.join(evidenceDir, "completion-verify.json");
|
|
106762
107636
|
fs74.mkdirSync(evidenceDir, { recursive: true });
|
|
106763
107637
|
const evidenceBundle = {
|
|
106764
107638
|
schema_version: "1.0.0",
|
|
@@ -106836,11 +107710,11 @@ var completion_verify = createSwarmTool({
|
|
|
106836
107710
|
// src/tools/complexity-hotspots.ts
|
|
106837
107711
|
init_zod();
|
|
106838
107712
|
import * as fs76 from "node:fs";
|
|
106839
|
-
import * as
|
|
107713
|
+
import * as path114 from "node:path";
|
|
106840
107714
|
|
|
106841
107715
|
// src/quality/metrics.ts
|
|
106842
107716
|
import * as fs75 from "node:fs";
|
|
106843
|
-
import * as
|
|
107717
|
+
import * as path113 from "node:path";
|
|
106844
107718
|
var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
|
|
106845
107719
|
var MIN_DUPLICATION_LINES = 10;
|
|
106846
107720
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -106892,7 +107766,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
106892
107766
|
let totalComplexity = 0;
|
|
106893
107767
|
const analyzedFiles = [];
|
|
106894
107768
|
for (const file3 of files) {
|
|
106895
|
-
const fullPath =
|
|
107769
|
+
const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
|
|
106896
107770
|
if (!fs75.existsSync(fullPath)) {
|
|
106897
107771
|
continue;
|
|
106898
107772
|
}
|
|
@@ -107015,7 +107889,7 @@ function countGoExports(content) {
|
|
|
107015
107889
|
function getExportCountForFile(filePath) {
|
|
107016
107890
|
try {
|
|
107017
107891
|
const content = fs75.readFileSync(filePath, "utf-8");
|
|
107018
|
-
const ext =
|
|
107892
|
+
const ext = path113.extname(filePath).toLowerCase();
|
|
107019
107893
|
switch (ext) {
|
|
107020
107894
|
case ".ts":
|
|
107021
107895
|
case ".tsx":
|
|
@@ -107041,7 +107915,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
107041
107915
|
let totalExports = 0;
|
|
107042
107916
|
const analyzedFiles = [];
|
|
107043
107917
|
for (const file3 of files) {
|
|
107044
|
-
const fullPath =
|
|
107918
|
+
const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
|
|
107045
107919
|
if (!fs75.existsSync(fullPath)) {
|
|
107046
107920
|
continue;
|
|
107047
107921
|
}
|
|
@@ -107075,7 +107949,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
107075
107949
|
let duplicateLines = 0;
|
|
107076
107950
|
const analyzedFiles = [];
|
|
107077
107951
|
for (const file3 of files) {
|
|
107078
|
-
const fullPath =
|
|
107952
|
+
const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
|
|
107079
107953
|
if (!fs75.existsSync(fullPath)) {
|
|
107080
107954
|
continue;
|
|
107081
107955
|
}
|
|
@@ -107108,8 +107982,8 @@ function countCodeLines(content) {
|
|
|
107108
107982
|
return lines.length;
|
|
107109
107983
|
}
|
|
107110
107984
|
function isTestFile(filePath) {
|
|
107111
|
-
const basename16 =
|
|
107112
|
-
const _ext =
|
|
107985
|
+
const basename16 = path113.basename(filePath);
|
|
107986
|
+
const _ext = path113.extname(filePath).toLowerCase();
|
|
107113
107987
|
const testPatterns = [
|
|
107114
107988
|
".test.",
|
|
107115
107989
|
".spec.",
|
|
@@ -107190,8 +108064,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
107190
108064
|
}
|
|
107191
108065
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
107192
108066
|
}
|
|
107193
|
-
function matchesGlobSegment(
|
|
107194
|
-
const normalizedPath =
|
|
108067
|
+
function matchesGlobSegment(path114, glob) {
|
|
108068
|
+
const normalizedPath = path114.replace(/\\/g, "/");
|
|
107195
108069
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
107196
108070
|
if (normalizedPath.includes("//")) {
|
|
107197
108071
|
return false;
|
|
@@ -107222,8 +108096,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
107222
108096
|
function hasGlobstar(glob) {
|
|
107223
108097
|
return glob.includes("**");
|
|
107224
108098
|
}
|
|
107225
|
-
function globMatches(
|
|
107226
|
-
const normalizedPath =
|
|
108099
|
+
function globMatches(path114, glob) {
|
|
108100
|
+
const normalizedPath = path114.replace(/\\/g, "/");
|
|
107227
108101
|
if (!glob || glob === "") {
|
|
107228
108102
|
if (normalizedPath.includes("//")) {
|
|
107229
108103
|
return false;
|
|
@@ -107259,7 +108133,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
107259
108133
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
107260
108134
|
let testLines = 0;
|
|
107261
108135
|
let codeLines = 0;
|
|
107262
|
-
const srcDir =
|
|
108136
|
+
const srcDir = path113.join(workingDir, "src");
|
|
107263
108137
|
if (fs75.existsSync(srcDir)) {
|
|
107264
108138
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
107265
108139
|
codeLines += lines;
|
|
@@ -107267,14 +108141,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
107267
108141
|
}
|
|
107268
108142
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
107269
108143
|
for (const dir of possibleSrcDirs) {
|
|
107270
|
-
const dirPath =
|
|
108144
|
+
const dirPath = path113.join(workingDir, dir);
|
|
107271
108145
|
if (fs75.existsSync(dirPath)) {
|
|
107272
108146
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
107273
108147
|
codeLines += lines;
|
|
107274
108148
|
});
|
|
107275
108149
|
}
|
|
107276
108150
|
}
|
|
107277
|
-
const testsDir =
|
|
108151
|
+
const testsDir = path113.join(workingDir, "tests");
|
|
107278
108152
|
if (fs75.existsSync(testsDir)) {
|
|
107279
108153
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
107280
108154
|
testLines += lines;
|
|
@@ -107282,7 +108156,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
107282
108156
|
}
|
|
107283
108157
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
107284
108158
|
for (const dir of possibleTestDirs) {
|
|
107285
|
-
const dirPath =
|
|
108159
|
+
const dirPath = path113.join(workingDir, dir);
|
|
107286
108160
|
if (fs75.existsSync(dirPath) && dirPath !== testsDir) {
|
|
107287
108161
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
107288
108162
|
testLines += lines;
|
|
@@ -107297,7 +108171,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
107297
108171
|
try {
|
|
107298
108172
|
const entries = fs75.readdirSync(dirPath, { withFileTypes: true });
|
|
107299
108173
|
for (const entry of entries) {
|
|
107300
|
-
const fullPath =
|
|
108174
|
+
const fullPath = path113.join(dirPath, entry.name);
|
|
107301
108175
|
if (entry.isDirectory()) {
|
|
107302
108176
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
107303
108177
|
continue;
|
|
@@ -107305,7 +108179,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
107305
108179
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
107306
108180
|
} else if (entry.isFile()) {
|
|
107307
108181
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
107308
|
-
const ext =
|
|
108182
|
+
const ext = path113.extname(entry.name).toLowerCase();
|
|
107309
108183
|
const validExts = [
|
|
107310
108184
|
".ts",
|
|
107311
108185
|
".tsx",
|
|
@@ -107556,7 +108430,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
107556
108430
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
107557
108431
|
const filteredChurn = new Map;
|
|
107558
108432
|
for (const [file3, count] of churnMap) {
|
|
107559
|
-
const ext =
|
|
108433
|
+
const ext = path114.extname(file3).toLowerCase();
|
|
107560
108434
|
if (extSet.has(ext)) {
|
|
107561
108435
|
filteredChurn.set(file3, count);
|
|
107562
108436
|
}
|
|
@@ -107567,7 +108441,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
107567
108441
|
for (const [file3, churnCount] of filteredChurn) {
|
|
107568
108442
|
let fullPath = file3;
|
|
107569
108443
|
if (!fs76.existsSync(fullPath)) {
|
|
107570
|
-
fullPath =
|
|
108444
|
+
fullPath = path114.join(cwd, file3);
|
|
107571
108445
|
}
|
|
107572
108446
|
const complexity = getComplexityForFile2(fullPath);
|
|
107573
108447
|
if (complexity !== null) {
|
|
@@ -107736,8 +108610,8 @@ ${body2}`);
|
|
|
107736
108610
|
|
|
107737
108611
|
// src/council/council-evidence-writer.ts
|
|
107738
108612
|
init_task_file();
|
|
107739
|
-
import { appendFileSync as appendFileSync12, existsSync as
|
|
107740
|
-
import { join as
|
|
108613
|
+
import { appendFileSync as appendFileSync12, existsSync as existsSync63, mkdirSync as mkdirSync29, readFileSync as readFileSync45 } from "node:fs";
|
|
108614
|
+
import { join as join95 } from "node:path";
|
|
107741
108615
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
107742
108616
|
var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
|
|
107743
108617
|
var COUNCIL_GATE_NAME = "council";
|
|
@@ -107774,14 +108648,14 @@ async function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
107774
108648
|
if (!VALID_TASK_ID.test(synthesis.taskId)) {
|
|
107775
108649
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
107776
108650
|
}
|
|
107777
|
-
const dir =
|
|
107778
|
-
|
|
108651
|
+
const dir = join95(workingDir, EVIDENCE_DIR2);
|
|
108652
|
+
mkdirSync29(dir, { recursive: true });
|
|
107779
108653
|
const filePath = taskEvidencePath(workingDir, synthesis.taskId);
|
|
107780
108654
|
await _internals53.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
|
|
107781
108655
|
const existingRoot = Object.create(null);
|
|
107782
|
-
if (
|
|
108656
|
+
if (existsSync63(filePath)) {
|
|
107783
108657
|
try {
|
|
107784
|
-
const parsed = JSON.parse(
|
|
108658
|
+
const parsed = JSON.parse(readFileSync45(filePath, "utf-8"));
|
|
107785
108659
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
107786
108660
|
safeAssignOwnProps(existingRoot, parsed);
|
|
107787
108661
|
}
|
|
@@ -107812,15 +108686,15 @@ async function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
107812
108686
|
await atomicWriteFile(filePath, JSON.stringify(updated, null, 2));
|
|
107813
108687
|
});
|
|
107814
108688
|
try {
|
|
107815
|
-
const councilDir =
|
|
107816
|
-
|
|
108689
|
+
const councilDir = join95(workingDir, ".swarm", "council");
|
|
108690
|
+
mkdirSync29(councilDir, { recursive: true });
|
|
107817
108691
|
const auditLine = JSON.stringify({
|
|
107818
108692
|
round: synthesis.roundNumber,
|
|
107819
108693
|
verdict: synthesis.overallVerdict,
|
|
107820
108694
|
timestamp: synthesis.timestamp,
|
|
107821
108695
|
vetoedBy: synthesis.vetoedBy
|
|
107822
108696
|
});
|
|
107823
|
-
appendFileSync12(
|
|
108697
|
+
appendFileSync12(join95(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
|
|
107824
108698
|
`);
|
|
107825
108699
|
} catch (auditError) {
|
|
107826
108700
|
console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
|
|
@@ -108142,25 +109016,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
|
|
|
108142
109016
|
}
|
|
108143
109017
|
|
|
108144
109018
|
// src/council/criteria-store.ts
|
|
108145
|
-
import { existsSync as
|
|
108146
|
-
import { join as
|
|
109019
|
+
import { existsSync as existsSync64, mkdirSync as mkdirSync30, readFileSync as readFileSync46, writeFileSync as writeFileSync22 } from "node:fs";
|
|
109020
|
+
import { join as join96 } from "node:path";
|
|
108147
109021
|
var COUNCIL_DIR = ".swarm/council";
|
|
108148
109022
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
108149
|
-
const dir =
|
|
108150
|
-
|
|
109023
|
+
const dir = join96(workingDir, COUNCIL_DIR);
|
|
109024
|
+
mkdirSync30(dir, { recursive: true });
|
|
108151
109025
|
const payload = {
|
|
108152
109026
|
taskId,
|
|
108153
109027
|
criteria,
|
|
108154
109028
|
declaredAt: new Date().toISOString()
|
|
108155
109029
|
};
|
|
108156
|
-
|
|
109030
|
+
writeFileSync22(join96(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
|
|
108157
109031
|
}
|
|
108158
109032
|
function readCriteria(workingDir, taskId) {
|
|
108159
|
-
const filePath =
|
|
108160
|
-
if (!
|
|
109033
|
+
const filePath = join96(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
|
|
109034
|
+
if (!existsSync64(filePath))
|
|
108161
109035
|
return null;
|
|
108162
109036
|
try {
|
|
108163
|
-
const parsed = JSON.parse(
|
|
109037
|
+
const parsed = JSON.parse(readFileSync46(filePath, "utf-8"));
|
|
108164
109038
|
if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
|
|
108165
109039
|
return parsed;
|
|
108166
109040
|
}
|
|
@@ -108310,7 +109184,7 @@ var submit_council_verdicts = createSwarmTool({
|
|
|
108310
109184
|
init_zod();
|
|
108311
109185
|
init_loader();
|
|
108312
109186
|
import * as fs77 from "node:fs";
|
|
108313
|
-
import * as
|
|
109187
|
+
import * as path115 from "node:path";
|
|
108314
109188
|
|
|
108315
109189
|
// src/council/general-council-advisory.ts
|
|
108316
109190
|
var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
|
|
@@ -108738,10 +109612,10 @@ var convene_general_council = createSwarmTool({
|
|
|
108738
109612
|
const round1 = input.round1Responses;
|
|
108739
109613
|
const round2 = input.round2Responses ?? [];
|
|
108740
109614
|
const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
|
|
108741
|
-
const evidenceDir =
|
|
109615
|
+
const evidenceDir = path115.join(workingDir, ".swarm", "council", "general");
|
|
108742
109616
|
const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
|
|
108743
109617
|
const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
|
|
108744
|
-
const evidencePath =
|
|
109618
|
+
const evidencePath = path115.join(evidenceDir, evidenceFile);
|
|
108745
109619
|
try {
|
|
108746
109620
|
await fs77.promises.mkdir(evidenceDir, { recursive: true });
|
|
108747
109621
|
await fs77.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
|
|
@@ -109012,7 +109886,7 @@ init_state();
|
|
|
109012
109886
|
init_task_id();
|
|
109013
109887
|
init_create_tool();
|
|
109014
109888
|
import * as fs78 from "node:fs";
|
|
109015
|
-
import * as
|
|
109889
|
+
import * as path116 from "node:path";
|
|
109016
109890
|
function validateTaskIdFormat2(taskId) {
|
|
109017
109891
|
return validateTaskIdFormat(taskId);
|
|
109018
109892
|
}
|
|
@@ -109086,8 +109960,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109086
109960
|
};
|
|
109087
109961
|
}
|
|
109088
109962
|
}
|
|
109089
|
-
normalizedDir =
|
|
109090
|
-
const pathParts = normalizedDir.split(
|
|
109963
|
+
normalizedDir = path116.normalize(args2.working_directory);
|
|
109964
|
+
const pathParts = normalizedDir.split(path116.sep);
|
|
109091
109965
|
if (pathParts.includes("..")) {
|
|
109092
109966
|
return {
|
|
109093
109967
|
success: false,
|
|
@@ -109097,10 +109971,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109097
109971
|
]
|
|
109098
109972
|
};
|
|
109099
109973
|
}
|
|
109100
|
-
const resolvedDir =
|
|
109974
|
+
const resolvedDir = path116.resolve(normalizedDir);
|
|
109101
109975
|
try {
|
|
109102
109976
|
const realPath = fs78.realpathSync(resolvedDir);
|
|
109103
|
-
const planPath2 =
|
|
109977
|
+
const planPath2 = path116.join(realPath, ".swarm", "plan.json");
|
|
109104
109978
|
if (!fs78.existsSync(planPath2)) {
|
|
109105
109979
|
return {
|
|
109106
109980
|
success: false,
|
|
@@ -109121,9 +109995,9 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109121
109995
|
}
|
|
109122
109996
|
if (normalizedDir && fallbackDir) {
|
|
109123
109997
|
try {
|
|
109124
|
-
const canonicalWorkingDir = fs78.realpathSync(
|
|
109125
|
-
const canonicalProjectRoot = fs78.realpathSync(
|
|
109126
|
-
if (canonicalWorkingDir.startsWith(canonicalProjectRoot +
|
|
109998
|
+
const canonicalWorkingDir = fs78.realpathSync(path116.resolve(normalizedDir));
|
|
109999
|
+
const canonicalProjectRoot = fs78.realpathSync(path116.resolve(fallbackDir));
|
|
110000
|
+
if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path116.sep)) {
|
|
109127
110001
|
return {
|
|
109128
110002
|
success: false,
|
|
109129
110003
|
message: `working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,
|
|
@@ -109145,7 +110019,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109145
110019
|
};
|
|
109146
110020
|
}
|
|
109147
110021
|
const directory = normalizedDir || fallbackDir;
|
|
109148
|
-
const planPath =
|
|
110022
|
+
const planPath = path116.resolve(directory, ".swarm", "plan.json");
|
|
109149
110023
|
if (!fs78.existsSync(planPath)) {
|
|
109150
110024
|
return {
|
|
109151
110025
|
success: false,
|
|
@@ -109185,8 +110059,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109185
110059
|
const normalizeErrors = [];
|
|
109186
110060
|
const dir = directory;
|
|
109187
110061
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
109188
|
-
if (
|
|
109189
|
-
const relativePath =
|
|
110062
|
+
if (path116.isAbsolute(file3)) {
|
|
110063
|
+
const relativePath = path116.relative(dir, file3).replace(/\\/g, "/");
|
|
109190
110064
|
if (relativePath.startsWith("..")) {
|
|
109191
110065
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
109192
110066
|
return file3;
|
|
@@ -109248,7 +110122,7 @@ var declare_scope = createSwarmTool({
|
|
|
109248
110122
|
init_zod();
|
|
109249
110123
|
import * as child_process7 from "node:child_process";
|
|
109250
110124
|
import * as fs79 from "node:fs";
|
|
109251
|
-
import * as
|
|
110125
|
+
import * as path117 from "node:path";
|
|
109252
110126
|
init_create_tool();
|
|
109253
110127
|
var MAX_DIFF_LINES = 500;
|
|
109254
110128
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -109277,20 +110151,20 @@ function validateBase(base) {
|
|
|
109277
110151
|
function validatePaths(paths) {
|
|
109278
110152
|
if (!paths)
|
|
109279
110153
|
return null;
|
|
109280
|
-
for (const
|
|
109281
|
-
if (!
|
|
110154
|
+
for (const path118 of paths) {
|
|
110155
|
+
if (!path118 || path118.length === 0) {
|
|
109282
110156
|
return "empty path not allowed";
|
|
109283
110157
|
}
|
|
109284
|
-
if (
|
|
110158
|
+
if (path118.length > MAX_PATH_LENGTH) {
|
|
109285
110159
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
109286
110160
|
}
|
|
109287
|
-
if (SHELL_METACHARACTERS2.test(
|
|
110161
|
+
if (SHELL_METACHARACTERS2.test(path118)) {
|
|
109288
110162
|
return "path contains shell metacharacters";
|
|
109289
110163
|
}
|
|
109290
|
-
if (
|
|
110164
|
+
if (path118.startsWith("-")) {
|
|
109291
110165
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
109292
110166
|
}
|
|
109293
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
110167
|
+
if (CONTROL_CHAR_PATTERN2.test(path118)) {
|
|
109294
110168
|
return "path contains control characters";
|
|
109295
110169
|
}
|
|
109296
110170
|
}
|
|
@@ -109398,8 +110272,8 @@ var diff = createSwarmTool({
|
|
|
109398
110272
|
if (parts2.length >= 3) {
|
|
109399
110273
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
109400
110274
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
109401
|
-
const
|
|
109402
|
-
files.push({ path:
|
|
110275
|
+
const path118 = parts2[2];
|
|
110276
|
+
files.push({ path: path118, additions, deletions });
|
|
109403
110277
|
}
|
|
109404
110278
|
}
|
|
109405
110279
|
const contractChanges = [];
|
|
@@ -109438,7 +110312,7 @@ var diff = createSwarmTool({
|
|
|
109438
110312
|
} else if (base === "unstaged") {
|
|
109439
110313
|
const oldRef = `:${file3.path}`;
|
|
109440
110314
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
109441
|
-
newContent = fs79.readFileSync(
|
|
110315
|
+
newContent = fs79.readFileSync(path117.join(directory, file3.path), "utf-8");
|
|
109442
110316
|
} else {
|
|
109443
110317
|
const oldRef = `${base}:${file3.path}`;
|
|
109444
110318
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
@@ -109515,12 +110389,12 @@ var diff = createSwarmTool({
|
|
|
109515
110389
|
init_zod();
|
|
109516
110390
|
import * as child_process8 from "node:child_process";
|
|
109517
110391
|
import * as fs80 from "node:fs";
|
|
109518
|
-
import * as
|
|
110392
|
+
import * as path118 from "node:path";
|
|
109519
110393
|
init_create_tool();
|
|
109520
110394
|
init_resolve_working_directory();
|
|
109521
110395
|
async function execGit2(workingDir, args2, options) {
|
|
109522
110396
|
try {
|
|
109523
|
-
const stdout = await new Promise((
|
|
110397
|
+
const stdout = await new Promise((resolve41, reject) => {
|
|
109524
110398
|
const execOpts = {
|
|
109525
110399
|
encoding: "utf-8",
|
|
109526
110400
|
cwd: workingDir,
|
|
@@ -109533,7 +110407,7 @@ async function execGit2(workingDir, args2, options) {
|
|
|
109533
110407
|
reject(error93);
|
|
109534
110408
|
return;
|
|
109535
110409
|
}
|
|
109536
|
-
|
|
110410
|
+
resolve41(output ?? "");
|
|
109537
110411
|
});
|
|
109538
110412
|
});
|
|
109539
110413
|
return stdout;
|
|
@@ -109584,7 +110458,7 @@ var diff_summary = createSwarmTool({
|
|
|
109584
110458
|
}
|
|
109585
110459
|
try {
|
|
109586
110460
|
let oldContent;
|
|
109587
|
-
const newContent = await fs80.promises.readFile(
|
|
110461
|
+
const newContent = await fs80.promises.readFile(path118.join(workingDir, filePath), "utf-8");
|
|
109588
110462
|
if (fileExistsInHead) {
|
|
109589
110463
|
oldContent = await execGit2(workingDir, ["show", `HEAD:${filePath}`], {
|
|
109590
110464
|
timeout: 5000,
|
|
@@ -109814,7 +110688,7 @@ init_zod();
|
|
|
109814
110688
|
init_create_tool();
|
|
109815
110689
|
init_path_security();
|
|
109816
110690
|
import * as fs81 from "node:fs";
|
|
109817
|
-
import * as
|
|
110691
|
+
import * as path119 from "node:path";
|
|
109818
110692
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
109819
110693
|
var MAX_EVIDENCE_FILES = 1000;
|
|
109820
110694
|
var EVIDENCE_DIR3 = ".swarm/evidence";
|
|
@@ -109841,9 +110715,9 @@ function validateRequiredTypes(input) {
|
|
|
109841
110715
|
return null;
|
|
109842
110716
|
}
|
|
109843
110717
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
109844
|
-
const normalizedCwd =
|
|
109845
|
-
const swarmPath =
|
|
109846
|
-
const normalizedPath =
|
|
110718
|
+
const normalizedCwd = path119.resolve(cwd);
|
|
110719
|
+
const swarmPath = path119.join(normalizedCwd, ".swarm");
|
|
110720
|
+
const normalizedPath = path119.resolve(filePath);
|
|
109847
110721
|
return normalizedPath.startsWith(swarmPath);
|
|
109848
110722
|
}
|
|
109849
110723
|
function parseCompletedTasks(planContent) {
|
|
@@ -109873,10 +110747,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
109873
110747
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
109874
110748
|
continue;
|
|
109875
110749
|
}
|
|
109876
|
-
const filePath =
|
|
110750
|
+
const filePath = path119.join(evidenceDir, filename);
|
|
109877
110751
|
try {
|
|
109878
|
-
const resolvedPath =
|
|
109879
|
-
const evidenceDirResolved =
|
|
110752
|
+
const resolvedPath = path119.resolve(filePath);
|
|
110753
|
+
const evidenceDirResolved = path119.resolve(evidenceDir);
|
|
109880
110754
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
109881
110755
|
continue;
|
|
109882
110756
|
}
|
|
@@ -109994,7 +110868,7 @@ var evidence_check = createSwarmTool({
|
|
|
109994
110868
|
return JSON.stringify(errorResult, null, 2);
|
|
109995
110869
|
}
|
|
109996
110870
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
109997
|
-
const planPath =
|
|
110871
|
+
const planPath = path119.join(cwd, PLAN_FILE);
|
|
109998
110872
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
109999
110873
|
const errorResult = {
|
|
110000
110874
|
error: "plan file path validation failed",
|
|
@@ -110026,7 +110900,7 @@ var evidence_check = createSwarmTool({
|
|
|
110026
110900
|
};
|
|
110027
110901
|
return JSON.stringify(result2, null, 2);
|
|
110028
110902
|
}
|
|
110029
|
-
const evidenceDir =
|
|
110903
|
+
const evidenceDir = path119.join(cwd, EVIDENCE_DIR3);
|
|
110030
110904
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
110031
110905
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
110032
110906
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -110045,7 +110919,7 @@ var evidence_check = createSwarmTool({
|
|
|
110045
110919
|
init_zod();
|
|
110046
110920
|
init_create_tool();
|
|
110047
110921
|
import * as fs82 from "node:fs";
|
|
110048
|
-
import * as
|
|
110922
|
+
import * as path120 from "node:path";
|
|
110049
110923
|
var EXT_MAP = {
|
|
110050
110924
|
python: ".py",
|
|
110051
110925
|
py: ".py",
|
|
@@ -110126,12 +111000,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
110126
111000
|
if (prefix) {
|
|
110127
111001
|
filename = `${prefix}_${filename}`;
|
|
110128
111002
|
}
|
|
110129
|
-
let filepath =
|
|
110130
|
-
const base =
|
|
110131
|
-
const ext =
|
|
111003
|
+
let filepath = path120.join(targetDir, filename);
|
|
111004
|
+
const base = path120.basename(filepath, path120.extname(filepath));
|
|
111005
|
+
const ext = path120.extname(filepath);
|
|
110132
111006
|
let counter = 1;
|
|
110133
111007
|
while (fs82.existsSync(filepath)) {
|
|
110134
|
-
filepath =
|
|
111008
|
+
filepath = path120.join(targetDir, `${base}_${counter}${ext}`);
|
|
110135
111009
|
counter++;
|
|
110136
111010
|
}
|
|
110137
111011
|
try {
|
|
@@ -110473,7 +111347,7 @@ init_create_tool();
|
|
|
110473
111347
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
110474
111348
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
110475
111349
|
var GITINGEST_MAX_RETRIES = 2;
|
|
110476
|
-
var delay = (ms) => new Promise((
|
|
111350
|
+
var delay = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
|
|
110477
111351
|
async function fetchGitingest(args2) {
|
|
110478
111352
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
110479
111353
|
try {
|
|
@@ -110562,7 +111436,7 @@ init_zod();
|
|
|
110562
111436
|
init_create_tool();
|
|
110563
111437
|
init_path_security();
|
|
110564
111438
|
import * as fs83 from "node:fs";
|
|
110565
|
-
import * as
|
|
111439
|
+
import * as path121 from "node:path";
|
|
110566
111440
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
110567
111441
|
var MAX_SYMBOL_LENGTH = 256;
|
|
110568
111442
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -110610,7 +111484,7 @@ function validateSymbolInput(symbol3) {
|
|
|
110610
111484
|
return null;
|
|
110611
111485
|
}
|
|
110612
111486
|
function isBinaryFile2(filePath, buffer) {
|
|
110613
|
-
const ext =
|
|
111487
|
+
const ext = path121.extname(filePath).toLowerCase();
|
|
110614
111488
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
110615
111489
|
return false;
|
|
110616
111490
|
}
|
|
@@ -110634,15 +111508,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
110634
111508
|
const imports = [];
|
|
110635
111509
|
let _resolvedTarget;
|
|
110636
111510
|
try {
|
|
110637
|
-
_resolvedTarget =
|
|
111511
|
+
_resolvedTarget = path121.resolve(targetFile);
|
|
110638
111512
|
} catch {
|
|
110639
111513
|
_resolvedTarget = targetFile;
|
|
110640
111514
|
}
|
|
110641
|
-
const targetBasename =
|
|
111515
|
+
const targetBasename = path121.basename(targetFile, path121.extname(targetFile));
|
|
110642
111516
|
const targetWithExt = targetFile;
|
|
110643
111517
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
110644
|
-
const normalizedTargetWithExt =
|
|
110645
|
-
const normalizedTargetWithoutExt =
|
|
111518
|
+
const normalizedTargetWithExt = path121.normalize(targetWithExt).replace(/\\/g, "/");
|
|
111519
|
+
const normalizedTargetWithoutExt = path121.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
110646
111520
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
110647
111521
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
110648
111522
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -110665,9 +111539,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
110665
111539
|
}
|
|
110666
111540
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
110667
111541
|
let isMatch = false;
|
|
110668
|
-
const _targetDir =
|
|
110669
|
-
const targetExt =
|
|
110670
|
-
const targetBasenameNoExt =
|
|
111542
|
+
const _targetDir = path121.dirname(targetFile);
|
|
111543
|
+
const targetExt = path121.extname(targetFile);
|
|
111544
|
+
const targetBasenameNoExt = path121.basename(targetFile, targetExt);
|
|
110671
111545
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
110672
111546
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
110673
111547
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -110735,10 +111609,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
110735
111609
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
110736
111610
|
for (const entry of entries) {
|
|
110737
111611
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
110738
|
-
stats.skippedDirs.push(
|
|
111612
|
+
stats.skippedDirs.push(path121.join(dir, entry));
|
|
110739
111613
|
continue;
|
|
110740
111614
|
}
|
|
110741
|
-
const fullPath =
|
|
111615
|
+
const fullPath = path121.join(dir, entry);
|
|
110742
111616
|
let stat9;
|
|
110743
111617
|
try {
|
|
110744
111618
|
stat9 = fs83.statSync(fullPath);
|
|
@@ -110752,7 +111626,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
110752
111626
|
if (stat9.isDirectory()) {
|
|
110753
111627
|
findSourceFiles2(fullPath, files, stats);
|
|
110754
111628
|
} else if (stat9.isFile()) {
|
|
110755
|
-
const ext =
|
|
111629
|
+
const ext = path121.extname(fullPath).toLowerCase();
|
|
110756
111630
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
110757
111631
|
files.push(fullPath);
|
|
110758
111632
|
}
|
|
@@ -110809,7 +111683,7 @@ var imports = createSwarmTool({
|
|
|
110809
111683
|
return JSON.stringify(errorResult, null, 2);
|
|
110810
111684
|
}
|
|
110811
111685
|
try {
|
|
110812
|
-
const targetFile =
|
|
111686
|
+
const targetFile = path121.resolve(file3);
|
|
110813
111687
|
if (!fs83.existsSync(targetFile)) {
|
|
110814
111688
|
const errorResult = {
|
|
110815
111689
|
error: `target file not found: ${file3}`,
|
|
@@ -110831,7 +111705,7 @@ var imports = createSwarmTool({
|
|
|
110831
111705
|
};
|
|
110832
111706
|
return JSON.stringify(errorResult, null, 2);
|
|
110833
111707
|
}
|
|
110834
|
-
const baseDir =
|
|
111708
|
+
const baseDir = path121.dirname(targetFile);
|
|
110835
111709
|
const scanStats = {
|
|
110836
111710
|
skippedDirs: [],
|
|
110837
111711
|
skippedFiles: 0,
|
|
@@ -111219,7 +112093,7 @@ init_zod();
|
|
|
111219
112093
|
init_config();
|
|
111220
112094
|
init_knowledge_store();
|
|
111221
112095
|
init_create_tool();
|
|
111222
|
-
import { existsSync as
|
|
112096
|
+
import { existsSync as existsSync69 } from "node:fs";
|
|
111223
112097
|
var DEFAULT_LIMIT = 10;
|
|
111224
112098
|
var MAX_LESSON_LENGTH = 200;
|
|
111225
112099
|
var VALID_CATEGORIES3 = [
|
|
@@ -111295,14 +112169,14 @@ function validateLimit(limit) {
|
|
|
111295
112169
|
}
|
|
111296
112170
|
async function readSwarmKnowledge(directory) {
|
|
111297
112171
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
111298
|
-
if (!
|
|
112172
|
+
if (!existsSync69(swarmPath)) {
|
|
111299
112173
|
return [];
|
|
111300
112174
|
}
|
|
111301
112175
|
return readKnowledge(swarmPath);
|
|
111302
112176
|
}
|
|
111303
112177
|
async function readHiveKnowledge() {
|
|
111304
112178
|
const hivePath = resolveHiveKnowledgePath();
|
|
111305
|
-
if (!
|
|
112179
|
+
if (!existsSync69(hivePath)) {
|
|
111306
112180
|
return [];
|
|
111307
112181
|
}
|
|
111308
112182
|
return readKnowledge(hivePath);
|
|
@@ -111728,11 +112602,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
111728
112602
|
init_zod();
|
|
111729
112603
|
init_constants();
|
|
111730
112604
|
import * as fs85 from "node:fs";
|
|
111731
|
-
import * as
|
|
112605
|
+
import * as path123 from "node:path";
|
|
111732
112606
|
|
|
111733
112607
|
// src/turbo/lean/conflicts.ts
|
|
111734
112608
|
import * as fs84 from "node:fs";
|
|
111735
|
-
import * as
|
|
112609
|
+
import * as path122 from "node:path";
|
|
111736
112610
|
var DEFAULT_GLOBAL_FILES = [
|
|
111737
112611
|
"package.json",
|
|
111738
112612
|
"package-lock.json",
|
|
@@ -111835,7 +112709,7 @@ function isGlobalFile(normalizedPath) {
|
|
|
111835
112709
|
}
|
|
111836
112710
|
return false;
|
|
111837
112711
|
}
|
|
111838
|
-
function
|
|
112712
|
+
function isProtectedPath3(normalizedPath) {
|
|
111839
112713
|
const lowerPath = normalizedPath.toLowerCase();
|
|
111840
112714
|
for (const pattern of DEFAULT_PROTECTED_PATTERNS) {
|
|
111841
112715
|
if (lowerPath.includes(pattern.toLowerCase())) {
|
|
@@ -111859,7 +112733,7 @@ function isProtectedPath2(normalizedPath) {
|
|
|
111859
112733
|
return false;
|
|
111860
112734
|
}
|
|
111861
112735
|
function readTaskScopes(directory, taskId) {
|
|
111862
|
-
const scopePath =
|
|
112736
|
+
const scopePath = path122.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
111863
112737
|
try {
|
|
111864
112738
|
if (!fs84.existsSync(scopePath)) {
|
|
111865
112739
|
return null;
|
|
@@ -111885,7 +112759,7 @@ function assessTaskRisk(files, hasDeclaredScope, hasInvalidScope, config3) {
|
|
|
111885
112759
|
files: globalFiles
|
|
111886
112760
|
};
|
|
111887
112761
|
}
|
|
111888
|
-
const protectedFiles = files.filter(
|
|
112762
|
+
const protectedFiles = files.filter(isProtectedPath3);
|
|
111889
112763
|
if (protectedFiles.length > 0) {
|
|
111890
112764
|
return {
|
|
111891
112765
|
category: "protected",
|
|
@@ -112247,7 +113121,7 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
112247
113121
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
112248
113122
|
init_create_tool();
|
|
112249
113123
|
function readPlanJson(directory) {
|
|
112250
|
-
const planPath =
|
|
113124
|
+
const planPath = path123.join(directory, ".swarm", "plan.json");
|
|
112251
113125
|
if (!fs85.existsSync(planPath)) {
|
|
112252
113126
|
return null;
|
|
112253
113127
|
}
|
|
@@ -112303,15 +113177,15 @@ init_config();
|
|
|
112303
113177
|
// src/turbo/lean/reviewer.ts
|
|
112304
113178
|
init_state();
|
|
112305
113179
|
import * as fs87 from "node:fs/promises";
|
|
112306
|
-
import * as
|
|
113180
|
+
import * as path125 from "node:path";
|
|
112307
113181
|
|
|
112308
113182
|
// src/turbo/lean/evidence.ts
|
|
112309
113183
|
init_bun_compat();
|
|
112310
113184
|
import { rmSync as rmSync6 } from "node:fs";
|
|
112311
113185
|
import * as fs86 from "node:fs/promises";
|
|
112312
|
-
import * as
|
|
113186
|
+
import * as path124 from "node:path";
|
|
112313
113187
|
function leanTurboEvidenceDir(directory, phase) {
|
|
112314
|
-
return
|
|
113188
|
+
return path124.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
112315
113189
|
}
|
|
112316
113190
|
function validateLaneId(laneId) {
|
|
112317
113191
|
if (laneId.length === 0) {
|
|
@@ -112333,16 +113207,16 @@ function validateLaneId(laneId) {
|
|
|
112333
113207
|
function laneEvidencePath(directory, phase, laneId) {
|
|
112334
113208
|
validateLaneId(laneId);
|
|
112335
113209
|
const expectedDir = leanTurboEvidenceDir(directory, phase);
|
|
112336
|
-
const resolvedPath =
|
|
112337
|
-
const resolvedDir =
|
|
112338
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
113210
|
+
const resolvedPath = path124.resolve(path124.join(expectedDir, `${laneId}.json`));
|
|
113211
|
+
const resolvedDir = path124.resolve(expectedDir);
|
|
113212
|
+
if (!resolvedPath.startsWith(resolvedDir + path124.sep) && resolvedPath !== resolvedDir) {
|
|
112339
113213
|
throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
|
|
112340
113214
|
}
|
|
112341
113215
|
return resolvedPath;
|
|
112342
113216
|
}
|
|
112343
113217
|
async function atomicWriteJson(filePath, data) {
|
|
112344
113218
|
const content = JSON.stringify(data, null, 2);
|
|
112345
|
-
const dir =
|
|
113219
|
+
const dir = path124.dirname(filePath);
|
|
112346
113220
|
await fs86.mkdir(dir, { recursive: true });
|
|
112347
113221
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
112348
113222
|
try {
|
|
@@ -112356,7 +113230,7 @@ async function atomicWriteJson(filePath, data) {
|
|
|
112356
113230
|
}
|
|
112357
113231
|
}
|
|
112358
113232
|
function phaseEvidencePath(directory, phase) {
|
|
112359
|
-
return
|
|
113233
|
+
return path124.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
|
|
112360
113234
|
}
|
|
112361
113235
|
async function writeLaneEvidence(directory, phase, evidence) {
|
|
112362
113236
|
const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
|
|
@@ -112400,7 +113274,7 @@ async function listLaneEvidence(directory, phase) {
|
|
|
112400
113274
|
if (entry === "lean-turbo-phase.json") {
|
|
112401
113275
|
continue;
|
|
112402
113276
|
}
|
|
112403
|
-
const filePath =
|
|
113277
|
+
const filePath = path124.join(evidenceDir, entry);
|
|
112404
113278
|
let content;
|
|
112405
113279
|
try {
|
|
112406
113280
|
content = await fs86.readFile(filePath, "utf-8");
|
|
@@ -112531,9 +113405,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
112531
113405
|
return { verdict, reason };
|
|
112532
113406
|
}
|
|
112533
113407
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
112534
|
-
const evidenceDir =
|
|
113408
|
+
const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
|
|
112535
113409
|
await fs87.mkdir(evidenceDir, { recursive: true });
|
|
112536
|
-
const evidencePath =
|
|
113410
|
+
const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
|
|
112537
113411
|
const content = JSON.stringify({
|
|
112538
113412
|
phase,
|
|
112539
113413
|
verdict,
|
|
@@ -113345,7 +114219,7 @@ init_lint();
|
|
|
113345
114219
|
init_spec_schema();
|
|
113346
114220
|
init_create_tool();
|
|
113347
114221
|
import * as fs88 from "node:fs";
|
|
113348
|
-
import * as
|
|
114222
|
+
import * as path126 from "node:path";
|
|
113349
114223
|
var SPEC_FILE_NAME = "spec.md";
|
|
113350
114224
|
var SWARM_DIR2 = ".swarm";
|
|
113351
114225
|
var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -113398,7 +114272,7 @@ var lint_spec = createSwarmTool({
|
|
|
113398
114272
|
async execute(_args, directory) {
|
|
113399
114273
|
const errors5 = [];
|
|
113400
114274
|
const warnings = [];
|
|
113401
|
-
const specPath =
|
|
114275
|
+
const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
113402
114276
|
if (!fs88.existsSync(specPath)) {
|
|
113403
114277
|
const result2 = {
|
|
113404
114278
|
valid: false,
|
|
@@ -113470,12 +114344,12 @@ var lint_spec = createSwarmTool({
|
|
|
113470
114344
|
// src/tools/mutation-test.ts
|
|
113471
114345
|
init_zod();
|
|
113472
114346
|
import * as fs89 from "node:fs";
|
|
113473
|
-
import * as
|
|
114347
|
+
import * as path128 from "node:path";
|
|
113474
114348
|
|
|
113475
114349
|
// src/mutation/engine.ts
|
|
113476
114350
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
113477
|
-
import { unlinkSync as
|
|
113478
|
-
import * as
|
|
114351
|
+
import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync24 } from "node:fs";
|
|
114352
|
+
import * as path127 from "node:path";
|
|
113479
114353
|
|
|
113480
114354
|
// src/mutation/equivalence.ts
|
|
113481
114355
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -113621,9 +114495,9 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
113621
114495
|
let patchFile;
|
|
113622
114496
|
try {
|
|
113623
114497
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
113624
|
-
patchFile =
|
|
114498
|
+
patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
113625
114499
|
try {
|
|
113626
|
-
|
|
114500
|
+
writeFileSync24(patchFile, patch.patch);
|
|
113627
114501
|
} catch (writeErr) {
|
|
113628
114502
|
error93 = `Failed to write patch file: ${writeErr}`;
|
|
113629
114503
|
outcome = "error";
|
|
@@ -113719,7 +114593,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
113719
114593
|
revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
|
|
113720
114594
|
}
|
|
113721
114595
|
try {
|
|
113722
|
-
|
|
114596
|
+
unlinkSync18(patchFile);
|
|
113723
114597
|
} catch (_unlinkErr) {}
|
|
113724
114598
|
}
|
|
113725
114599
|
}
|
|
@@ -114025,7 +114899,7 @@ var mutation_test = createSwarmTool({
|
|
|
114025
114899
|
];
|
|
114026
114900
|
for (const filePath of uniquePaths) {
|
|
114027
114901
|
try {
|
|
114028
|
-
const resolvedPath =
|
|
114902
|
+
const resolvedPath = path128.resolve(cwd, filePath);
|
|
114029
114903
|
sourceFiles.set(filePath, fs89.readFileSync(resolvedPath, "utf-8"));
|
|
114030
114904
|
} catch {}
|
|
114031
114905
|
}
|
|
@@ -114047,22 +114921,22 @@ init_config();
|
|
|
114047
114921
|
init_schema();
|
|
114048
114922
|
init_manager2();
|
|
114049
114923
|
import * as fs99 from "node:fs";
|
|
114050
|
-
import * as
|
|
114924
|
+
import * as path138 from "node:path";
|
|
114051
114925
|
|
|
114052
114926
|
// src/full-auto/phase-approval.ts
|
|
114053
114927
|
init_utils2();
|
|
114054
114928
|
init_logger();
|
|
114055
114929
|
init_state2();
|
|
114056
114930
|
import * as fs90 from "node:fs";
|
|
114057
|
-
import * as
|
|
114931
|
+
import * as path129 from "node:path";
|
|
114058
114932
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
114059
114933
|
function readEvidenceDir(directory, phase) {
|
|
114060
114934
|
try {
|
|
114061
|
-
const dirPath = validateSwarmPath(directory,
|
|
114935
|
+
const dirPath = validateSwarmPath(directory, path129.posix.join("evidence", String(phase)));
|
|
114062
114936
|
if (!fs90.existsSync(dirPath))
|
|
114063
114937
|
return [];
|
|
114064
114938
|
const entries = fs90.readdirSync(dirPath);
|
|
114065
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
114939
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path129.join(dirPath, e));
|
|
114066
114940
|
} catch {
|
|
114067
114941
|
return [];
|
|
114068
114942
|
}
|
|
@@ -114203,16 +115077,16 @@ init_plan_schema();
|
|
|
114203
115077
|
init_ledger();
|
|
114204
115078
|
init_manager();
|
|
114205
115079
|
import * as fs91 from "node:fs";
|
|
114206
|
-
import * as
|
|
115080
|
+
import * as path130 from "node:path";
|
|
114207
115081
|
async function writeCheckpoint(directory) {
|
|
114208
115082
|
try {
|
|
114209
115083
|
const plan = await loadPlan(directory);
|
|
114210
115084
|
if (!plan)
|
|
114211
115085
|
return;
|
|
114212
|
-
const swarmDir =
|
|
115086
|
+
const swarmDir = path130.join(directory, ".swarm");
|
|
114213
115087
|
fs91.mkdirSync(swarmDir, { recursive: true });
|
|
114214
|
-
const jsonPath =
|
|
114215
|
-
const mdPath =
|
|
115088
|
+
const jsonPath = path130.join(swarmDir, "SWARM_PLAN.json");
|
|
115089
|
+
const mdPath = path130.join(swarmDir, "SWARM_PLAN.md");
|
|
114216
115090
|
fs91.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
114217
115091
|
const md = derivePlanMarkdown(plan);
|
|
114218
115092
|
fs91.writeFileSync(mdPath, md, "utf8");
|
|
@@ -114231,7 +115105,7 @@ init_telemetry();
|
|
|
114231
115105
|
// src/turbo/lean/phase-ready.ts
|
|
114232
115106
|
init_file_locks();
|
|
114233
115107
|
import * as fs92 from "node:fs";
|
|
114234
|
-
import * as
|
|
115108
|
+
import * as path131 from "node:path";
|
|
114235
115109
|
init_state3();
|
|
114236
115110
|
var DEFAULT_CONFIG3 = {
|
|
114237
115111
|
phase_reviewer: true,
|
|
@@ -114240,7 +115114,7 @@ var DEFAULT_CONFIG3 = {
|
|
|
114240
115114
|
};
|
|
114241
115115
|
function defaultReadPlanJson(dir) {
|
|
114242
115116
|
try {
|
|
114243
|
-
const planPath =
|
|
115117
|
+
const planPath = path131.join(dir, ".swarm", "plan.json");
|
|
114244
115118
|
if (!fs92.existsSync(planPath))
|
|
114245
115119
|
return null;
|
|
114246
115120
|
const raw = fs92.readFileSync(planPath, "utf-8");
|
|
@@ -114255,7 +115129,7 @@ function defaultReadPlanJson(dir) {
|
|
|
114255
115129
|
}
|
|
114256
115130
|
function readReviewerEvidenceFromFile(directory, phase) {
|
|
114257
115131
|
try {
|
|
114258
|
-
const evidencePath =
|
|
115132
|
+
const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
|
|
114259
115133
|
if (!fs92.existsSync(evidencePath)) {
|
|
114260
115134
|
return null;
|
|
114261
115135
|
}
|
|
@@ -114275,7 +115149,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
|
|
|
114275
115149
|
}
|
|
114276
115150
|
function readCriticEvidenceFromFile(directory, phase) {
|
|
114277
115151
|
try {
|
|
114278
|
-
const evidencePath =
|
|
115152
|
+
const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
|
|
114279
115153
|
if (!fs92.existsSync(evidencePath)) {
|
|
114280
115154
|
return null;
|
|
114281
115155
|
}
|
|
@@ -114294,7 +115168,7 @@ function readCriticEvidenceFromFile(directory, phase) {
|
|
|
114294
115168
|
}
|
|
114295
115169
|
}
|
|
114296
115170
|
function listLaneEvidenceSync(directory, phase) {
|
|
114297
|
-
const evidenceDir =
|
|
115171
|
+
const evidenceDir = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
114298
115172
|
let entries;
|
|
114299
115173
|
try {
|
|
114300
115174
|
entries = fs92.readdirSync(evidenceDir);
|
|
@@ -114364,7 +115238,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
114364
115238
|
...DEFAULT_CONFIG3,
|
|
114365
115239
|
...actualConfig
|
|
114366
115240
|
};
|
|
114367
|
-
const statePath =
|
|
115241
|
+
const statePath = path131.join(directory, ".swarm", "turbo-state.json");
|
|
114368
115242
|
if (!fs92.existsSync(statePath)) {
|
|
114369
115243
|
return {
|
|
114370
115244
|
ok: false,
|
|
@@ -114552,7 +115426,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
114552
115426
|
}
|
|
114553
115427
|
}
|
|
114554
115428
|
if (mergedConfig.integrated_diff_required) {
|
|
114555
|
-
const evidencePath =
|
|
115429
|
+
const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
|
|
114556
115430
|
let hasDiff = false;
|
|
114557
115431
|
try {
|
|
114558
115432
|
const content = fs92.readFileSync(evidencePath, "utf-8");
|
|
@@ -114704,13 +115578,13 @@ init_qa_gate_profile();
|
|
|
114704
115578
|
init_manager();
|
|
114705
115579
|
init_state();
|
|
114706
115580
|
import * as fs93 from "node:fs";
|
|
114707
|
-
import * as
|
|
115581
|
+
import * as path132 from "node:path";
|
|
114708
115582
|
async function runDriftGate(ctx) {
|
|
114709
115583
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
114710
115584
|
let driftCheckEnabled = true;
|
|
114711
115585
|
let driftHasSpecMd = false;
|
|
114712
115586
|
try {
|
|
114713
|
-
const specMdPath =
|
|
115587
|
+
const specMdPath = path132.join(dir, ".swarm", "spec.md");
|
|
114714
115588
|
driftHasSpecMd = fs93.existsSync(specMdPath);
|
|
114715
115589
|
const gatePlan = await loadPlan(dir);
|
|
114716
115590
|
if (gatePlan) {
|
|
@@ -114738,7 +115612,7 @@ async function runDriftGate(ctx) {
|
|
|
114738
115612
|
}
|
|
114739
115613
|
let phaseType;
|
|
114740
115614
|
try {
|
|
114741
|
-
const planPath =
|
|
115615
|
+
const planPath = path132.join(dir, ".swarm", "plan.json");
|
|
114742
115616
|
if (fs93.existsSync(planPath)) {
|
|
114743
115617
|
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
114744
115618
|
const plan = JSON.parse(planRaw);
|
|
@@ -114757,7 +115631,7 @@ async function runDriftGate(ctx) {
|
|
|
114757
115631
|
};
|
|
114758
115632
|
}
|
|
114759
115633
|
try {
|
|
114760
|
-
const driftEvidencePath =
|
|
115634
|
+
const driftEvidencePath = path132.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
114761
115635
|
let driftVerdictFound = false;
|
|
114762
115636
|
let driftVerdictApproved = false;
|
|
114763
115637
|
try {
|
|
@@ -114793,7 +115667,7 @@ async function runDriftGate(ctx) {
|
|
|
114793
115667
|
let incompleteTaskCount = 0;
|
|
114794
115668
|
let planParseable = false;
|
|
114795
115669
|
try {
|
|
114796
|
-
const planPath =
|
|
115670
|
+
const planPath = path132.join(dir, ".swarm", "plan.json");
|
|
114797
115671
|
if (fs93.existsSync(planPath)) {
|
|
114798
115672
|
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
114799
115673
|
const plan = JSON.parse(planRaw);
|
|
@@ -114875,7 +115749,7 @@ init_qa_gate_profile();
|
|
|
114875
115749
|
init_manager();
|
|
114876
115750
|
init_state();
|
|
114877
115751
|
import * as fs94 from "node:fs";
|
|
114878
|
-
import * as
|
|
115752
|
+
import * as path133 from "node:path";
|
|
114879
115753
|
async function runFinalCouncilGate(ctx) {
|
|
114880
115754
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
114881
115755
|
let finalCouncilEnabled = false;
|
|
@@ -114892,7 +115766,7 @@ async function runFinalCouncilGate(ctx) {
|
|
|
114892
115766
|
const effective = getEffectiveGates(profile, overrides);
|
|
114893
115767
|
if (effective.final_council === true) {
|
|
114894
115768
|
finalCouncilEnabled = true;
|
|
114895
|
-
const fcPath =
|
|
115769
|
+
const fcPath = path133.join(dir, ".swarm", "evidence", "final-council.json");
|
|
114896
115770
|
let fcVerdictFound = false;
|
|
114897
115771
|
let _fcVerdict;
|
|
114898
115772
|
try {
|
|
@@ -115022,7 +115896,7 @@ init_qa_gate_profile();
|
|
|
115022
115896
|
init_manager();
|
|
115023
115897
|
init_state();
|
|
115024
115898
|
import * as fs95 from "node:fs";
|
|
115025
|
-
import * as
|
|
115899
|
+
import * as path134 from "node:path";
|
|
115026
115900
|
async function runHallucinationGate(ctx) {
|
|
115027
115901
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
115028
115902
|
try {
|
|
@@ -115035,7 +115909,7 @@ async function runHallucinationGate(ctx) {
|
|
|
115035
115909
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
115036
115910
|
const effective = getEffectiveGates(profile, overrides);
|
|
115037
115911
|
if (effective.hallucination_guard === true) {
|
|
115038
|
-
const hgPath =
|
|
115912
|
+
const hgPath = path134.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
115039
115913
|
let hgVerdictFound = false;
|
|
115040
115914
|
let hgVerdictApproved = false;
|
|
115041
115915
|
try {
|
|
@@ -115098,7 +115972,7 @@ init_qa_gate_profile();
|
|
|
115098
115972
|
init_manager();
|
|
115099
115973
|
init_state();
|
|
115100
115974
|
import * as fs96 from "node:fs";
|
|
115101
|
-
import * as
|
|
115975
|
+
import * as path135 from "node:path";
|
|
115102
115976
|
async function runMutationGate(ctx) {
|
|
115103
115977
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
115104
115978
|
try {
|
|
@@ -115111,7 +115985,7 @@ async function runMutationGate(ctx) {
|
|
|
115111
115985
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
115112
115986
|
const effective = getEffectiveGates(profile, overrides);
|
|
115113
115987
|
if (effective.mutation_test === true) {
|
|
115114
|
-
const mgPath =
|
|
115988
|
+
const mgPath = path135.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
115115
115989
|
let mgVerdictFound = false;
|
|
115116
115990
|
let mgVerdict;
|
|
115117
115991
|
try {
|
|
@@ -115174,7 +116048,7 @@ init_qa_gate_profile();
|
|
|
115174
116048
|
init_manager();
|
|
115175
116049
|
init_state();
|
|
115176
116050
|
import * as fs97 from "node:fs";
|
|
115177
|
-
import * as
|
|
116051
|
+
import * as path136 from "node:path";
|
|
115178
116052
|
async function runPhaseCouncilGate(ctx) {
|
|
115179
116053
|
const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
|
|
115180
116054
|
let councilModeEnabled = false;
|
|
@@ -115189,7 +116063,7 @@ async function runPhaseCouncilGate(ctx) {
|
|
|
115189
116063
|
const effective = getEffectiveGates(profile, overrides);
|
|
115190
116064
|
if (effective.council_mode === true) {
|
|
115191
116065
|
councilModeEnabled = true;
|
|
115192
|
-
const pcPath =
|
|
116066
|
+
const pcPath = path136.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
115193
116067
|
let pcVerdictFound = false;
|
|
115194
116068
|
let _pcVerdict;
|
|
115195
116069
|
let pcQuorumSize;
|
|
@@ -115704,7 +116578,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
115704
116578
|
}
|
|
115705
116579
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
115706
116580
|
try {
|
|
115707
|
-
const projectName =
|
|
116581
|
+
const projectName = path138.basename(dir);
|
|
115708
116582
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
115709
116583
|
if (curationResult) {
|
|
115710
116584
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -116147,7 +117021,7 @@ init_utils();
|
|
|
116147
117021
|
init_bun_compat();
|
|
116148
117022
|
init_create_tool();
|
|
116149
117023
|
import * as fs100 from "node:fs";
|
|
116150
|
-
import * as
|
|
117024
|
+
import * as path139 from "node:path";
|
|
116151
117025
|
var MAX_OUTPUT_BYTES6 = 52428800;
|
|
116152
117026
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
116153
117027
|
function isValidEcosystem(value) {
|
|
@@ -116175,16 +117049,16 @@ function validateArgs3(args2) {
|
|
|
116175
117049
|
function detectEcosystems(directory) {
|
|
116176
117050
|
const ecosystems = [];
|
|
116177
117051
|
const cwd = directory;
|
|
116178
|
-
if (fs100.existsSync(
|
|
117052
|
+
if (fs100.existsSync(path139.join(cwd, "package.json"))) {
|
|
116179
117053
|
ecosystems.push("npm");
|
|
116180
117054
|
}
|
|
116181
|
-
if (fs100.existsSync(
|
|
117055
|
+
if (fs100.existsSync(path139.join(cwd, "pyproject.toml")) || fs100.existsSync(path139.join(cwd, "requirements.txt"))) {
|
|
116182
117056
|
ecosystems.push("pip");
|
|
116183
117057
|
}
|
|
116184
|
-
if (fs100.existsSync(
|
|
117058
|
+
if (fs100.existsSync(path139.join(cwd, "Cargo.toml"))) {
|
|
116185
117059
|
ecosystems.push("cargo");
|
|
116186
117060
|
}
|
|
116187
|
-
if (fs100.existsSync(
|
|
117061
|
+
if (fs100.existsSync(path139.join(cwd, "go.mod"))) {
|
|
116188
117062
|
ecosystems.push("go");
|
|
116189
117063
|
}
|
|
116190
117064
|
try {
|
|
@@ -116193,13 +117067,13 @@ function detectEcosystems(directory) {
|
|
|
116193
117067
|
ecosystems.push("dotnet");
|
|
116194
117068
|
}
|
|
116195
117069
|
} catch {}
|
|
116196
|
-
if (fs100.existsSync(
|
|
117070
|
+
if (fs100.existsSync(path139.join(cwd, "Gemfile")) || fs100.existsSync(path139.join(cwd, "Gemfile.lock"))) {
|
|
116197
117071
|
ecosystems.push("ruby");
|
|
116198
117072
|
}
|
|
116199
|
-
if (fs100.existsSync(
|
|
117073
|
+
if (fs100.existsSync(path139.join(cwd, "pubspec.yaml"))) {
|
|
116200
117074
|
ecosystems.push("dart");
|
|
116201
117075
|
}
|
|
116202
|
-
if (fs100.existsSync(
|
|
117076
|
+
if (fs100.existsSync(path139.join(cwd, "composer.lock"))) {
|
|
116203
117077
|
ecosystems.push("composer");
|
|
116204
117078
|
}
|
|
116205
117079
|
return ecosystems;
|
|
@@ -116212,7 +117086,7 @@ async function runNpmAudit(directory) {
|
|
|
116212
117086
|
stderr: "pipe",
|
|
116213
117087
|
cwd: directory
|
|
116214
117088
|
});
|
|
116215
|
-
const timeoutPromise = new Promise((
|
|
117089
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116216
117090
|
const result = await Promise.race([
|
|
116217
117091
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
116218
117092
|
timeoutPromise
|
|
@@ -116332,7 +117206,7 @@ async function runPipAudit(directory) {
|
|
|
116332
117206
|
stderr: "pipe",
|
|
116333
117207
|
cwd: directory
|
|
116334
117208
|
});
|
|
116335
|
-
const timeoutPromise = new Promise((
|
|
117209
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116336
117210
|
const result = await Promise.race([
|
|
116337
117211
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
116338
117212
|
timeoutPromise
|
|
@@ -116460,7 +117334,7 @@ async function runCargoAudit(directory) {
|
|
|
116460
117334
|
stderr: "pipe",
|
|
116461
117335
|
cwd: directory
|
|
116462
117336
|
});
|
|
116463
|
-
const timeoutPromise = new Promise((
|
|
117337
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116464
117338
|
const result = await Promise.race([
|
|
116465
117339
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116466
117340
|
timeoutPromise
|
|
@@ -116584,7 +117458,7 @@ async function runGoAudit(directory) {
|
|
|
116584
117458
|
stderr: "pipe",
|
|
116585
117459
|
cwd: directory
|
|
116586
117460
|
});
|
|
116587
|
-
const timeoutPromise = new Promise((
|
|
117461
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116588
117462
|
const result = await Promise.race([
|
|
116589
117463
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116590
117464
|
timeoutPromise
|
|
@@ -116717,7 +117591,7 @@ async function runDotnetAudit(directory) {
|
|
|
116717
117591
|
stderr: "pipe",
|
|
116718
117592
|
cwd: directory
|
|
116719
117593
|
});
|
|
116720
|
-
const timeoutPromise = new Promise((
|
|
117594
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116721
117595
|
const result = await Promise.race([
|
|
116722
117596
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116723
117597
|
timeoutPromise
|
|
@@ -116833,7 +117707,7 @@ async function runBundleAudit(directory) {
|
|
|
116833
117707
|
stderr: "pipe",
|
|
116834
117708
|
cwd: directory
|
|
116835
117709
|
});
|
|
116836
|
-
const timeoutPromise = new Promise((
|
|
117710
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116837
117711
|
const result = await Promise.race([
|
|
116838
117712
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116839
117713
|
timeoutPromise
|
|
@@ -116978,7 +117852,7 @@ async function runDartAudit(directory) {
|
|
|
116978
117852
|
stderr: "pipe",
|
|
116979
117853
|
cwd: directory
|
|
116980
117854
|
});
|
|
116981
|
-
const timeoutPromise = new Promise((
|
|
117855
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116982
117856
|
const result = await Promise.race([
|
|
116983
117857
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116984
117858
|
timeoutPromise
|
|
@@ -117093,7 +117967,7 @@ async function runComposerAudit(directory) {
|
|
|
117093
117967
|
stderr: "pipe",
|
|
117094
117968
|
cwd: directory
|
|
117095
117969
|
});
|
|
117096
|
-
const timeoutPromise = new Promise((
|
|
117970
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
117097
117971
|
const result = await Promise.race([
|
|
117098
117972
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
117099
117973
|
timeoutPromise
|
|
@@ -117336,7 +118210,7 @@ var pkg_audit = createSwarmTool({
|
|
|
117336
118210
|
init_zod();
|
|
117337
118211
|
init_manager2();
|
|
117338
118212
|
import * as fs101 from "node:fs";
|
|
117339
|
-
import * as
|
|
118213
|
+
import * as path140 from "node:path";
|
|
117340
118214
|
init_utils();
|
|
117341
118215
|
init_create_tool();
|
|
117342
118216
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -117459,7 +118333,7 @@ function isScaffoldFile(filePath) {
|
|
|
117459
118333
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
117460
118334
|
return true;
|
|
117461
118335
|
}
|
|
117462
|
-
const filename =
|
|
118336
|
+
const filename = path140.basename(filePath);
|
|
117463
118337
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
117464
118338
|
return true;
|
|
117465
118339
|
}
|
|
@@ -117476,7 +118350,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
117476
118350
|
if (regex.test(normalizedPath)) {
|
|
117477
118351
|
return true;
|
|
117478
118352
|
}
|
|
117479
|
-
const filename =
|
|
118353
|
+
const filename = path140.basename(filePath);
|
|
117480
118354
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
117481
118355
|
if (filenameRegex.test(filename)) {
|
|
117482
118356
|
return true;
|
|
@@ -117485,7 +118359,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
117485
118359
|
return false;
|
|
117486
118360
|
}
|
|
117487
118361
|
function isParserSupported(filePath) {
|
|
117488
|
-
const ext =
|
|
118362
|
+
const ext = path140.extname(filePath).toLowerCase();
|
|
117489
118363
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
117490
118364
|
}
|
|
117491
118365
|
function isPlanFile(filePath) {
|
|
@@ -117732,9 +118606,9 @@ async function placeholderScan(input, directory) {
|
|
|
117732
118606
|
let filesScanned = 0;
|
|
117733
118607
|
const filesWithFindings = new Set;
|
|
117734
118608
|
for (const filePath of changed_files) {
|
|
117735
|
-
const fullPath =
|
|
117736
|
-
const resolvedDirectory =
|
|
117737
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
118609
|
+
const fullPath = path140.isAbsolute(filePath) ? filePath : path140.resolve(directory, filePath);
|
|
118610
|
+
const resolvedDirectory = path140.resolve(directory);
|
|
118611
|
+
if (!fullPath.startsWith(resolvedDirectory + path140.sep) && fullPath !== resolvedDirectory) {
|
|
117738
118612
|
continue;
|
|
117739
118613
|
}
|
|
117740
118614
|
if (!fs101.existsSync(fullPath)) {
|
|
@@ -117743,7 +118617,7 @@ async function placeholderScan(input, directory) {
|
|
|
117743
118617
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
117744
118618
|
continue;
|
|
117745
118619
|
}
|
|
117746
|
-
const relativeFilePath =
|
|
118620
|
+
const relativeFilePath = path140.relative(directory, fullPath).replace(/\\/g, "/");
|
|
117747
118621
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
117748
118622
|
continue;
|
|
117749
118623
|
}
|
|
@@ -117816,7 +118690,7 @@ var placeholder_scan = createSwarmTool({
|
|
|
117816
118690
|
|
|
117817
118691
|
// src/tools/pre-check-batch.ts
|
|
117818
118692
|
import * as fs105 from "node:fs";
|
|
117819
|
-
import * as
|
|
118693
|
+
import * as path144 from "node:path";
|
|
117820
118694
|
init_zod();
|
|
117821
118695
|
init_manager2();
|
|
117822
118696
|
init_utils();
|
|
@@ -117957,7 +118831,7 @@ init_zod();
|
|
|
117957
118831
|
init_manager2();
|
|
117958
118832
|
init_detector();
|
|
117959
118833
|
import * as fs104 from "node:fs";
|
|
117960
|
-
import * as
|
|
118834
|
+
import * as path143 from "node:path";
|
|
117961
118835
|
import { extname as extname20 } from "node:path";
|
|
117962
118836
|
|
|
117963
118837
|
// src/sast/rules/c.ts
|
|
@@ -118673,7 +119547,7 @@ function executeRulesSync(filePath, content, language) {
|
|
|
118673
119547
|
// src/sast/semgrep.ts
|
|
118674
119548
|
import * as child_process9 from "node:child_process";
|
|
118675
119549
|
import * as fs102 from "node:fs";
|
|
118676
|
-
import * as
|
|
119550
|
+
import * as path141 from "node:path";
|
|
118677
119551
|
var semgrepAvailableCache = null;
|
|
118678
119552
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
118679
119553
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
@@ -118754,7 +119628,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
118754
119628
|
}
|
|
118755
119629
|
}
|
|
118756
119630
|
async function executeWithTimeout(command, args2, options) {
|
|
118757
|
-
return new Promise((
|
|
119631
|
+
return new Promise((resolve48) => {
|
|
118758
119632
|
const child = child_process9.spawn(command, args2, {
|
|
118759
119633
|
shell: false,
|
|
118760
119634
|
cwd: options.cwd
|
|
@@ -118763,7 +119637,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
118763
119637
|
let stderr = "";
|
|
118764
119638
|
const timeout = setTimeout(() => {
|
|
118765
119639
|
child.kill("SIGTERM");
|
|
118766
|
-
|
|
119640
|
+
resolve48({
|
|
118767
119641
|
stdout,
|
|
118768
119642
|
stderr: "Process timed out",
|
|
118769
119643
|
exitCode: 124
|
|
@@ -118777,7 +119651,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
118777
119651
|
});
|
|
118778
119652
|
child.on("close", (code) => {
|
|
118779
119653
|
clearTimeout(timeout);
|
|
118780
|
-
|
|
119654
|
+
resolve48({
|
|
118781
119655
|
stdout,
|
|
118782
119656
|
stderr,
|
|
118783
119657
|
exitCode: code ?? 0
|
|
@@ -118785,7 +119659,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
118785
119659
|
});
|
|
118786
119660
|
child.on("error", (err2) => {
|
|
118787
119661
|
clearTimeout(timeout);
|
|
118788
|
-
|
|
119662
|
+
resolve48({
|
|
118789
119663
|
stdout,
|
|
118790
119664
|
stderr: err2.message,
|
|
118791
119665
|
exitCode: 1
|
|
@@ -118860,7 +119734,7 @@ async function runSemgrep(options) {
|
|
|
118860
119734
|
}
|
|
118861
119735
|
function getRulesDirectory(projectRoot) {
|
|
118862
119736
|
if (projectRoot) {
|
|
118863
|
-
return
|
|
119737
|
+
return path141.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
118864
119738
|
}
|
|
118865
119739
|
return DEFAULT_RULES_DIR;
|
|
118866
119740
|
}
|
|
@@ -118881,24 +119755,24 @@ init_create_tool();
|
|
|
118881
119755
|
init_utils2();
|
|
118882
119756
|
import * as crypto11 from "node:crypto";
|
|
118883
119757
|
import * as fs103 from "node:fs";
|
|
118884
|
-
import * as
|
|
119758
|
+
import * as path142 from "node:path";
|
|
118885
119759
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
118886
119760
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
118887
119761
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
118888
119762
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
118889
119763
|
function normalizeFindingPath(directory, file3) {
|
|
118890
|
-
const resolved =
|
|
118891
|
-
const rel =
|
|
119764
|
+
const resolved = path142.isAbsolute(file3) ? file3 : path142.resolve(directory, file3);
|
|
119765
|
+
const rel = path142.relative(path142.resolve(directory), resolved);
|
|
118892
119766
|
return rel.replace(/\\/g, "/");
|
|
118893
119767
|
}
|
|
118894
119768
|
function baselineRelPath(phase) {
|
|
118895
|
-
return
|
|
119769
|
+
return path142.join("evidence", String(phase), "sast-baseline.json");
|
|
118896
119770
|
}
|
|
118897
119771
|
function tempRelPath(phase) {
|
|
118898
|
-
return
|
|
119772
|
+
return path142.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
118899
119773
|
}
|
|
118900
119774
|
function lockRelPath(phase) {
|
|
118901
|
-
return
|
|
119775
|
+
return path142.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
118902
119776
|
}
|
|
118903
119777
|
function getLine(lines, idx) {
|
|
118904
119778
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -118984,7 +119858,7 @@ async function acquireLock2(lockPath) {
|
|
|
118984
119858
|
};
|
|
118985
119859
|
} catch {
|
|
118986
119860
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
118987
|
-
await new Promise((
|
|
119861
|
+
await new Promise((resolve49) => setTimeout(resolve49, LOCK_RETRY_DELAYS_MS[attempt]));
|
|
118988
119862
|
}
|
|
118989
119863
|
}
|
|
118990
119864
|
}
|
|
@@ -119019,8 +119893,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
119019
119893
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
119020
119894
|
};
|
|
119021
119895
|
}
|
|
119022
|
-
fs103.mkdirSync(
|
|
119023
|
-
fs103.mkdirSync(
|
|
119896
|
+
fs103.mkdirSync(path142.dirname(baselinePath), { recursive: true });
|
|
119897
|
+
fs103.mkdirSync(path142.dirname(tempPath), { recursive: true });
|
|
119024
119898
|
const releaseLock = await acquireLock2(lockPath);
|
|
119025
119899
|
try {
|
|
119026
119900
|
let existing = null;
|
|
@@ -119293,9 +120167,9 @@ async function sastScan(input, directory, config3) {
|
|
|
119293
120167
|
_filesSkipped++;
|
|
119294
120168
|
continue;
|
|
119295
120169
|
}
|
|
119296
|
-
const resolvedPath =
|
|
119297
|
-
const resolvedDirectory =
|
|
119298
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
120170
|
+
const resolvedPath = path143.isAbsolute(filePath) ? filePath : path143.resolve(directory, filePath);
|
|
120171
|
+
const resolvedDirectory = path143.resolve(directory);
|
|
120172
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path143.sep) && resolvedPath !== resolvedDirectory) {
|
|
119299
120173
|
_filesSkipped++;
|
|
119300
120174
|
continue;
|
|
119301
120175
|
}
|
|
@@ -119610,20 +120484,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
119610
120484
|
let resolved;
|
|
119611
120485
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
119612
120486
|
if (isWinAbs) {
|
|
119613
|
-
resolved =
|
|
119614
|
-
} else if (
|
|
119615
|
-
resolved =
|
|
120487
|
+
resolved = path144.win32.resolve(inputPath);
|
|
120488
|
+
} else if (path144.isAbsolute(inputPath)) {
|
|
120489
|
+
resolved = path144.resolve(inputPath);
|
|
119616
120490
|
} else {
|
|
119617
|
-
resolved =
|
|
120491
|
+
resolved = path144.resolve(baseDir, inputPath);
|
|
119618
120492
|
}
|
|
119619
|
-
const workspaceResolved =
|
|
119620
|
-
let
|
|
120493
|
+
const workspaceResolved = path144.resolve(workspaceDir);
|
|
120494
|
+
let relative28;
|
|
119621
120495
|
if (isWinAbs) {
|
|
119622
|
-
|
|
120496
|
+
relative28 = path144.win32.relative(workspaceResolved, resolved);
|
|
119623
120497
|
} else {
|
|
119624
|
-
|
|
120498
|
+
relative28 = path144.relative(workspaceResolved, resolved);
|
|
119625
120499
|
}
|
|
119626
|
-
if (
|
|
120500
|
+
if (relative28.startsWith("..")) {
|
|
119627
120501
|
return "path traversal detected";
|
|
119628
120502
|
}
|
|
119629
120503
|
return null;
|
|
@@ -119686,7 +120560,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
119686
120560
|
if (typeof file3 !== "string") {
|
|
119687
120561
|
continue;
|
|
119688
120562
|
}
|
|
119689
|
-
const resolvedPath =
|
|
120563
|
+
const resolvedPath = path144.resolve(file3);
|
|
119690
120564
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
119691
120565
|
if (validationError) {
|
|
119692
120566
|
continue;
|
|
@@ -119843,7 +120717,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
119843
120717
|
skippedFiles++;
|
|
119844
120718
|
continue;
|
|
119845
120719
|
}
|
|
119846
|
-
const resolvedPath =
|
|
120720
|
+
const resolvedPath = path144.resolve(file3);
|
|
119847
120721
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
119848
120722
|
if (validationError) {
|
|
119849
120723
|
skippedFiles++;
|
|
@@ -119861,7 +120735,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
119861
120735
|
};
|
|
119862
120736
|
}
|
|
119863
120737
|
for (const file3 of validatedFiles) {
|
|
119864
|
-
const ext =
|
|
120738
|
+
const ext = path144.extname(file3).toLowerCase();
|
|
119865
120739
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
119866
120740
|
skippedFiles++;
|
|
119867
120741
|
continue;
|
|
@@ -120080,7 +120954,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
120080
120954
|
const preexistingFindings = [];
|
|
120081
120955
|
for (const finding of findings) {
|
|
120082
120956
|
const filePath = finding.location.file;
|
|
120083
|
-
const normalised =
|
|
120957
|
+
const normalised = path144.relative(directory, filePath).replace(/\\/g, "/");
|
|
120084
120958
|
const changedLines = changedLineRanges.get(normalised);
|
|
120085
120959
|
if (changedLines?.has(finding.location.line)) {
|
|
120086
120960
|
newFindings.push(finding);
|
|
@@ -120131,7 +121005,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
120131
121005
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
120132
121006
|
continue;
|
|
120133
121007
|
}
|
|
120134
|
-
changedFiles.push(
|
|
121008
|
+
changedFiles.push(path144.resolve(directory, file3));
|
|
120135
121009
|
}
|
|
120136
121010
|
if (changedFiles.length === 0) {
|
|
120137
121011
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -120332,9 +121206,9 @@ var pre_check_batch = createSwarmTool({
|
|
|
120332
121206
|
};
|
|
120333
121207
|
return JSON.stringify(errorResult, null, 2);
|
|
120334
121208
|
}
|
|
120335
|
-
const resolvedDirectory =
|
|
120336
|
-
const workspaceAnchor =
|
|
120337
|
-
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor +
|
|
121209
|
+
const resolvedDirectory = path144.resolve(typedArgs.directory);
|
|
121210
|
+
const workspaceAnchor = path144.resolve(directory);
|
|
121211
|
+
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path144.sep)) {
|
|
120338
121212
|
const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
|
|
120339
121213
|
const subDirResult = {
|
|
120340
121214
|
gates_passed: false,
|
|
@@ -120386,7 +121260,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
120386
121260
|
|
|
120387
121261
|
// src/tools/repo-map.ts
|
|
120388
121262
|
init_zod();
|
|
120389
|
-
import * as
|
|
121263
|
+
import * as path145 from "node:path";
|
|
120390
121264
|
init_path_security();
|
|
120391
121265
|
init_create_tool();
|
|
120392
121266
|
var VALID_ACTIONS = [
|
|
@@ -120411,7 +121285,7 @@ function validateFile(p) {
|
|
|
120411
121285
|
return "file contains control characters";
|
|
120412
121286
|
if (containsPathTraversal(p))
|
|
120413
121287
|
return "file contains path traversal";
|
|
120414
|
-
if (
|
|
121288
|
+
if (path145.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
120415
121289
|
return "file must be a workspace-relative path, not absolute";
|
|
120416
121290
|
}
|
|
120417
121291
|
return null;
|
|
@@ -120434,8 +121308,8 @@ function ok(action, payload) {
|
|
|
120434
121308
|
}
|
|
120435
121309
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
120436
121310
|
const normalized = input.replace(/\\/g, "/");
|
|
120437
|
-
if (
|
|
120438
|
-
const rel =
|
|
121311
|
+
if (path145.isAbsolute(normalized)) {
|
|
121312
|
+
const rel = path145.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
120439
121313
|
return normalizeGraphPath2(rel);
|
|
120440
121314
|
}
|
|
120441
121315
|
return normalizeGraphPath2(normalized);
|
|
@@ -120581,7 +121455,7 @@ var repo_map = createSwarmTool({
|
|
|
120581
121455
|
init_zod();
|
|
120582
121456
|
init_create_tool();
|
|
120583
121457
|
import * as fs106 from "node:fs";
|
|
120584
|
-
import * as
|
|
121458
|
+
import * as path146 from "node:path";
|
|
120585
121459
|
var SPEC_FILE = ".swarm/spec.md";
|
|
120586
121460
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
120587
121461
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -120650,7 +121524,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120650
121524
|
return [];
|
|
120651
121525
|
}
|
|
120652
121526
|
for (const entry of entries) {
|
|
120653
|
-
const entryPath =
|
|
121527
|
+
const entryPath = path146.join(evidenceDir, entry);
|
|
120654
121528
|
try {
|
|
120655
121529
|
const stat9 = fs106.statSync(entryPath);
|
|
120656
121530
|
if (!stat9.isDirectory()) {
|
|
@@ -120666,11 +121540,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120666
121540
|
if (entryPhase !== String(phase)) {
|
|
120667
121541
|
continue;
|
|
120668
121542
|
}
|
|
120669
|
-
const evidenceFilePath =
|
|
121543
|
+
const evidenceFilePath = path146.join(entryPath, "evidence.json");
|
|
120670
121544
|
try {
|
|
120671
|
-
const resolvedPath =
|
|
120672
|
-
const evidenceDirResolved =
|
|
120673
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
121545
|
+
const resolvedPath = path146.resolve(evidenceFilePath);
|
|
121546
|
+
const evidenceDirResolved = path146.resolve(evidenceDir);
|
|
121547
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path146.sep)) {
|
|
120674
121548
|
continue;
|
|
120675
121549
|
}
|
|
120676
121550
|
const stat9 = fs106.lstatSync(evidenceFilePath);
|
|
@@ -120704,7 +121578,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120704
121578
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
120705
121579
|
for (const file3 of diffEntry.files_changed) {
|
|
120706
121580
|
if (typeof file3 === "string") {
|
|
120707
|
-
touchedFiles.add(
|
|
121581
|
+
touchedFiles.add(path146.resolve(cwd, file3));
|
|
120708
121582
|
}
|
|
120709
121583
|
}
|
|
120710
121584
|
}
|
|
@@ -120717,8 +121591,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120717
121591
|
}
|
|
120718
121592
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
120719
121593
|
try {
|
|
120720
|
-
const resolvedPath =
|
|
120721
|
-
const cwdResolved =
|
|
121594
|
+
const resolvedPath = path146.resolve(filePath);
|
|
121595
|
+
const cwdResolved = path146.resolve(cwd);
|
|
120722
121596
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
120723
121597
|
return false;
|
|
120724
121598
|
}
|
|
@@ -120852,7 +121726,7 @@ var req_coverage = createSwarmTool({
|
|
|
120852
121726
|
}, null, 2);
|
|
120853
121727
|
}
|
|
120854
121728
|
const cwd = inputDirectory || directory;
|
|
120855
|
-
const specPath =
|
|
121729
|
+
const specPath = path146.join(cwd, SPEC_FILE);
|
|
120856
121730
|
let specContent;
|
|
120857
121731
|
try {
|
|
120858
121732
|
specContent = fs106.readFileSync(specPath, "utf-8");
|
|
@@ -120879,7 +121753,7 @@ var req_coverage = createSwarmTool({
|
|
|
120879
121753
|
message: "No FR requirements found in spec.md"
|
|
120880
121754
|
}, null, 2);
|
|
120881
121755
|
}
|
|
120882
|
-
const evidenceDir =
|
|
121756
|
+
const evidenceDir = path146.join(cwd, EVIDENCE_DIR4);
|
|
120883
121757
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
120884
121758
|
const analyzedRequirements = [];
|
|
120885
121759
|
let coveredCount = 0;
|
|
@@ -120905,7 +121779,7 @@ var req_coverage = createSwarmTool({
|
|
|
120905
121779
|
requirements: analyzedRequirements
|
|
120906
121780
|
};
|
|
120907
121781
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
120908
|
-
const reportPath =
|
|
121782
|
+
const reportPath = path146.join(evidenceDir, reportFilename);
|
|
120909
121783
|
try {
|
|
120910
121784
|
if (!fs106.existsSync(evidenceDir)) {
|
|
120911
121785
|
fs106.mkdirSync(evidenceDir, { recursive: true });
|
|
@@ -120995,7 +121869,7 @@ init_qa_gate_profile();
|
|
|
120995
121869
|
init_file_locks();
|
|
120996
121870
|
import * as crypto12 from "node:crypto";
|
|
120997
121871
|
import * as fs107 from "node:fs";
|
|
120998
|
-
import * as
|
|
121872
|
+
import * as path147 from "node:path";
|
|
120999
121873
|
init_ledger();
|
|
121000
121874
|
init_manager();
|
|
121001
121875
|
init_state();
|
|
@@ -121076,8 +121950,8 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121076
121950
|
};
|
|
121077
121951
|
}
|
|
121078
121952
|
if (args2.working_directory && fallbackDir) {
|
|
121079
|
-
const resolvedTarget =
|
|
121080
|
-
const resolvedRoot =
|
|
121953
|
+
const resolvedTarget = path147.resolve(args2.working_directory);
|
|
121954
|
+
const resolvedRoot = path147.resolve(fallbackDir);
|
|
121081
121955
|
let fallbackExists = false;
|
|
121082
121956
|
try {
|
|
121083
121957
|
fs107.accessSync(resolvedRoot, fs107.constants.F_OK);
|
|
@@ -121086,7 +121960,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121086
121960
|
fallbackExists = false;
|
|
121087
121961
|
}
|
|
121088
121962
|
if (fallbackExists) {
|
|
121089
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
121963
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path147.sep);
|
|
121090
121964
|
if (isSubdirectory) {
|
|
121091
121965
|
return {
|
|
121092
121966
|
success: false,
|
|
@@ -121102,7 +121976,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121102
121976
|
let specMtime;
|
|
121103
121977
|
let specHash;
|
|
121104
121978
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
121105
|
-
const specPath =
|
|
121979
|
+
const specPath = path147.join(targetWorkspace, ".swarm", "spec.md");
|
|
121106
121980
|
try {
|
|
121107
121981
|
const stat9 = await fs107.promises.stat(specPath);
|
|
121108
121982
|
specMtime = stat9.mtime.toISOString();
|
|
@@ -121118,7 +121992,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121118
121992
|
}
|
|
121119
121993
|
}
|
|
121120
121994
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
121121
|
-
const contextPath =
|
|
121995
|
+
const contextPath = path147.join(targetWorkspace, ".swarm", "context.md");
|
|
121122
121996
|
let contextContent = "";
|
|
121123
121997
|
try {
|
|
121124
121998
|
contextContent = await fs107.promises.readFile(contextPath, "utf8");
|
|
@@ -121408,7 +122282,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121408
122282
|
}
|
|
121409
122283
|
await writeCheckpoint(dir).catch(() => {});
|
|
121410
122284
|
try {
|
|
121411
|
-
const markerPath =
|
|
122285
|
+
const markerPath = path147.join(dir, ".swarm", ".plan-write-marker");
|
|
121412
122286
|
const marker = JSON.stringify({
|
|
121413
122287
|
source: "save_plan",
|
|
121414
122288
|
timestamp: new Date().toISOString(),
|
|
@@ -121431,7 +122305,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121431
122305
|
return {
|
|
121432
122306
|
success: true,
|
|
121433
122307
|
message: "Plan saved successfully",
|
|
121434
|
-
plan_path:
|
|
122308
|
+
plan_path: path147.join(dir, ".swarm", "plan.json"),
|
|
121435
122309
|
phases_count: plan.phases.length,
|
|
121436
122310
|
tasks_count: tasksCount,
|
|
121437
122311
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -121498,7 +122372,7 @@ var save_plan = createSwarmTool({
|
|
|
121498
122372
|
init_zod();
|
|
121499
122373
|
init_manager2();
|
|
121500
122374
|
import * as fs108 from "node:fs";
|
|
121501
|
-
import * as
|
|
122375
|
+
import * as path148 from "node:path";
|
|
121502
122376
|
|
|
121503
122377
|
// src/sbom/detectors/index.ts
|
|
121504
122378
|
init_utils();
|
|
@@ -122348,7 +123222,7 @@ function findManifestFiles(rootDir) {
|
|
|
122348
123222
|
try {
|
|
122349
123223
|
const entries = fs108.readdirSync(dir, { withFileTypes: true });
|
|
122350
123224
|
for (const entry of entries) {
|
|
122351
|
-
const fullPath =
|
|
123225
|
+
const fullPath = path148.join(dir, entry.name);
|
|
122352
123226
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
122353
123227
|
continue;
|
|
122354
123228
|
}
|
|
@@ -122357,7 +123231,7 @@ function findManifestFiles(rootDir) {
|
|
|
122357
123231
|
} else if (entry.isFile()) {
|
|
122358
123232
|
for (const pattern of patterns) {
|
|
122359
123233
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
122360
|
-
manifestFiles.push(
|
|
123234
|
+
manifestFiles.push(path148.relative(rootDir, fullPath));
|
|
122361
123235
|
break;
|
|
122362
123236
|
}
|
|
122363
123237
|
}
|
|
@@ -122375,11 +123249,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
122375
123249
|
try {
|
|
122376
123250
|
const entries = fs108.readdirSync(dir, { withFileTypes: true });
|
|
122377
123251
|
for (const entry of entries) {
|
|
122378
|
-
const fullPath =
|
|
123252
|
+
const fullPath = path148.join(dir, entry.name);
|
|
122379
123253
|
if (entry.isFile()) {
|
|
122380
123254
|
for (const pattern of patterns) {
|
|
122381
123255
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
122382
|
-
found.push(
|
|
123256
|
+
found.push(path148.relative(workingDir, fullPath));
|
|
122383
123257
|
break;
|
|
122384
123258
|
}
|
|
122385
123259
|
}
|
|
@@ -122392,11 +123266,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
122392
123266
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
122393
123267
|
const dirs = new Set;
|
|
122394
123268
|
for (const file3 of changedFiles) {
|
|
122395
|
-
let currentDir =
|
|
123269
|
+
let currentDir = path148.dirname(file3);
|
|
122396
123270
|
while (true) {
|
|
122397
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
122398
|
-
dirs.add(
|
|
122399
|
-
const parent =
|
|
123271
|
+
if (currentDir && currentDir !== "." && currentDir !== path148.sep) {
|
|
123272
|
+
dirs.add(path148.join(workingDir, currentDir));
|
|
123273
|
+
const parent = path148.dirname(currentDir);
|
|
122400
123274
|
if (parent === currentDir)
|
|
122401
123275
|
break;
|
|
122402
123276
|
currentDir = parent;
|
|
@@ -122480,7 +123354,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122480
123354
|
const changedFiles = obj.changed_files;
|
|
122481
123355
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
122482
123356
|
const workingDir = directory;
|
|
122483
|
-
const outputDir =
|
|
123357
|
+
const outputDir = path148.isAbsolute(relativeOutputDir) ? relativeOutputDir : path148.join(workingDir, relativeOutputDir);
|
|
122484
123358
|
let manifestFiles = [];
|
|
122485
123359
|
if (scope === "all") {
|
|
122486
123360
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -122503,7 +123377,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122503
123377
|
const processedFiles = [];
|
|
122504
123378
|
for (const manifestFile of manifestFiles) {
|
|
122505
123379
|
try {
|
|
122506
|
-
const fullPath =
|
|
123380
|
+
const fullPath = path148.isAbsolute(manifestFile) ? manifestFile : path148.join(workingDir, manifestFile);
|
|
122507
123381
|
if (!fs108.existsSync(fullPath)) {
|
|
122508
123382
|
continue;
|
|
122509
123383
|
}
|
|
@@ -122520,7 +123394,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122520
123394
|
const bom = generateCycloneDX(allComponents);
|
|
122521
123395
|
const bomJson = serializeCycloneDX(bom);
|
|
122522
123396
|
const filename = generateSbomFilename();
|
|
122523
|
-
const outputPath =
|
|
123397
|
+
const outputPath = path148.join(outputDir, filename);
|
|
122524
123398
|
fs108.writeFileSync(outputPath, bomJson, "utf-8");
|
|
122525
123399
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
122526
123400
|
try {
|
|
@@ -122565,7 +123439,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122565
123439
|
init_zod();
|
|
122566
123440
|
init_create_tool();
|
|
122567
123441
|
import * as fs109 from "node:fs";
|
|
122568
|
-
import * as
|
|
123442
|
+
import * as path149 from "node:path";
|
|
122569
123443
|
var SPEC_CANDIDATES = [
|
|
122570
123444
|
"openapi.json",
|
|
122571
123445
|
"openapi.yaml",
|
|
@@ -122597,12 +123471,12 @@ function normalizePath5(p) {
|
|
|
122597
123471
|
}
|
|
122598
123472
|
function discoverSpecFile(cwd, specFileArg) {
|
|
122599
123473
|
if (specFileArg) {
|
|
122600
|
-
const resolvedPath =
|
|
122601
|
-
const normalizedCwd = cwd.endsWith(
|
|
123474
|
+
const resolvedPath = path149.resolve(cwd, specFileArg);
|
|
123475
|
+
const normalizedCwd = cwd.endsWith(path149.sep) ? cwd : cwd + path149.sep;
|
|
122602
123476
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
122603
123477
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
122604
123478
|
}
|
|
122605
|
-
const ext =
|
|
123479
|
+
const ext = path149.extname(resolvedPath).toLowerCase();
|
|
122606
123480
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
122607
123481
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
122608
123482
|
}
|
|
@@ -122616,7 +123490,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
122616
123490
|
return resolvedPath;
|
|
122617
123491
|
}
|
|
122618
123492
|
for (const candidate of SPEC_CANDIDATES) {
|
|
122619
|
-
const candidatePath =
|
|
123493
|
+
const candidatePath = path149.resolve(cwd, candidate);
|
|
122620
123494
|
if (fs109.existsSync(candidatePath)) {
|
|
122621
123495
|
const stats = fs109.statSync(candidatePath);
|
|
122622
123496
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -122628,7 +123502,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
122628
123502
|
}
|
|
122629
123503
|
function parseSpec(specFile) {
|
|
122630
123504
|
const content = fs109.readFileSync(specFile, "utf-8");
|
|
122631
|
-
const ext =
|
|
123505
|
+
const ext = path149.extname(specFile).toLowerCase();
|
|
122632
123506
|
if (ext === ".json") {
|
|
122633
123507
|
return parseJsonSpec(content);
|
|
122634
123508
|
}
|
|
@@ -122704,7 +123578,7 @@ function extractRoutes(cwd) {
|
|
|
122704
123578
|
return;
|
|
122705
123579
|
}
|
|
122706
123580
|
for (const entry of entries) {
|
|
122707
|
-
const fullPath =
|
|
123581
|
+
const fullPath = path149.join(dir, entry.name);
|
|
122708
123582
|
if (entry.isSymbolicLink()) {
|
|
122709
123583
|
continue;
|
|
122710
123584
|
}
|
|
@@ -122714,7 +123588,7 @@ function extractRoutes(cwd) {
|
|
|
122714
123588
|
}
|
|
122715
123589
|
walkDir(fullPath);
|
|
122716
123590
|
} else if (entry.isFile()) {
|
|
122717
|
-
const ext =
|
|
123591
|
+
const ext = path149.extname(entry.name).toLowerCase();
|
|
122718
123592
|
const baseName = entry.name.toLowerCase();
|
|
122719
123593
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
122720
123594
|
continue;
|
|
@@ -122883,7 +123757,7 @@ init_bun_compat();
|
|
|
122883
123757
|
init_path_security();
|
|
122884
123758
|
init_create_tool();
|
|
122885
123759
|
import * as fs110 from "node:fs";
|
|
122886
|
-
import * as
|
|
123760
|
+
import * as path150 from "node:path";
|
|
122887
123761
|
var DEFAULT_MAX_RESULTS = 100;
|
|
122888
123762
|
var DEFAULT_MAX_LINES = 200;
|
|
122889
123763
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -122906,24 +123780,24 @@ function matchesGlobs(filePath, globs) {
|
|
|
122906
123780
|
return true;
|
|
122907
123781
|
return globs.some((glob) => globMatch(glob, filePath));
|
|
122908
123782
|
}
|
|
122909
|
-
var
|
|
122910
|
-
function
|
|
123783
|
+
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
123784
|
+
function containsWindowsAttacks4(str) {
|
|
122911
123785
|
if (/:[^\\/]/.test(str))
|
|
122912
123786
|
return true;
|
|
122913
123787
|
const parts2 = str.split(/[/\\]/);
|
|
122914
123788
|
for (const part of parts2) {
|
|
122915
|
-
if (
|
|
123789
|
+
if (WINDOWS_RESERVED_NAMES4.test(part))
|
|
122916
123790
|
return true;
|
|
122917
123791
|
}
|
|
122918
123792
|
return false;
|
|
122919
123793
|
}
|
|
122920
123794
|
function isPathInWorkspace3(filePath, workspace) {
|
|
122921
123795
|
try {
|
|
122922
|
-
const resolvedPath =
|
|
123796
|
+
const resolvedPath = path150.resolve(workspace, filePath);
|
|
122923
123797
|
const realWorkspace = fs110.realpathSync(workspace);
|
|
122924
123798
|
const realResolvedPath = fs110.realpathSync(resolvedPath);
|
|
122925
|
-
const relativePath =
|
|
122926
|
-
if (relativePath.startsWith("..") ||
|
|
123799
|
+
const relativePath = path150.relative(realWorkspace, realResolvedPath);
|
|
123800
|
+
if (relativePath.startsWith("..") || path150.isAbsolute(relativePath)) {
|
|
122927
123801
|
return false;
|
|
122928
123802
|
}
|
|
122929
123803
|
return true;
|
|
@@ -122936,11 +123810,11 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
122936
123810
|
}
|
|
122937
123811
|
function findRgInEnvPath() {
|
|
122938
123812
|
const searchPath = process.env.PATH ?? "";
|
|
122939
|
-
for (const dir of searchPath.split(
|
|
123813
|
+
for (const dir of searchPath.split(path150.delimiter)) {
|
|
122940
123814
|
if (!dir)
|
|
122941
123815
|
continue;
|
|
122942
123816
|
const isWindows = process.platform === "win32";
|
|
122943
|
-
const candidate =
|
|
123817
|
+
const candidate = path150.join(dir, isWindows ? "rg.exe" : "rg");
|
|
122944
123818
|
if (fs110.existsSync(candidate))
|
|
122945
123819
|
return candidate;
|
|
122946
123820
|
}
|
|
@@ -122995,7 +123869,7 @@ async function ripgrepSearch(opts) {
|
|
|
122995
123869
|
stderr: "pipe",
|
|
122996
123870
|
cwd: opts.workspace
|
|
122997
123871
|
});
|
|
122998
|
-
const timeout = new Promise((
|
|
123872
|
+
const timeout = new Promise((resolve55) => setTimeout(() => resolve55("timeout"), REGEX_TIMEOUT_MS));
|
|
122999
123873
|
const exitPromise = proc.exited;
|
|
123000
123874
|
const result = await Promise.race([exitPromise, timeout]);
|
|
123001
123875
|
if (result === "timeout") {
|
|
@@ -123070,8 +123944,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
123070
123944
|
try {
|
|
123071
123945
|
const entries = fs110.readdirSync(dir, { withFileTypes: true });
|
|
123072
123946
|
for (const entry of entries) {
|
|
123073
|
-
const fullPath =
|
|
123074
|
-
const relativePath =
|
|
123947
|
+
const fullPath = path150.join(dir, entry.name);
|
|
123948
|
+
const relativePath = path150.relative(workspace, fullPath);
|
|
123075
123949
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
123076
123950
|
continue;
|
|
123077
123951
|
}
|
|
@@ -123112,7 +123986,7 @@ async function fallbackSearch(opts) {
|
|
|
123112
123986
|
const matches = [];
|
|
123113
123987
|
let total = 0;
|
|
123114
123988
|
for (const file3 of files) {
|
|
123115
|
-
const fullPath =
|
|
123989
|
+
const fullPath = path150.join(opts.workspace, file3);
|
|
123116
123990
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
123117
123991
|
continue;
|
|
123118
123992
|
}
|
|
@@ -123225,14 +124099,14 @@ var search = createSwarmTool({
|
|
|
123225
124099
|
message: "Exclude pattern contains path traversal sequence"
|
|
123226
124100
|
}, null, 2);
|
|
123227
124101
|
}
|
|
123228
|
-
if (include &&
|
|
124102
|
+
if (include && containsWindowsAttacks4(include)) {
|
|
123229
124103
|
return JSON.stringify({
|
|
123230
124104
|
error: true,
|
|
123231
124105
|
type: "path-escape",
|
|
123232
124106
|
message: "Include pattern contains invalid Windows-specific sequence"
|
|
123233
124107
|
}, null, 2);
|
|
123234
124108
|
}
|
|
123235
|
-
if (exclude &&
|
|
124109
|
+
if (exclude && containsWindowsAttacks4(exclude)) {
|
|
123236
124110
|
return JSON.stringify({
|
|
123237
124111
|
error: true,
|
|
123238
124112
|
type: "path-escape",
|
|
@@ -123525,7 +124399,7 @@ init_config();
|
|
|
123525
124399
|
init_schema();
|
|
123526
124400
|
init_create_tool();
|
|
123527
124401
|
import { mkdir as mkdir24, rename as rename10, writeFile as writeFile19 } from "node:fs/promises";
|
|
123528
|
-
import * as
|
|
124402
|
+
import * as path151 from "node:path";
|
|
123529
124403
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
123530
124404
|
var spec_write = createSwarmTool({
|
|
123531
124405
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -123566,8 +124440,8 @@ var spec_write = createSwarmTool({
|
|
|
123566
124440
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
123567
124441
|
}, null, 2);
|
|
123568
124442
|
}
|
|
123569
|
-
const target =
|
|
123570
|
-
await mkdir24(
|
|
124443
|
+
const target = path151.join(directory, ".swarm", "spec.md");
|
|
124444
|
+
await mkdir24(path151.dirname(target), { recursive: true });
|
|
123571
124445
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
123572
124446
|
let finalContent = content;
|
|
123573
124447
|
if (mode === "append") {
|
|
@@ -123596,14 +124470,14 @@ ${content}
|
|
|
123596
124470
|
init_zod();
|
|
123597
124471
|
init_loader();
|
|
123598
124472
|
import {
|
|
123599
|
-
existsSync as
|
|
123600
|
-
mkdirSync as
|
|
123601
|
-
readFileSync as
|
|
123602
|
-
renameSync as
|
|
123603
|
-
unlinkSync as
|
|
123604
|
-
writeFileSync as
|
|
124473
|
+
existsSync as existsSync85,
|
|
124474
|
+
mkdirSync as mkdirSync36,
|
|
124475
|
+
readFileSync as readFileSync72,
|
|
124476
|
+
renameSync as renameSync22,
|
|
124477
|
+
unlinkSync as unlinkSync20,
|
|
124478
|
+
writeFileSync as writeFileSync30
|
|
123605
124479
|
} from "node:fs";
|
|
123606
|
-
import
|
|
124480
|
+
import path152 from "node:path";
|
|
123607
124481
|
init_create_tool();
|
|
123608
124482
|
init_resolve_working_directory();
|
|
123609
124483
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -123733,9 +124607,9 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
123733
124607
|
}
|
|
123734
124608
|
});
|
|
123735
124609
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
123736
|
-
const mutationGatePath =
|
|
124610
|
+
const mutationGatePath = path152.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
123737
124611
|
try {
|
|
123738
|
-
const raw =
|
|
124612
|
+
const raw = readFileSync72(mutationGatePath, "utf-8");
|
|
123739
124613
|
const parsed = JSON.parse(raw);
|
|
123740
124614
|
const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
|
|
123741
124615
|
if (!gateEntry) {
|
|
@@ -123795,9 +124669,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
123795
124669
|
}
|
|
123796
124670
|
}
|
|
123797
124671
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
123798
|
-
const evidenceDir =
|
|
123799
|
-
|
|
123800
|
-
const evidenceFile =
|
|
124672
|
+
const evidenceDir = path152.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
124673
|
+
mkdirSync36(evidenceDir, { recursive: true });
|
|
124674
|
+
const evidenceFile = path152.join(evidenceDir, "phase-council.json");
|
|
123801
124675
|
const evidenceBundle = {
|
|
123802
124676
|
entries: [
|
|
123803
124677
|
{
|
|
@@ -123830,11 +124704,11 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
|
123830
124704
|
};
|
|
123831
124705
|
const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
|
|
123832
124706
|
try {
|
|
123833
|
-
|
|
123834
|
-
|
|
124707
|
+
writeFileSync30(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
124708
|
+
renameSync22(tempFile, evidenceFile);
|
|
123835
124709
|
} finally {
|
|
123836
|
-
if (
|
|
123837
|
-
|
|
124710
|
+
if (existsSync85(tempFile)) {
|
|
124711
|
+
unlinkSync20(tempFile);
|
|
123838
124712
|
}
|
|
123839
124713
|
}
|
|
123840
124714
|
}
|
|
@@ -123859,28 +124733,28 @@ init_zod();
|
|
|
123859
124733
|
init_path_security();
|
|
123860
124734
|
init_create_tool();
|
|
123861
124735
|
import * as fs111 from "node:fs";
|
|
123862
|
-
import * as
|
|
123863
|
-
var
|
|
123864
|
-
function
|
|
124736
|
+
import * as path153 from "node:path";
|
|
124737
|
+
var WINDOWS_RESERVED_NAMES5 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
124738
|
+
function containsWindowsAttacks5(str) {
|
|
123865
124739
|
if (/:[^\\/]/.test(str))
|
|
123866
124740
|
return true;
|
|
123867
124741
|
const parts2 = str.split(/[/\\]/);
|
|
123868
124742
|
for (const part of parts2) {
|
|
123869
|
-
if (
|
|
124743
|
+
if (WINDOWS_RESERVED_NAMES5.test(part))
|
|
123870
124744
|
return true;
|
|
123871
124745
|
}
|
|
123872
124746
|
return false;
|
|
123873
124747
|
}
|
|
123874
124748
|
function isPathInWorkspace4(filePath, workspace) {
|
|
123875
124749
|
try {
|
|
123876
|
-
const resolvedPath =
|
|
124750
|
+
const resolvedPath = path153.resolve(workspace, filePath);
|
|
123877
124751
|
if (!fs111.existsSync(resolvedPath)) {
|
|
123878
124752
|
return true;
|
|
123879
124753
|
}
|
|
123880
124754
|
const realWorkspace = fs111.realpathSync(workspace);
|
|
123881
124755
|
const realResolvedPath = fs111.realpathSync(resolvedPath);
|
|
123882
|
-
const relativePath =
|
|
123883
|
-
if (relativePath.startsWith("..") ||
|
|
124756
|
+
const relativePath = path153.relative(realWorkspace, realResolvedPath);
|
|
124757
|
+
if (relativePath.startsWith("..") || path153.isAbsolute(relativePath)) {
|
|
123884
124758
|
return false;
|
|
123885
124759
|
}
|
|
123886
124760
|
return true;
|
|
@@ -123895,7 +124769,7 @@ function validateFilePath(filePath, workspace) {
|
|
|
123895
124769
|
return false;
|
|
123896
124770
|
if (containsControlChars(filePath))
|
|
123897
124771
|
return false;
|
|
123898
|
-
if (
|
|
124772
|
+
if (containsWindowsAttacks5(filePath))
|
|
123899
124773
|
return false;
|
|
123900
124774
|
return isPathInWorkspace4(filePath, workspace);
|
|
123901
124775
|
}
|
|
@@ -123908,12 +124782,12 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123908
124782
|
if (contextBefore && contextBefore.length > 0) {
|
|
123909
124783
|
for (let i2 = 0;i2 <= lines.length - contextBefore.length; i2++) {
|
|
123910
124784
|
const slice = lines.slice(i2, i2 + contextBefore.length);
|
|
123911
|
-
if (
|
|
124785
|
+
if (arraysEqual2(slice, contextBefore)) {
|
|
123912
124786
|
const afterStart = i2 + contextBefore.length;
|
|
123913
124787
|
if (contextAfter && contextAfter.length > 0) {
|
|
123914
124788
|
for (let j = afterStart;j <= lines.length - contextAfter.length; j++) {
|
|
123915
124789
|
const afterSlice = lines.slice(j, j + contextAfter.length);
|
|
123916
|
-
if (
|
|
124790
|
+
if (arraysEqual2(afterSlice, contextAfter)) {
|
|
123917
124791
|
if (j === afterStart) {
|
|
123918
124792
|
return {
|
|
123919
124793
|
startLineIndex: i2,
|
|
@@ -123926,7 +124800,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123926
124800
|
const oldContentLines = oldContent.split(`
|
|
123927
124801
|
`);
|
|
123928
124802
|
const betweenLines = lines.slice(afterStart, j);
|
|
123929
|
-
if (
|
|
124803
|
+
if (arraysEqual2(betweenLines, oldContentLines)) {
|
|
123930
124804
|
return {
|
|
123931
124805
|
startLineIndex: i2,
|
|
123932
124806
|
endLineIndex: j - 1,
|
|
@@ -123952,7 +124826,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123952
124826
|
`);
|
|
123953
124827
|
for (let k = afterStart;k <= lines.length - oldContentLines.length; k++) {
|
|
123954
124828
|
const candidate = lines.slice(k, k + oldContentLines.length);
|
|
123955
|
-
if (
|
|
124829
|
+
if (arraysEqual2(candidate, oldContentLines)) {
|
|
123956
124830
|
return {
|
|
123957
124831
|
startLineIndex: i2,
|
|
123958
124832
|
endLineIndex: k + oldContentLines.length - 1,
|
|
@@ -123976,7 +124850,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123976
124850
|
} else if (contextAfter && contextAfter.length > 0) {
|
|
123977
124851
|
for (let j = 0;j <= lines.length - contextAfter.length; j++) {
|
|
123978
124852
|
const afterSlice = lines.slice(j, j + contextAfter.length);
|
|
123979
|
-
if (
|
|
124853
|
+
if (arraysEqual2(afterSlice, contextAfter)) {
|
|
123980
124854
|
return {
|
|
123981
124855
|
startLineIndex: 0,
|
|
123982
124856
|
endLineIndex: j - 1,
|
|
@@ -123988,7 +124862,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123988
124862
|
}
|
|
123989
124863
|
return null;
|
|
123990
124864
|
}
|
|
123991
|
-
function
|
|
124865
|
+
function arraysEqual2(a, b) {
|
|
123992
124866
|
if (a.length !== b.length)
|
|
123993
124867
|
return false;
|
|
123994
124868
|
for (let i2 = 0;i2 < a.length; i2++) {
|
|
@@ -124088,7 +124962,7 @@ var suggestPatch = createSwarmTool({
|
|
|
124088
124962
|
});
|
|
124089
124963
|
continue;
|
|
124090
124964
|
}
|
|
124091
|
-
const fullPath =
|
|
124965
|
+
const fullPath = path153.resolve(directory, change.file);
|
|
124092
124966
|
if (!fs111.existsSync(fullPath)) {
|
|
124093
124967
|
errors5.push({
|
|
124094
124968
|
success: false,
|
|
@@ -124492,7 +125366,7 @@ init_zod();
|
|
|
124492
125366
|
init_manager2();
|
|
124493
125367
|
init_detector();
|
|
124494
125368
|
import * as fs112 from "node:fs";
|
|
124495
|
-
import * as
|
|
125369
|
+
import * as path154 from "node:path";
|
|
124496
125370
|
init_create_tool();
|
|
124497
125371
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
124498
125372
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -124558,7 +125432,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124558
125432
|
if (languages?.length) {
|
|
124559
125433
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
124560
125434
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
124561
|
-
const ext =
|
|
125435
|
+
const ext = path154.extname(file3.path).toLowerCase();
|
|
124562
125436
|
const langDef = getLanguageForExtension(ext);
|
|
124563
125437
|
const fileProfile = getProfileForFile(file3.path);
|
|
124564
125438
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -124571,7 +125445,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124571
125445
|
let skippedCount = 0;
|
|
124572
125446
|
for (const fileInfo of filesToCheck) {
|
|
124573
125447
|
const { path: filePath } = fileInfo;
|
|
124574
|
-
const fullPath =
|
|
125448
|
+
const fullPath = path154.isAbsolute(filePath) ? filePath : path154.join(directory, filePath);
|
|
124575
125449
|
const result = {
|
|
124576
125450
|
path: filePath,
|
|
124577
125451
|
language: "",
|
|
@@ -124620,7 +125494,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124620
125494
|
results.push(result);
|
|
124621
125495
|
continue;
|
|
124622
125496
|
}
|
|
124623
|
-
const ext =
|
|
125497
|
+
const ext = path154.extname(filePath).toLowerCase();
|
|
124624
125498
|
const langDef = getLanguageForExtension(ext);
|
|
124625
125499
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
124626
125500
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -124719,7 +125593,7 @@ init_utils();
|
|
|
124719
125593
|
init_create_tool();
|
|
124720
125594
|
init_path_security();
|
|
124721
125595
|
import * as fs113 from "node:fs";
|
|
124722
|
-
import * as
|
|
125596
|
+
import * as path155 from "node:path";
|
|
124723
125597
|
var MAX_TEXT_LENGTH = 200;
|
|
124724
125598
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
124725
125599
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -124785,9 +125659,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
124785
125659
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
124786
125660
|
}
|
|
124787
125661
|
try {
|
|
124788
|
-
const resolvedPath =
|
|
124789
|
-
const normalizedCwd =
|
|
124790
|
-
const normalizedResolved =
|
|
125662
|
+
const resolvedPath = path155.resolve(paths);
|
|
125663
|
+
const normalizedCwd = path155.resolve(cwd);
|
|
125664
|
+
const normalizedResolved = path155.resolve(resolvedPath);
|
|
124791
125665
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
124792
125666
|
return {
|
|
124793
125667
|
error: "paths must be within the current working directory",
|
|
@@ -124803,7 +125677,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
124803
125677
|
}
|
|
124804
125678
|
}
|
|
124805
125679
|
function isSupportedExtension(filePath) {
|
|
124806
|
-
const ext =
|
|
125680
|
+
const ext = path155.extname(filePath).toLowerCase();
|
|
124807
125681
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
124808
125682
|
}
|
|
124809
125683
|
function findSourceFiles3(dir, files = []) {
|
|
@@ -124818,7 +125692,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
124818
125692
|
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
124819
125693
|
continue;
|
|
124820
125694
|
}
|
|
124821
|
-
const fullPath =
|
|
125695
|
+
const fullPath = path155.join(dir, entry);
|
|
124822
125696
|
let stat9;
|
|
124823
125697
|
try {
|
|
124824
125698
|
stat9 = fs113.statSync(fullPath);
|
|
@@ -124930,7 +125804,7 @@ var todo_extract = createSwarmTool({
|
|
|
124930
125804
|
filesToScan.push(scanPath);
|
|
124931
125805
|
} else {
|
|
124932
125806
|
const errorResult = {
|
|
124933
|
-
error: `unsupported file extension: ${
|
|
125807
|
+
error: `unsupported file extension: ${path155.extname(scanPath)}`,
|
|
124934
125808
|
total: 0,
|
|
124935
125809
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
124936
125810
|
entries: []
|
|
@@ -124980,17 +125854,17 @@ init_schema();
|
|
|
124980
125854
|
init_qa_gate_profile();
|
|
124981
125855
|
init_gate_evidence();
|
|
124982
125856
|
import * as fs117 from "node:fs";
|
|
124983
|
-
import * as
|
|
125857
|
+
import * as path159 from "node:path";
|
|
124984
125858
|
|
|
124985
125859
|
// src/hooks/diff-scope.ts
|
|
124986
125860
|
init_bun_compat();
|
|
124987
125861
|
import * as fs115 from "node:fs";
|
|
124988
|
-
import * as
|
|
125862
|
+
import * as path157 from "node:path";
|
|
124989
125863
|
|
|
124990
125864
|
// src/utils/gitignore-warning.ts
|
|
124991
125865
|
init_bun_compat();
|
|
124992
125866
|
import * as fs114 from "node:fs";
|
|
124993
|
-
import * as
|
|
125867
|
+
import * as path156 from "node:path";
|
|
124994
125868
|
var _internals67 = { bunSpawn };
|
|
124995
125869
|
var _swarmGitExcludedChecked = false;
|
|
124996
125870
|
function fileCoversSwarm(content) {
|
|
@@ -125064,10 +125938,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
125064
125938
|
const excludeRelPath = excludePathRaw.trim();
|
|
125065
125939
|
if (!excludeRelPath)
|
|
125066
125940
|
return;
|
|
125067
|
-
const excludePath =
|
|
125941
|
+
const excludePath = path156.isAbsolute(excludeRelPath) ? excludeRelPath : path156.join(directory, excludeRelPath);
|
|
125068
125942
|
if (checkIgnoreExitCode !== 0) {
|
|
125069
125943
|
try {
|
|
125070
|
-
fs114.mkdirSync(
|
|
125944
|
+
fs114.mkdirSync(path156.dirname(excludePath), { recursive: true });
|
|
125071
125945
|
let existing = "";
|
|
125072
125946
|
try {
|
|
125073
125947
|
existing = fs114.readFileSync(excludePath, "utf8");
|
|
@@ -125111,7 +125985,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
125111
125985
|
var _internals68 = { bunSpawn };
|
|
125112
125986
|
function getDeclaredScope(taskId, directory) {
|
|
125113
125987
|
try {
|
|
125114
|
-
const planPath =
|
|
125988
|
+
const planPath = path157.join(directory, ".swarm", "plan.json");
|
|
125115
125989
|
if (!fs115.existsSync(planPath))
|
|
125116
125990
|
return null;
|
|
125117
125991
|
const raw = fs115.readFileSync(planPath, "utf-8");
|
|
@@ -125217,7 +126091,7 @@ init_telemetry();
|
|
|
125217
126091
|
// src/turbo/lean/task-completion.ts
|
|
125218
126092
|
init_file_locks();
|
|
125219
126093
|
import * as fs116 from "node:fs";
|
|
125220
|
-
import * as
|
|
126094
|
+
import * as path158 from "node:path";
|
|
125221
126095
|
var _internals69 = {
|
|
125222
126096
|
listActiveLocks,
|
|
125223
126097
|
verifyLeanTurboTaskCompletion
|
|
@@ -125236,7 +126110,7 @@ var TIER_3_PATTERNS = [
|
|
|
125236
126110
|
];
|
|
125237
126111
|
function matchesTier3Pattern(files) {
|
|
125238
126112
|
for (const file3 of files) {
|
|
125239
|
-
const fileName =
|
|
126113
|
+
const fileName = path158.basename(file3);
|
|
125240
126114
|
for (const pattern of TIER_3_PATTERNS) {
|
|
125241
126115
|
if (pattern.test(fileName)) {
|
|
125242
126116
|
return true;
|
|
@@ -125248,7 +126122,7 @@ function matchesTier3Pattern(files) {
|
|
|
125248
126122
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
125249
126123
|
let persisted = null;
|
|
125250
126124
|
try {
|
|
125251
|
-
const statePath =
|
|
126125
|
+
const statePath = path158.join(directory, ".swarm", "turbo-state.json");
|
|
125252
126126
|
if (!fs116.existsSync(statePath)) {
|
|
125253
126127
|
return {
|
|
125254
126128
|
ok: false,
|
|
@@ -125332,11 +126206,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
125332
126206
|
};
|
|
125333
126207
|
}
|
|
125334
126208
|
const phase = runState.phase ?? 0;
|
|
125335
|
-
const evidencePath =
|
|
125336
|
-
const expectedDir =
|
|
125337
|
-
const resolvedPath =
|
|
125338
|
-
const resolvedDir =
|
|
125339
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
126209
|
+
const evidencePath = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
126210
|
+
const expectedDir = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
126211
|
+
const resolvedPath = path158.resolve(evidencePath);
|
|
126212
|
+
const resolvedDir = path158.resolve(expectedDir);
|
|
126213
|
+
if (!resolvedPath.startsWith(resolvedDir + path158.sep) && resolvedPath !== resolvedDir) {
|
|
125340
126214
|
return {
|
|
125341
126215
|
ok: false,
|
|
125342
126216
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -125376,7 +126250,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
125376
126250
|
}
|
|
125377
126251
|
let filesTouched = [];
|
|
125378
126252
|
try {
|
|
125379
|
-
const planPath =
|
|
126253
|
+
const planPath = path158.join(directory, ".swarm", "plan.json");
|
|
125380
126254
|
const planRaw = fs116.readFileSync(planPath, "utf-8");
|
|
125381
126255
|
const plan = JSON.parse(planRaw);
|
|
125382
126256
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -125460,7 +126334,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
125460
126334
|
];
|
|
125461
126335
|
function matchesTier3Pattern2(files) {
|
|
125462
126336
|
for (const file3 of files) {
|
|
125463
|
-
const fileName =
|
|
126337
|
+
const fileName = path159.basename(file3);
|
|
125464
126338
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
125465
126339
|
if (pattern.test(fileName)) {
|
|
125466
126340
|
return true;
|
|
@@ -125499,7 +126373,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
125499
126373
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
125500
126374
|
const resolvedDir2 = workingDirectory;
|
|
125501
126375
|
try {
|
|
125502
|
-
const planPath =
|
|
126376
|
+
const planPath = path159.join(resolvedDir2, ".swarm", "plan.json");
|
|
125503
126377
|
const planRaw = fs117.readFileSync(planPath, "utf-8");
|
|
125504
126378
|
const plan = JSON.parse(planRaw);
|
|
125505
126379
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -125577,7 +126451,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
125577
126451
|
}
|
|
125578
126452
|
if (resolvedDir) {
|
|
125579
126453
|
try {
|
|
125580
|
-
const planPath =
|
|
126454
|
+
const planPath = path159.join(resolvedDir, ".swarm", "plan.json");
|
|
125581
126455
|
const planRaw = fs117.readFileSync(planPath, "utf-8");
|
|
125582
126456
|
const plan = JSON.parse(planRaw);
|
|
125583
126457
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -125813,7 +126687,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125813
126687
|
};
|
|
125814
126688
|
}
|
|
125815
126689
|
directory = resolveResult.directory;
|
|
125816
|
-
const planPath =
|
|
126690
|
+
const planPath = path159.join(directory, ".swarm", "plan.json");
|
|
125817
126691
|
if (!fs117.existsSync(planPath)) {
|
|
125818
126692
|
return {
|
|
125819
126693
|
success: false,
|
|
@@ -125822,9 +126696,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125822
126696
|
};
|
|
125823
126697
|
}
|
|
125824
126698
|
if (fallbackDir && directory !== fallbackDir) {
|
|
125825
|
-
const canonicalDir = fs117.realpathSync(
|
|
125826
|
-
const canonicalRoot = fs117.realpathSync(
|
|
125827
|
-
if (canonicalDir.startsWith(canonicalRoot +
|
|
126699
|
+
const canonicalDir = fs117.realpathSync(path159.resolve(directory));
|
|
126700
|
+
const canonicalRoot = fs117.realpathSync(path159.resolve(fallbackDir));
|
|
126701
|
+
if (canonicalDir.startsWith(canonicalRoot + path159.sep)) {
|
|
125828
126702
|
return {
|
|
125829
126703
|
success: false,
|
|
125830
126704
|
message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
|
|
@@ -125836,8 +126710,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125836
126710
|
}
|
|
125837
126711
|
if (args2.status === "in_progress") {
|
|
125838
126712
|
try {
|
|
125839
|
-
const evidencePath =
|
|
125840
|
-
fs117.mkdirSync(
|
|
126713
|
+
const evidencePath = path159.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
126714
|
+
fs117.mkdirSync(path159.dirname(evidencePath), { recursive: true });
|
|
125841
126715
|
const fd = fs117.openSync(evidencePath, "wx");
|
|
125842
126716
|
let writeOk = false;
|
|
125843
126717
|
try {
|
|
@@ -125861,7 +126735,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125861
126735
|
recoverTaskStateFromDelegations(args2.task_id, directory);
|
|
125862
126736
|
let phaseRequiresReviewer = true;
|
|
125863
126737
|
try {
|
|
125864
|
-
const planPath2 =
|
|
126738
|
+
const planPath2 = path159.join(directory, ".swarm", "plan.json");
|
|
125865
126739
|
const planRaw = fs117.readFileSync(planPath2, "utf-8");
|
|
125866
126740
|
const plan = JSON.parse(planRaw);
|
|
125867
126741
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
@@ -126090,7 +126964,7 @@ init_utils2();
|
|
|
126090
126964
|
init_redaction();
|
|
126091
126965
|
import { createHash as createHash12 } from "node:crypto";
|
|
126092
126966
|
import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
|
|
126093
|
-
import * as
|
|
126967
|
+
import * as path160 from "node:path";
|
|
126094
126968
|
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
126095
126969
|
var MAX_EVIDENCE_TEXT_LENGTH = 4000;
|
|
126096
126970
|
async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
@@ -126098,7 +126972,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
|
126098
126972
|
const capturedAt = now().toISOString();
|
|
126099
126973
|
const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
|
|
126100
126974
|
if (records.length > 0) {
|
|
126101
|
-
await mkdir25(
|
|
126975
|
+
await mkdir25(path160.dirname(filePath), { recursive: true });
|
|
126102
126976
|
await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
|
|
126103
126977
|
`)}
|
|
126104
126978
|
`, "utf-8");
|
|
@@ -126295,7 +127169,7 @@ init_schema3();
|
|
|
126295
127169
|
init_store();
|
|
126296
127170
|
init_create_tool();
|
|
126297
127171
|
init_resolve_working_directory();
|
|
126298
|
-
import * as
|
|
127172
|
+
import * as path161 from "node:path";
|
|
126299
127173
|
var FindingSchema2 = exports_external.object({
|
|
126300
127174
|
severity: exports_external.enum(["low", "medium", "high", "critical"]),
|
|
126301
127175
|
category: exports_external.string().min(1),
|
|
@@ -126359,7 +127233,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
126359
127233
|
if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
|
|
126360
127234
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
126361
127235
|
const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
|
|
126362
|
-
const result = await curateAndStoreSwarm(lessons,
|
|
127236
|
+
const result = await curateAndStoreSwarm(lessons, path161.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
|
|
126363
127237
|
knowledgeProposed = result.stored;
|
|
126364
127238
|
}
|
|
126365
127239
|
} catch {}
|
|
@@ -126395,7 +127269,7 @@ init_ledger();
|
|
|
126395
127269
|
init_manager();
|
|
126396
127270
|
init_create_tool();
|
|
126397
127271
|
import fs118 from "node:fs";
|
|
126398
|
-
import
|
|
127272
|
+
import path162 from "node:path";
|
|
126399
127273
|
function normalizeVerdict(verdict) {
|
|
126400
127274
|
switch (verdict) {
|
|
126401
127275
|
case "APPROVED":
|
|
@@ -126443,7 +127317,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
126443
127317
|
entries: [evidenceEntry]
|
|
126444
127318
|
};
|
|
126445
127319
|
const filename = "drift-verifier.json";
|
|
126446
|
-
const relativePath =
|
|
127320
|
+
const relativePath = path162.join("evidence", String(phase), filename);
|
|
126447
127321
|
let validatedPath;
|
|
126448
127322
|
try {
|
|
126449
127323
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126454,10 +127328,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
126454
127328
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126455
127329
|
}, null, 2);
|
|
126456
127330
|
}
|
|
126457
|
-
const evidenceDir =
|
|
127331
|
+
const evidenceDir = path162.dirname(validatedPath);
|
|
126458
127332
|
try {
|
|
126459
127333
|
await fs118.promises.mkdir(evidenceDir, { recursive: true });
|
|
126460
|
-
const tempPath =
|
|
127334
|
+
const tempPath = path162.join(evidenceDir, `.${filename}.tmp`);
|
|
126461
127335
|
await fs118.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126462
127336
|
await fs118.promises.rename(tempPath, validatedPath);
|
|
126463
127337
|
let snapshotInfo;
|
|
@@ -126554,7 +127428,7 @@ var write_drift_evidence = createSwarmTool({
|
|
|
126554
127428
|
init_zod();
|
|
126555
127429
|
init_loader();
|
|
126556
127430
|
import fs119 from "node:fs";
|
|
126557
|
-
import
|
|
127431
|
+
import path163 from "node:path";
|
|
126558
127432
|
init_utils2();
|
|
126559
127433
|
init_manager();
|
|
126560
127434
|
init_create_tool();
|
|
@@ -126642,7 +127516,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
126642
127516
|
timestamp: synthesis.timestamp
|
|
126643
127517
|
};
|
|
126644
127518
|
const filename = "final-council.json";
|
|
126645
|
-
const relativePath =
|
|
127519
|
+
const relativePath = path163.join("evidence", filename);
|
|
126646
127520
|
let validatedPath;
|
|
126647
127521
|
try {
|
|
126648
127522
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126656,10 +127530,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
126656
127530
|
const evidenceContent = {
|
|
126657
127531
|
entries: [evidenceEntry]
|
|
126658
127532
|
};
|
|
126659
|
-
const evidenceDir =
|
|
127533
|
+
const evidenceDir = path163.dirname(validatedPath);
|
|
126660
127534
|
try {
|
|
126661
127535
|
await fs119.promises.mkdir(evidenceDir, { recursive: true });
|
|
126662
|
-
const tempPath =
|
|
127536
|
+
const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
|
|
126663
127537
|
await fs119.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126664
127538
|
await fs119.promises.rename(tempPath, validatedPath);
|
|
126665
127539
|
return JSON.stringify({
|
|
@@ -126719,7 +127593,7 @@ init_zod();
|
|
|
126719
127593
|
init_utils2();
|
|
126720
127594
|
init_create_tool();
|
|
126721
127595
|
import fs120 from "node:fs";
|
|
126722
|
-
import
|
|
127596
|
+
import path164 from "node:path";
|
|
126723
127597
|
function normalizeVerdict2(verdict) {
|
|
126724
127598
|
switch (verdict) {
|
|
126725
127599
|
case "APPROVED":
|
|
@@ -126767,7 +127641,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126767
127641
|
entries: [evidenceEntry]
|
|
126768
127642
|
};
|
|
126769
127643
|
const filename = "hallucination-guard.json";
|
|
126770
|
-
const relativePath =
|
|
127644
|
+
const relativePath = path164.join("evidence", String(phase), filename);
|
|
126771
127645
|
let validatedPath;
|
|
126772
127646
|
try {
|
|
126773
127647
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126778,10 +127652,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126778
127652
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126779
127653
|
}, null, 2);
|
|
126780
127654
|
}
|
|
126781
|
-
const evidenceDir =
|
|
127655
|
+
const evidenceDir = path164.dirname(validatedPath);
|
|
126782
127656
|
try {
|
|
126783
127657
|
await fs120.promises.mkdir(evidenceDir, { recursive: true });
|
|
126784
|
-
const tempPath =
|
|
127658
|
+
const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
|
|
126785
127659
|
await fs120.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126786
127660
|
await fs120.promises.rename(tempPath, validatedPath);
|
|
126787
127661
|
return JSON.stringify({
|
|
@@ -126831,7 +127705,7 @@ init_zod();
|
|
|
126831
127705
|
init_utils2();
|
|
126832
127706
|
init_create_tool();
|
|
126833
127707
|
import fs121 from "node:fs";
|
|
126834
|
-
import
|
|
127708
|
+
import path165 from "node:path";
|
|
126835
127709
|
function normalizeVerdict3(verdict) {
|
|
126836
127710
|
switch (verdict) {
|
|
126837
127711
|
case "PASS":
|
|
@@ -126905,7 +127779,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126905
127779
|
entries: [evidenceEntry]
|
|
126906
127780
|
};
|
|
126907
127781
|
const filename = "mutation-gate.json";
|
|
126908
|
-
const relativePath =
|
|
127782
|
+
const relativePath = path165.join("evidence", String(phase), filename);
|
|
126909
127783
|
let validatedPath;
|
|
126910
127784
|
try {
|
|
126911
127785
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126916,10 +127790,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126916
127790
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126917
127791
|
}, null, 2);
|
|
126918
127792
|
}
|
|
126919
|
-
const evidenceDir =
|
|
127793
|
+
const evidenceDir = path165.dirname(validatedPath);
|
|
126920
127794
|
try {
|
|
126921
127795
|
await fs121.promises.mkdir(evidenceDir, { recursive: true });
|
|
126922
|
-
const tempPath =
|
|
127796
|
+
const tempPath = path165.join(evidenceDir, `.${filename}.tmp`);
|
|
126923
127797
|
await fs121.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126924
127798
|
await fs121.promises.rename(tempPath, validatedPath);
|
|
126925
127799
|
return JSON.stringify({
|
|
@@ -127055,7 +127929,8 @@ var TOOL_MANIFEST = defineHandlers({
|
|
|
127055
127929
|
lean_turbo_runner_status: () => lean_turbo_runner_status,
|
|
127056
127930
|
lean_turbo_review: () => lean_turbo_review,
|
|
127057
127931
|
lean_turbo_run_phase: () => lean_turbo_run_phase,
|
|
127058
|
-
lean_turbo_status: () => lean_turbo_status
|
|
127932
|
+
lean_turbo_status: () => lean_turbo_status,
|
|
127933
|
+
apply_patch: () => applyPatch
|
|
127059
127934
|
});
|
|
127060
127935
|
|
|
127061
127936
|
// src/tools/plugin-registration.ts
|
|
@@ -127366,7 +128241,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
127366
128241
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
127367
128242
|
preflightTriggerManager = new PTM(automationConfig);
|
|
127368
128243
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
127369
|
-
const swarmDir =
|
|
128244
|
+
const swarmDir = path167.resolve(ctx.directory, ".swarm");
|
|
127370
128245
|
statusArtifact = new ASA(swarmDir);
|
|
127371
128246
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
127372
128247
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -127880,7 +128755,7 @@ ${promptRaw}`;
|
|
|
127880
128755
|
const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
|
|
127881
128756
|
let desc = meta3.description || "";
|
|
127882
128757
|
if (!desc || desc === "No description provided") {
|
|
127883
|
-
desc =
|
|
128758
|
+
desc = path167.basename(path167.dirname(s.skillPath));
|
|
127884
128759
|
}
|
|
127885
128760
|
desc = desc.replace(/,/g, ";");
|
|
127886
128761
|
return `file:${s.skillPath} (-- ${desc})`;
|
|
@@ -127890,7 +128765,7 @@ ${promptRaw}`;
|
|
|
127890
128765
|
|
|
127891
128766
|
${promptRaw}`;
|
|
127892
128767
|
argsRecord.prompt = newPrompt;
|
|
127893
|
-
const skillNames = topSkills.map((s) => `${
|
|
128768
|
+
const skillNames = topSkills.map((s) => `${path167.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
127894
128769
|
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
127895
128770
|
for (const skill of topSkills) {
|
|
127896
128771
|
try {
|