opencode-swarm 7.49.0 → 7.50.0
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/agents/critic.d.ts +2 -2
- package/dist/cli/index.js +5 -1
- package/dist/hooks/scope-guard.d.ts +24 -0
- package/dist/index.js +1302 -439
- 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/repo-graph/builder.d.ts +22 -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.0",
|
|
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);
|
|
@@ -84420,7 +84424,8 @@ Before reviewing the plan, check whether it was silently mutated since last crit
|
|
|
84420
84424
|
2. Examine the response:
|
|
84421
84425
|
- If \`success: false\` with \`reason: "no_approved_snapshot"\`: this is the first plan or no prior approval exists. Note this and proceed with plan review.
|
|
84422
84426
|
- If \`drift_detected: false\`: baseline integrity confirmed — the plan has not been mutated since the last critic approval. Proceed with plan review.
|
|
84423
|
-
- If \`drift_detected: true
|
|
84427
|
+
- If \`drift_detected: true\` AND \`approved_plan\` is defined: CRITICAL finding — plan mutated after approval. Compare \`approved_plan\` vs \`current_plan\` to identify what changed (phases added/removed, tasks modified, scope changes). Report findings in a \`## BASELINE DRIFT\` section before the rubric assessment.
|
|
84428
|
+
- If \`drift_detected: true\` AND \`approved_plan\` is undefined but \`current_plan_error\` is present: CRITICAL finding — plan identity was mutated (tampering detected). Report \`current_plan_error\` as primary evidence; state that direct comparison is unavailable due to identity mutation. Report findings in a \`## BASELINE DRIFT\` section before the rubric assessment.
|
|
84424
84429
|
- If \`drift_detected: "unknown"\`: flag as warning and proceed with caution.
|
|
84425
84430
|
3. Report spec-intent divergence: compare the approved baseline intent against what the current plan actually does, not just structural diff. Identify if the plan's purpose or scope has drifted from the original approved intent.
|
|
84426
84431
|
|
|
@@ -84606,7 +84611,8 @@ Before reviewing individual tasks, check whether the plan itself was silently mu
|
|
|
84606
84611
|
2. Examine the response:
|
|
84607
84612
|
- If \`success: false\` with \`reason: "no_approved_snapshot"\`: this is likely the first phase or no prior approval exists. Note this and proceed to per-task review.
|
|
84608
84613
|
- If \`drift_detected: false\`: baseline integrity confirmed — the plan has not been mutated since the last critic approval. Proceed to per-task review.
|
|
84609
|
-
- If \`drift_detected: true
|
|
84614
|
+
- If \`drift_detected: true\` AND \`approved_plan\` is defined: CRITICAL finding — plan mutated after approval. Compare \`approved_plan\` vs \`current_plan\` to identify what changed (phases added/removed, tasks modified, scope changes). Report findings in a \`## BASELINE DRIFT\` section before the per-task rubric.
|
|
84615
|
+
- If \`drift_detected: true\` AND \`approved_plan\` is undefined but \`current_plan_error\` is present: CRITICAL finding — plan identity was mutated (tampering detected). Report \`current_plan_error\` as primary evidence; state that direct comparison is unavailable due to identity mutation. Report findings in a \`## BASELINE DRIFT\` section before the per-task rubric.
|
|
84610
84616
|
- If \`drift_detected: "unknown"\`: current plan.json is unavailable. Flag this as a warning and proceed.
|
|
84611
84617
|
3. If baseline drift is detected, this is a CRITICAL finding — plan mutations after approval bypass the quality gate.
|
|
84612
84618
|
4. EXECUTION PROFILE DRIFT: If the \`get_approved_plan\` response includes \`execution_profile\` (on \`approved_plan\`) and the current plan also has \`execution_profile\`, compare them. If they differ and the approved profile was locked, flag as CRITICAL (locked profiles are immutable — a change indicates tampering or plan reset without re-approval). If the current plan has lost its execution_profile entirely when the approved plan had a locked one, flag as CRITICAL.
|
|
@@ -92312,7 +92318,7 @@ __export(exports_design_doc_drift, {
|
|
|
92312
92318
|
_internals: () => _internals60
|
|
92313
92319
|
});
|
|
92314
92320
|
import * as fs98 from "node:fs";
|
|
92315
|
-
import * as
|
|
92321
|
+
import * as path137 from "node:path";
|
|
92316
92322
|
function mtimeMsOrNull(absPath) {
|
|
92317
92323
|
try {
|
|
92318
92324
|
return fs98.statSync(absPath).mtimeMs;
|
|
@@ -92323,35 +92329,35 @@ function mtimeMsOrNull(absPath) {
|
|
|
92323
92329
|
function resolveAnchorWithin(directory, anchor) {
|
|
92324
92330
|
if (!anchor || typeof anchor !== "string")
|
|
92325
92331
|
return null;
|
|
92326
|
-
const root =
|
|
92327
|
-
const resolved =
|
|
92328
|
-
const rel =
|
|
92329
|
-
if (rel.startsWith("..") ||
|
|
92332
|
+
const root = path137.resolve(directory);
|
|
92333
|
+
const resolved = path137.resolve(root, anchor);
|
|
92334
|
+
const rel = path137.relative(root, resolved);
|
|
92335
|
+
if (rel.startsWith("..") || path137.isAbsolute(rel))
|
|
92330
92336
|
return null;
|
|
92331
92337
|
return resolved;
|
|
92332
92338
|
}
|
|
92333
92339
|
async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
92334
92340
|
try {
|
|
92335
|
-
const root =
|
|
92336
|
-
const outAbs =
|
|
92337
|
-
const outRel =
|
|
92338
|
-
if (outRel.startsWith("..") ||
|
|
92341
|
+
const root = path137.resolve(directory);
|
|
92342
|
+
const outAbs = path137.resolve(root, outDir);
|
|
92343
|
+
const outRel = path137.relative(root, outAbs);
|
|
92344
|
+
if (outRel.startsWith("..") || path137.isAbsolute(outRel)) {
|
|
92339
92345
|
return null;
|
|
92340
92346
|
}
|
|
92341
92347
|
const docMtimes = new Map;
|
|
92342
92348
|
const checkedDocs = [];
|
|
92343
92349
|
const missingDocs = [];
|
|
92344
92350
|
for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
|
|
92345
|
-
const abs =
|
|
92351
|
+
const abs = path137.join(outAbs, relFile);
|
|
92346
92352
|
const mtime = mtimeMsOrNull(abs);
|
|
92347
92353
|
docMtimes.set(docName, mtime);
|
|
92348
92354
|
if (mtime === null) {
|
|
92349
|
-
missingDocs.push(
|
|
92355
|
+
missingDocs.push(path137.join(outDir, relFile));
|
|
92350
92356
|
} else {
|
|
92351
|
-
checkedDocs.push(
|
|
92357
|
+
checkedDocs.push(path137.join(outDir, relFile));
|
|
92352
92358
|
}
|
|
92353
92359
|
}
|
|
92354
|
-
const traceabilityAbs =
|
|
92360
|
+
const traceabilityAbs = path137.join(outAbs, TRACEABILITY_REL);
|
|
92355
92361
|
let registry3 = null;
|
|
92356
92362
|
try {
|
|
92357
92363
|
const stat9 = await fs98.promises.stat(traceabilityAbs);
|
|
@@ -92364,7 +92370,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
92364
92370
|
registry3 = null;
|
|
92365
92371
|
}
|
|
92366
92372
|
const noDocs = checkedDocs.length === 0 || registry3 === null;
|
|
92367
|
-
const specMtime = mtimeMsOrNull(
|
|
92373
|
+
const specMtime = mtimeMsOrNull(path137.join(root, ".swarm", "spec.md"));
|
|
92368
92374
|
const staleSections = [];
|
|
92369
92375
|
if (!noDocs && Array.isArray(registry3?.sections)) {
|
|
92370
92376
|
for (const section of registry3.sections) {
|
|
@@ -92420,7 +92426,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
92420
92426
|
};
|
|
92421
92427
|
const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
|
|
92422
92428
|
const filePath = validateSwarmPath(directory, filename);
|
|
92423
|
-
await fs98.promises.mkdir(
|
|
92429
|
+
await fs98.promises.mkdir(path137.dirname(filePath), { recursive: true });
|
|
92424
92430
|
await fs98.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
92425
92431
|
getGlobalEventBus().publish("curator.docdrift.completed", {
|
|
92426
92432
|
phase,
|
|
@@ -92451,10 +92457,10 @@ var init_design_doc_drift = __esm(() => {
|
|
|
92451
92457
|
domain: "domain.md",
|
|
92452
92458
|
"technical-spec": "technical-spec.md",
|
|
92453
92459
|
"behavior-spec": "behavior-spec.md",
|
|
92454
|
-
"reference-impl":
|
|
92455
|
-
"idiom-notes":
|
|
92460
|
+
"reference-impl": path137.join("reference", "reference-impl.md"),
|
|
92461
|
+
"idiom-notes": path137.join("reference", "idiom-notes.md")
|
|
92456
92462
|
};
|
|
92457
|
-
TRACEABILITY_REL =
|
|
92463
|
+
TRACEABILITY_REL = path137.join("reference", "traceability.json");
|
|
92458
92464
|
_internals60 = {
|
|
92459
92465
|
mtimeMsOrNull,
|
|
92460
92466
|
resolveAnchorWithin,
|
|
@@ -92470,7 +92476,7 @@ __export(exports_project_context, {
|
|
|
92470
92476
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
92471
92477
|
});
|
|
92472
92478
|
import * as fs122 from "node:fs";
|
|
92473
|
-
import * as
|
|
92479
|
+
import * as path166 from "node:path";
|
|
92474
92480
|
function detectFileExists2(directory, pattern) {
|
|
92475
92481
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
92476
92482
|
try {
|
|
@@ -92482,7 +92488,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92482
92488
|
}
|
|
92483
92489
|
}
|
|
92484
92490
|
try {
|
|
92485
|
-
fs122.accessSync(
|
|
92491
|
+
fs122.accessSync(path166.join(directory, pattern));
|
|
92486
92492
|
return true;
|
|
92487
92493
|
} catch {
|
|
92488
92494
|
return false;
|
|
@@ -92491,7 +92497,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92491
92497
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
92492
92498
|
let pkgRaw;
|
|
92493
92499
|
try {
|
|
92494
|
-
pkgRaw = fs122.readFileSync(
|
|
92500
|
+
pkgRaw = fs122.readFileSync(path166.join(directory, "package.json"), "utf-8");
|
|
92495
92501
|
} catch {
|
|
92496
92502
|
return null;
|
|
92497
92503
|
}
|
|
@@ -92600,7 +92606,7 @@ var init_project_context = __esm(() => {
|
|
|
92600
92606
|
init_package();
|
|
92601
92607
|
init_agents2();
|
|
92602
92608
|
init_critic();
|
|
92603
|
-
import * as
|
|
92609
|
+
import * as path167 from "node:path";
|
|
92604
92610
|
|
|
92605
92611
|
// src/background/index.ts
|
|
92606
92612
|
init_event_bus();
|
|
@@ -95825,7 +95831,10 @@ function validateGraphEdge(edge) {
|
|
|
95825
95831
|
|
|
95826
95832
|
// src/tools/repo-graph/builder.ts
|
|
95827
95833
|
var _internals43 = {
|
|
95828
|
-
safeRealpathSync
|
|
95834
|
+
safeRealpathSync,
|
|
95835
|
+
extractTSSymbols,
|
|
95836
|
+
extractPythonSymbols,
|
|
95837
|
+
parseFileImports
|
|
95829
95838
|
};
|
|
95830
95839
|
var SKIP_DIRECTORIES2 = new Set([
|
|
95831
95840
|
"node_modules",
|
|
@@ -96122,14 +96131,14 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
|
|
|
96122
96131
|
try {
|
|
96123
96132
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
96124
96133
|
const relativePath = path81.relative(absoluteRoot, filePath);
|
|
96125
|
-
const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
|
|
96134
|
+
const symbols2 = _internals43.extractTSSymbols(relativePath, absoluteRoot);
|
|
96126
96135
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
96127
96136
|
} else if (ext === ".py") {
|
|
96128
96137
|
const relativePath = path81.relative(absoluteRoot, filePath);
|
|
96129
|
-
const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
|
|
96138
|
+
const symbols2 = _internals43.extractPythonSymbols(relativePath, absoluteRoot);
|
|
96130
96139
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
96131
96140
|
}
|
|
96132
|
-
const parsedImports = parseFileImports(content);
|
|
96141
|
+
const parsedImports = _internals43.parseFileImports(content);
|
|
96133
96142
|
const node = {
|
|
96134
96143
|
filePath,
|
|
96135
96144
|
moduleName: toModuleName(filePath, absoluteRoot),
|
|
@@ -103462,29 +103471,34 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
103462
103471
|
if (!declaredScope || declaredScope.length === 0)
|
|
103463
103472
|
return;
|
|
103464
103473
|
const argsObj = output.args;
|
|
103465
|
-
const
|
|
103466
|
-
|
|
103467
|
-
|
|
103468
|
-
|
|
103469
|
-
|
|
103470
|
-
|
|
103471
|
-
|
|
103472
|
-
|
|
103473
|
-
|
|
103474
|
-
|
|
103475
|
-
|
|
103476
|
-
|
|
103477
|
-
|
|
103478
|
-
|
|
103479
|
-
|
|
103480
|
-
|
|
103481
|
-
|
|
103482
|
-
} catch {}
|
|
103483
|
-
break;
|
|
103474
|
+
const candidatePaths = [];
|
|
103475
|
+
const singlePathKeys = ["path", "filePath", "file"];
|
|
103476
|
+
for (const key of singlePathKeys) {
|
|
103477
|
+
const val = argsObj?.[key];
|
|
103478
|
+
if (typeof val === "string" && val) {
|
|
103479
|
+
candidatePaths.push(val);
|
|
103480
|
+
}
|
|
103481
|
+
}
|
|
103482
|
+
let hasArrayKeys = false;
|
|
103483
|
+
const arrayPathKeys = ["files", "paths", "targetFiles"];
|
|
103484
|
+
for (const key of arrayPathKeys) {
|
|
103485
|
+
const val = argsObj?.[key];
|
|
103486
|
+
if (Array.isArray(val)) {
|
|
103487
|
+
hasArrayKeys = true;
|
|
103488
|
+
for (const item of val) {
|
|
103489
|
+
if (typeof item === "string" && item) {
|
|
103490
|
+
candidatePaths.push(item);
|
|
103484
103491
|
}
|
|
103485
103492
|
}
|
|
103486
103493
|
}
|
|
103487
|
-
|
|
103494
|
+
}
|
|
103495
|
+
if (candidatePaths.length === 0 && !hasArrayKeys)
|
|
103496
|
+
return;
|
|
103497
|
+
for (const rawPath of candidatePaths) {
|
|
103498
|
+
const filePath = sanitizePath(rawPath);
|
|
103499
|
+
if (!isFileInScope(filePath, declaredScope, directory)) {
|
|
103500
|
+
reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, swarmState, declaredScope);
|
|
103501
|
+
}
|
|
103488
103502
|
}
|
|
103489
103503
|
}
|
|
103490
103504
|
};
|
|
@@ -103492,7 +103506,7 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
103492
103506
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
103493
103507
|
const dir = directory ?? process.cwd();
|
|
103494
103508
|
const resolvedFile = path102.resolve(dir, filePath);
|
|
103495
|
-
return scopeEntries.some((scope) => {
|
|
103509
|
+
return scopeEntries.filter((scope) => scope.length > 0).some((scope) => {
|
|
103496
103510
|
const resolvedScope = path102.resolve(dir, scope);
|
|
103497
103511
|
if (resolvedFile === resolvedScope)
|
|
103498
103512
|
return true;
|
|
@@ -103500,6 +103514,38 @@ function isFileInScope(filePath, scopeEntries, directory) {
|
|
|
103500
103514
|
return rel.length > 0 && !rel.startsWith("..") && !path102.isAbsolute(rel);
|
|
103501
103515
|
});
|
|
103502
103516
|
}
|
|
103517
|
+
function sanitizePath(raw) {
|
|
103518
|
+
let result = "";
|
|
103519
|
+
for (let i2 = 0;i2 < raw.length; i2++) {
|
|
103520
|
+
const c = raw.charCodeAt(i2);
|
|
103521
|
+
if (c <= 31 || c === 127 || c >= 128 && c <= 159) {
|
|
103522
|
+
result += "_";
|
|
103523
|
+
continue;
|
|
103524
|
+
}
|
|
103525
|
+
result += raw[i2];
|
|
103526
|
+
}
|
|
103527
|
+
return result.replace(/\[[\d;]*m/g, "");
|
|
103528
|
+
}
|
|
103529
|
+
function reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, state, scopeEntries) {
|
|
103530
|
+
const taskLabel = taskId ?? "unknown";
|
|
103531
|
+
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 ? "..." : ""}]`;
|
|
103532
|
+
if (session) {
|
|
103533
|
+
session.lastScopeViolation = violationMessage;
|
|
103534
|
+
session.scopeViolationDetected = true;
|
|
103535
|
+
}
|
|
103536
|
+
if (injectAdvisory) {
|
|
103537
|
+
for (const [archSessionId, archSession] of state.agentSessions) {
|
|
103538
|
+
const archAgent = state.activeAgent.get(archSessionId) ?? archSession.agentName;
|
|
103539
|
+
if (stripKnownSwarmPrefix(archAgent) === ORCHESTRATOR_NAME) {
|
|
103540
|
+
try {
|
|
103541
|
+
injectAdvisory(archSessionId, `[SCOPE GUARD] ${violationMessage}`);
|
|
103542
|
+
} catch {}
|
|
103543
|
+
break;
|
|
103544
|
+
}
|
|
103545
|
+
}
|
|
103546
|
+
}
|
|
103547
|
+
throw new Error(violationMessage);
|
|
103548
|
+
}
|
|
103503
103549
|
|
|
103504
103550
|
// src/hooks/self-review.ts
|
|
103505
103551
|
init_constants();
|
|
@@ -105992,20 +106038,836 @@ init_snapshot_writer();
|
|
|
105992
106038
|
init_state();
|
|
105993
106039
|
init_telemetry();
|
|
105994
106040
|
|
|
106041
|
+
// src/tools/apply-patch.ts
|
|
106042
|
+
init_zod();
|
|
106043
|
+
init_path_security();
|
|
106044
|
+
init_create_tool();
|
|
106045
|
+
import {
|
|
106046
|
+
existsSync as existsSync58,
|
|
106047
|
+
mkdirSync as mkdirSync27,
|
|
106048
|
+
mkdtempSync as mkdtempSync2,
|
|
106049
|
+
readFileSync as readFileSync39,
|
|
106050
|
+
realpathSync as realpathSync13,
|
|
106051
|
+
renameSync as renameSync20,
|
|
106052
|
+
rmdirSync,
|
|
106053
|
+
unlinkSync as unlinkSync17,
|
|
106054
|
+
writeFileSync as writeFileSync20
|
|
106055
|
+
} from "node:fs";
|
|
106056
|
+
import * as path109 from "node:path";
|
|
106057
|
+
var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
106058
|
+
var MAX_PATCH_SIZE = 500000;
|
|
106059
|
+
function containsWindowsAttacks2(filePath) {
|
|
106060
|
+
if (/:[^\\/]/.test(filePath))
|
|
106061
|
+
return true;
|
|
106062
|
+
const parts2 = filePath.split(/[/\\]/);
|
|
106063
|
+
for (const part of parts2) {
|
|
106064
|
+
if (WINDOWS_RESERVED_NAMES2.test(part))
|
|
106065
|
+
return true;
|
|
106066
|
+
}
|
|
106067
|
+
return false;
|
|
106068
|
+
}
|
|
106069
|
+
function isProtectedPath2(filePath) {
|
|
106070
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
106071
|
+
const segments = normalized.split("/");
|
|
106072
|
+
return segments.some((seg) => seg === ".git" || seg === ".swarm");
|
|
106073
|
+
}
|
|
106074
|
+
function containsStrictControlChars(str) {
|
|
106075
|
+
for (let i2 = 0;i2 < str.length; i2++) {
|
|
106076
|
+
const c = str.charCodeAt(i2);
|
|
106077
|
+
if (c <= 31 && c !== 9 && c !== 10 && c !== 13)
|
|
106078
|
+
return true;
|
|
106079
|
+
}
|
|
106080
|
+
return false;
|
|
106081
|
+
}
|
|
106082
|
+
function isCanonicalProtectedPath(targetPath, workspace) {
|
|
106083
|
+
try {
|
|
106084
|
+
const canonicalTarget = realpathSync13(targetPath);
|
|
106085
|
+
const canonicalWorkspace = realpathSync13(workspace);
|
|
106086
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalTarget).replace(/\\/g, "/");
|
|
106087
|
+
const segments = relative21.split("/").filter(Boolean);
|
|
106088
|
+
return segments.some((seg) => seg === ".git" || seg === ".swarm");
|
|
106089
|
+
} catch {
|
|
106090
|
+
const parentDir = path109.dirname(targetPath);
|
|
106091
|
+
if (parentDir === targetPath)
|
|
106092
|
+
return false;
|
|
106093
|
+
try {
|
|
106094
|
+
const canonicalParent = realpathSync13(parentDir);
|
|
106095
|
+
const canonicalWorkspace = realpathSync13(workspace);
|
|
106096
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalParent).replace(/\\/g, "/");
|
|
106097
|
+
const segments = relative21.split("/").filter(Boolean);
|
|
106098
|
+
return segments.some((seg) => seg === ".git" || seg === ".swarm");
|
|
106099
|
+
} catch {
|
|
106100
|
+
return false;
|
|
106101
|
+
}
|
|
106102
|
+
}
|
|
106103
|
+
}
|
|
106104
|
+
function isCanonicalPathWithinWorkspace(targetPath, workspaceRoot) {
|
|
106105
|
+
try {
|
|
106106
|
+
const canonicalTarget = realpathSync13(targetPath);
|
|
106107
|
+
const canonicalWorkspace = realpathSync13(workspaceRoot);
|
|
106108
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalTarget);
|
|
106109
|
+
if (relative21.startsWith("..") || path109.isAbsolute(relative21))
|
|
106110
|
+
return false;
|
|
106111
|
+
const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
106112
|
+
if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
|
|
106113
|
+
return false;
|
|
106114
|
+
return true;
|
|
106115
|
+
} catch {
|
|
106116
|
+
const parentDir = path109.dirname(targetPath);
|
|
106117
|
+
if (parentDir === targetPath) {
|
|
106118
|
+
return false;
|
|
106119
|
+
}
|
|
106120
|
+
try {
|
|
106121
|
+
const canonicalParent = realpathSync13(parentDir);
|
|
106122
|
+
const canonicalWorkspace = realpathSync13(workspaceRoot);
|
|
106123
|
+
const relative21 = path109.relative(canonicalWorkspace, canonicalParent);
|
|
106124
|
+
if (relative21.startsWith("..") || path109.isAbsolute(relative21))
|
|
106125
|
+
return false;
|
|
106126
|
+
const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
106127
|
+
if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
|
|
106128
|
+
return false;
|
|
106129
|
+
return true;
|
|
106130
|
+
} catch {
|
|
106131
|
+
return false;
|
|
106132
|
+
}
|
|
106133
|
+
}
|
|
106134
|
+
}
|
|
106135
|
+
function validatePatchTargetPath(filePath, workspace) {
|
|
106136
|
+
if (!filePath || filePath.trim() === "") {
|
|
106137
|
+
return "Empty file path";
|
|
106138
|
+
}
|
|
106139
|
+
if (path109.isAbsolute(filePath) || /^[A-Za-z]:[/\\]/.test(filePath)) {
|
|
106140
|
+
return `Absolute path rejected: ${filePath}`;
|
|
106141
|
+
}
|
|
106142
|
+
if (containsPathTraversal(filePath)) {
|
|
106143
|
+
return `Path traversal detected: ${filePath}`;
|
|
106144
|
+
}
|
|
106145
|
+
if (containsStrictControlChars(filePath)) {
|
|
106146
|
+
return `Control characters detected in path: ${filePath}`;
|
|
106147
|
+
}
|
|
106148
|
+
if (containsControlChars(filePath)) {
|
|
106149
|
+
return `Control characters detected in path: ${filePath}`;
|
|
106150
|
+
}
|
|
106151
|
+
if (containsWindowsAttacks2(filePath)) {
|
|
106152
|
+
return `Windows reserved name or invalid path: ${filePath}`;
|
|
106153
|
+
}
|
|
106154
|
+
if (isProtectedPath2(filePath)) {
|
|
106155
|
+
return `Protected directory target rejected: ${filePath}`;
|
|
106156
|
+
}
|
|
106157
|
+
const resolved = path109.resolve(workspace, filePath);
|
|
106158
|
+
const relative21 = path109.relative(workspace, resolved);
|
|
106159
|
+
if (relative21.startsWith("..") || path109.isAbsolute(relative21)) {
|
|
106160
|
+
return `Path escapes workspace: ${filePath}`;
|
|
106161
|
+
}
|
|
106162
|
+
if (!isCanonicalPathWithinWorkspace(resolved, workspace)) {
|
|
106163
|
+
return `Path escapes workspace via symlink/junction: ${filePath}`;
|
|
106164
|
+
}
|
|
106165
|
+
return null;
|
|
106166
|
+
}
|
|
106167
|
+
function extractHeaderPath(header, prefix) {
|
|
106168
|
+
const trimmed = header.trim();
|
|
106169
|
+
if (!trimmed.startsWith(prefix))
|
|
106170
|
+
return null;
|
|
106171
|
+
const rest = trimmed.slice(prefix.length).trim();
|
|
106172
|
+
if (rest === "/dev/null")
|
|
106173
|
+
return "/dev/null";
|
|
106174
|
+
if (rest.startsWith("a/") || rest.startsWith("b/")) {
|
|
106175
|
+
const stripped = rest.slice(2);
|
|
106176
|
+
if (stripped.length === 0)
|
|
106177
|
+
return null;
|
|
106178
|
+
return stripped;
|
|
106179
|
+
}
|
|
106180
|
+
return rest.length > 0 ? rest : null;
|
|
106181
|
+
}
|
|
106182
|
+
function parseHunkHeader(line) {
|
|
106183
|
+
const match = line.match(/^@@\s*-(\d+)(?:,(\d+))?\s*\+(\d+)(?:,(\d+))?\s*@@/);
|
|
106184
|
+
if (!match)
|
|
106185
|
+
return null;
|
|
106186
|
+
return {
|
|
106187
|
+
oldStart: parseInt(match[1], 10),
|
|
106188
|
+
oldCount: match[2] !== undefined ? parseInt(match[2], 10) : 1,
|
|
106189
|
+
newStart: parseInt(match[3], 10),
|
|
106190
|
+
newCount: match[4] !== undefined ? parseInt(match[4], 10) : 1
|
|
106191
|
+
};
|
|
106192
|
+
}
|
|
106193
|
+
function parseUnifiedDiff(patchText) {
|
|
106194
|
+
if (patchText.length > MAX_PATCH_SIZE) {
|
|
106195
|
+
return {
|
|
106196
|
+
files: [],
|
|
106197
|
+
error: `Patch exceeds maximum size of ${MAX_PATCH_SIZE} characters`
|
|
106198
|
+
};
|
|
106199
|
+
}
|
|
106200
|
+
if (patchText.includes("\x00")) {
|
|
106201
|
+
return {
|
|
106202
|
+
files: [],
|
|
106203
|
+
error: "Binary content detected (null byte) — binary patches are not supported (FR-013)"
|
|
106204
|
+
};
|
|
106205
|
+
}
|
|
106206
|
+
const normalized = patchText.replace(/\r\n/g, `
|
|
106207
|
+
`).replace(/\r/g, `
|
|
106208
|
+
`);
|
|
106209
|
+
let lines = normalized.split(`
|
|
106210
|
+
`);
|
|
106211
|
+
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
106212
|
+
lines = lines.slice(0, -1);
|
|
106213
|
+
}
|
|
106214
|
+
for (const line of lines) {
|
|
106215
|
+
if (line === "GIT binary patch" || line.startsWith("Binary files ")) {
|
|
106216
|
+
return { files: [], error: "Binary patches are not supported (FR-013)" };
|
|
106217
|
+
}
|
|
106218
|
+
if (line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("copy from") || line.startsWith("copy to")) {
|
|
106219
|
+
return {
|
|
106220
|
+
files: [],
|
|
106221
|
+
error: "Rename/copy patches are not supported (FR-013)"
|
|
106222
|
+
};
|
|
106223
|
+
}
|
|
106224
|
+
}
|
|
106225
|
+
const fileDiffs = [];
|
|
106226
|
+
let i2 = 0;
|
|
106227
|
+
while (i2 < lines.length) {
|
|
106228
|
+
let oldHeaderPath = null;
|
|
106229
|
+
let newHeaderPath = null;
|
|
106230
|
+
if (lines[i2].startsWith("diff --git ")) {
|
|
106231
|
+
i2++;
|
|
106232
|
+
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 "))) {
|
|
106233
|
+
i2++;
|
|
106234
|
+
}
|
|
106235
|
+
}
|
|
106236
|
+
if (i2 < lines.length && lines[i2].startsWith("--- ")) {
|
|
106237
|
+
oldHeaderPath = extractHeaderPath(lines[i2], "--- ");
|
|
106238
|
+
i2++;
|
|
106239
|
+
} else if (oldHeaderPath === null) {
|
|
106240
|
+
i2++;
|
|
106241
|
+
continue;
|
|
106242
|
+
}
|
|
106243
|
+
if (i2 < lines.length && lines[i2].startsWith("+++ ")) {
|
|
106244
|
+
newHeaderPath = extractHeaderPath(lines[i2], "+++ ");
|
|
106245
|
+
i2++;
|
|
106246
|
+
} else {
|
|
106247
|
+
continue;
|
|
106248
|
+
}
|
|
106249
|
+
if (oldHeaderPath === null || newHeaderPath === null) {
|
|
106250
|
+
continue;
|
|
106251
|
+
}
|
|
106252
|
+
const isNewFile = oldHeaderPath === "/dev/null";
|
|
106253
|
+
const isDelete = newHeaderPath === "/dev/null";
|
|
106254
|
+
const targetPath = isDelete ? oldHeaderPath : newHeaderPath;
|
|
106255
|
+
if (targetPath === "/dev/null") {
|
|
106256
|
+
continue;
|
|
106257
|
+
}
|
|
106258
|
+
const hunks = [];
|
|
106259
|
+
while (i2 < lines.length && lines[i2].startsWith("@@")) {
|
|
106260
|
+
const header = parseHunkHeader(lines[i2]);
|
|
106261
|
+
if (!header) {
|
|
106262
|
+
i2++;
|
|
106263
|
+
continue;
|
|
106264
|
+
}
|
|
106265
|
+
i2++;
|
|
106266
|
+
const hunkLines = [];
|
|
106267
|
+
while (i2 < lines.length) {
|
|
106268
|
+
const line = lines[i2];
|
|
106269
|
+
if (line.startsWith("@@") || line.startsWith("diff --git ") || line.startsWith("--- ") || line.startsWith("+++ ")) {
|
|
106270
|
+
break;
|
|
106271
|
+
}
|
|
106272
|
+
if (line.startsWith("\\")) {
|
|
106273
|
+
i2++;
|
|
106274
|
+
continue;
|
|
106275
|
+
}
|
|
106276
|
+
if (line.length === 0) {
|
|
106277
|
+
break;
|
|
106278
|
+
}
|
|
106279
|
+
const firstChar = line[0];
|
|
106280
|
+
if (firstChar !== " " && firstChar !== "+" && firstChar !== "-") {
|
|
106281
|
+
break;
|
|
106282
|
+
}
|
|
106283
|
+
if (firstChar === "+") {
|
|
106284
|
+
hunkLines.push({ type: "addition", content: line.slice(1) });
|
|
106285
|
+
} else if (firstChar === "-") {
|
|
106286
|
+
hunkLines.push({ type: "removal", content: line.slice(1) });
|
|
106287
|
+
} else {
|
|
106288
|
+
hunkLines.push({ type: "context", content: line.slice(1) });
|
|
106289
|
+
}
|
|
106290
|
+
i2++;
|
|
106291
|
+
}
|
|
106292
|
+
hunks.push({
|
|
106293
|
+
oldStart: header.oldStart,
|
|
106294
|
+
oldCount: header.oldCount,
|
|
106295
|
+
newStart: header.newStart,
|
|
106296
|
+
newCount: header.newCount,
|
|
106297
|
+
lines: hunkLines
|
|
106298
|
+
});
|
|
106299
|
+
}
|
|
106300
|
+
if (hunks.length > 0) {
|
|
106301
|
+
fileDiffs.push({
|
|
106302
|
+
oldPath: oldHeaderPath,
|
|
106303
|
+
newPath: newHeaderPath,
|
|
106304
|
+
isNewFile,
|
|
106305
|
+
isDelete,
|
|
106306
|
+
hunks
|
|
106307
|
+
});
|
|
106308
|
+
} else {
|
|
106309
|
+
fileDiffs.push({
|
|
106310
|
+
oldPath: oldHeaderPath,
|
|
106311
|
+
newPath: newHeaderPath,
|
|
106312
|
+
isNewFile,
|
|
106313
|
+
isDelete,
|
|
106314
|
+
hunks: []
|
|
106315
|
+
});
|
|
106316
|
+
}
|
|
106317
|
+
}
|
|
106318
|
+
return { files: fileDiffs, error: null };
|
|
106319
|
+
}
|
|
106320
|
+
function arraysEqual(a, b) {
|
|
106321
|
+
if (a.length !== b.length)
|
|
106322
|
+
return false;
|
|
106323
|
+
for (let idx = 0;idx < a.length; idx++) {
|
|
106324
|
+
if (a[idx] !== b[idx])
|
|
106325
|
+
return false;
|
|
106326
|
+
}
|
|
106327
|
+
return true;
|
|
106328
|
+
}
|
|
106329
|
+
function applyHunks(content, fileDiff) {
|
|
106330
|
+
const normalizedContent = content.replace(/\r\n/g, `
|
|
106331
|
+
`);
|
|
106332
|
+
const fileLines = normalizedContent.split(`
|
|
106333
|
+
`);
|
|
106334
|
+
if (fileDiff.isNewFile) {
|
|
106335
|
+
const newLines = [];
|
|
106336
|
+
for (const hunk of fileDiff.hunks) {
|
|
106337
|
+
for (const line of hunk.lines) {
|
|
106338
|
+
if (line.type === "addition" || line.type === "context") {
|
|
106339
|
+
newLines.push(line.content);
|
|
106340
|
+
}
|
|
106341
|
+
}
|
|
106342
|
+
}
|
|
106343
|
+
return { success: true, appliedLines: newLines };
|
|
106344
|
+
}
|
|
106345
|
+
if (fileDiff.isDelete) {
|
|
106346
|
+
return { success: true, appliedLines: [] };
|
|
106347
|
+
}
|
|
106348
|
+
let accumulatedDelta = 0;
|
|
106349
|
+
for (let hunkIdx = 0;hunkIdx < fileDiff.hunks.length; hunkIdx++) {
|
|
106350
|
+
const hunk = fileDiff.hunks[hunkIdx];
|
|
106351
|
+
const searchStart = Math.max(0, hunk.oldStart - 1 + accumulatedDelta);
|
|
106352
|
+
const expectedOldLines = [];
|
|
106353
|
+
const newLinesForHunk = [];
|
|
106354
|
+
for (const line of hunk.lines) {
|
|
106355
|
+
if (line.type === "context") {
|
|
106356
|
+
expectedOldLines.push(line.content);
|
|
106357
|
+
newLinesForHunk.push(line.content);
|
|
106358
|
+
} else if (line.type === "removal") {
|
|
106359
|
+
expectedOldLines.push(line.content);
|
|
106360
|
+
} else if (line.type === "addition") {
|
|
106361
|
+
newLinesForHunk.push(line.content);
|
|
106362
|
+
}
|
|
106363
|
+
}
|
|
106364
|
+
const exactOffset = searchStart;
|
|
106365
|
+
const matchFound = exactOffset <= fileLines.length - expectedOldLines.length && arraysEqual(fileLines.slice(exactOffset, exactOffset + expectedOldLines.length), expectedOldLines);
|
|
106366
|
+
if (matchFound) {
|
|
106367
|
+
fileLines.splice(exactOffset, expectedOldLines.length, ...newLinesForHunk);
|
|
106368
|
+
const delta = newLinesForHunk.length - expectedOldLines.length;
|
|
106369
|
+
accumulatedDelta += delta;
|
|
106370
|
+
}
|
|
106371
|
+
if (!matchFound) {
|
|
106372
|
+
const diagStart = Math.min(searchStart, fileLines.length);
|
|
106373
|
+
const diagEnd = Math.min(diagStart + expectedOldLines.length, fileLines.length);
|
|
106374
|
+
const actualContent = fileLines.slice(diagStart, diagEnd).join(`
|
|
106375
|
+
`);
|
|
106376
|
+
const expectedContent = expectedOldLines.join(`
|
|
106377
|
+
`);
|
|
106378
|
+
return {
|
|
106379
|
+
success: false,
|
|
106380
|
+
failedHunkIndex: hunkIdx,
|
|
106381
|
+
error: {
|
|
106382
|
+
hunkIndex: hunkIdx,
|
|
106383
|
+
type: "context-mismatch",
|
|
106384
|
+
message: `Context mismatch in hunk ${hunkIdx + 1} at line ${searchStart + 1}: expected context does not match file content`,
|
|
106385
|
+
expected: expectedContent.length > 200 ? `${expectedContent.slice(0, 200)}... (truncated)` : expectedContent,
|
|
106386
|
+
actual: actualContent.length > 200 ? `${actualContent.slice(0, 200)}... (truncated)` : actualContent,
|
|
106387
|
+
line: searchStart + 1
|
|
106388
|
+
}
|
|
106389
|
+
};
|
|
106390
|
+
}
|
|
106391
|
+
}
|
|
106392
|
+
return { success: true, appliedLines: fileLines };
|
|
106393
|
+
}
|
|
106394
|
+
function atomicWriteFileSync(targetPath, content) {
|
|
106395
|
+
const dir = path109.dirname(targetPath);
|
|
106396
|
+
mkdirSync27(dir, { recursive: true });
|
|
106397
|
+
const tempPrefix = `.apply-patch-${Date.now()}-${process.pid}`;
|
|
106398
|
+
let tempPath;
|
|
106399
|
+
try {
|
|
106400
|
+
const tempDir = realpathSync13(mkdtempSync2(path109.join(dir, tempPrefix)));
|
|
106401
|
+
tempPath = path109.join(tempDir, "content");
|
|
106402
|
+
} catch {
|
|
106403
|
+
tempPath = path109.join(dir, `${tempPrefix}.tmp`);
|
|
106404
|
+
}
|
|
106405
|
+
try {
|
|
106406
|
+
writeFileSync20(tempPath, content, "utf-8");
|
|
106407
|
+
renameSync20(tempPath, targetPath);
|
|
106408
|
+
} finally {
|
|
106409
|
+
if (existsSync58(tempPath)) {
|
|
106410
|
+
try {
|
|
106411
|
+
unlinkSync17(tempPath);
|
|
106412
|
+
} catch {}
|
|
106413
|
+
}
|
|
106414
|
+
const tempDir = path109.dirname(tempPath);
|
|
106415
|
+
if (tempDir !== dir && existsSync58(tempDir)) {
|
|
106416
|
+
try {
|
|
106417
|
+
rmdirSync(tempDir);
|
|
106418
|
+
} catch {}
|
|
106419
|
+
}
|
|
106420
|
+
}
|
|
106421
|
+
}
|
|
106422
|
+
function detectLineEnding(content) {
|
|
106423
|
+
return content.includes(`\r
|
|
106424
|
+
`) ? `\r
|
|
106425
|
+
` : `
|
|
106426
|
+
`;
|
|
106427
|
+
}
|
|
106428
|
+
function ensureFinalNewline(content, originalEndsWithNewline) {
|
|
106429
|
+
if (originalEndsWithNewline && !content.endsWith(`
|
|
106430
|
+
`)) {
|
|
106431
|
+
return `${content}
|
|
106432
|
+
`;
|
|
106433
|
+
}
|
|
106434
|
+
if (!originalEndsWithNewline && content.endsWith(`
|
|
106435
|
+
`)) {
|
|
106436
|
+
return content.slice(0, -1);
|
|
106437
|
+
}
|
|
106438
|
+
return content;
|
|
106439
|
+
}
|
|
106440
|
+
function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allowCreates, allowDeletes) {
|
|
106441
|
+
const hunksTotal = fileDiff.hunks.length;
|
|
106442
|
+
if (!isCanonicalPathWithinWorkspace(fullPath, workspace)) {
|
|
106443
|
+
return {
|
|
106444
|
+
file: targetPath,
|
|
106445
|
+
status: "error",
|
|
106446
|
+
hunks: hunksTotal,
|
|
106447
|
+
hunksApplied: 0,
|
|
106448
|
+
hunksFailed: hunksTotal,
|
|
106449
|
+
errors: [
|
|
106450
|
+
{
|
|
106451
|
+
hunkIndex: 0,
|
|
106452
|
+
type: "context-mismatch",
|
|
106453
|
+
message: `Path escapes workspace via symlink/junction: ${targetPath}`
|
|
106454
|
+
}
|
|
106455
|
+
]
|
|
106456
|
+
};
|
|
106457
|
+
}
|
|
106458
|
+
if (isCanonicalProtectedPath(fullPath, workspace)) {
|
|
106459
|
+
return {
|
|
106460
|
+
file: targetPath,
|
|
106461
|
+
status: "error",
|
|
106462
|
+
hunks: hunksTotal,
|
|
106463
|
+
hunksApplied: 0,
|
|
106464
|
+
hunksFailed: hunksTotal,
|
|
106465
|
+
errors: [
|
|
106466
|
+
{
|
|
106467
|
+
hunkIndex: 0,
|
|
106468
|
+
type: "context-mismatch",
|
|
106469
|
+
message: `Protected directory target rejected via symlink: ${targetPath}`
|
|
106470
|
+
}
|
|
106471
|
+
]
|
|
106472
|
+
};
|
|
106473
|
+
}
|
|
106474
|
+
if (fileDiff.isNewFile) {
|
|
106475
|
+
if (!allowCreates) {
|
|
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: "create-not-allowed",
|
|
106486
|
+
message: `New file creation not allowed: ${targetPath} (set allowCreates to true)`
|
|
106487
|
+
}
|
|
106488
|
+
]
|
|
106489
|
+
};
|
|
106490
|
+
}
|
|
106491
|
+
const parentDir = path109.dirname(fullPath);
|
|
106492
|
+
if (!existsSync58(parentDir)) {
|
|
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: "file-not-found",
|
|
106503
|
+
message: `Parent directory does not exist: ${parentDir}`
|
|
106504
|
+
}
|
|
106505
|
+
]
|
|
106506
|
+
};
|
|
106507
|
+
}
|
|
106508
|
+
if (existsSync58(fullPath)) {
|
|
106509
|
+
return {
|
|
106510
|
+
file: targetPath,
|
|
106511
|
+
status: "error",
|
|
106512
|
+
hunks: hunksTotal,
|
|
106513
|
+
hunksApplied: 0,
|
|
106514
|
+
hunksFailed: hunksTotal,
|
|
106515
|
+
errors: [
|
|
106516
|
+
{
|
|
106517
|
+
hunkIndex: 0,
|
|
106518
|
+
type: "file-not-found",
|
|
106519
|
+
message: `File already exists: ${targetPath} (cannot create — patch may be stale)`
|
|
106520
|
+
}
|
|
106521
|
+
]
|
|
106522
|
+
};
|
|
106523
|
+
}
|
|
106524
|
+
if (hunksTotal === 0) {
|
|
106525
|
+
return {
|
|
106526
|
+
file: targetPath,
|
|
106527
|
+
status: "no-changes",
|
|
106528
|
+
hunks: 0,
|
|
106529
|
+
hunksApplied: 0,
|
|
106530
|
+
hunksFailed: 0
|
|
106531
|
+
};
|
|
106532
|
+
}
|
|
106533
|
+
const hunkResult2 = applyHunks("", fileDiff);
|
|
106534
|
+
if (!hunkResult2.success || !hunkResult2.appliedLines) {
|
|
106535
|
+
return {
|
|
106536
|
+
file: targetPath,
|
|
106537
|
+
status: "error",
|
|
106538
|
+
hunks: hunksTotal,
|
|
106539
|
+
hunksApplied: 0,
|
|
106540
|
+
hunksFailed: hunksTotal,
|
|
106541
|
+
errors: hunkResult2.error ? [hunkResult2.error] : []
|
|
106542
|
+
};
|
|
106543
|
+
}
|
|
106544
|
+
if (!dryRun) {
|
|
106545
|
+
const content2 = ensureFinalNewline(hunkResult2.appliedLines.join(`
|
|
106546
|
+
`), true);
|
|
106547
|
+
atomicWriteFileSync(fullPath, content2);
|
|
106548
|
+
}
|
|
106549
|
+
return {
|
|
106550
|
+
file: targetPath,
|
|
106551
|
+
status: "created",
|
|
106552
|
+
hunks: hunksTotal,
|
|
106553
|
+
hunksApplied: hunksTotal,
|
|
106554
|
+
hunksFailed: 0
|
|
106555
|
+
};
|
|
106556
|
+
}
|
|
106557
|
+
if (fileDiff.isDelete) {
|
|
106558
|
+
if (hunksTotal === 0) {
|
|
106559
|
+
return {
|
|
106560
|
+
file: targetPath,
|
|
106561
|
+
status: "no-changes",
|
|
106562
|
+
hunks: 0,
|
|
106563
|
+
hunksApplied: 0,
|
|
106564
|
+
hunksFailed: 0
|
|
106565
|
+
};
|
|
106566
|
+
}
|
|
106567
|
+
if (!allowDeletes) {
|
|
106568
|
+
return {
|
|
106569
|
+
file: targetPath,
|
|
106570
|
+
status: "error",
|
|
106571
|
+
hunks: hunksTotal,
|
|
106572
|
+
hunksApplied: 0,
|
|
106573
|
+
hunksFailed: hunksTotal,
|
|
106574
|
+
errors: [
|
|
106575
|
+
{
|
|
106576
|
+
hunkIndex: 0,
|
|
106577
|
+
type: "delete-not-allowed",
|
|
106578
|
+
message: `File deletion not allowed: ${targetPath} (set allowDeletes to true)`
|
|
106579
|
+
}
|
|
106580
|
+
]
|
|
106581
|
+
};
|
|
106582
|
+
}
|
|
106583
|
+
if (!existsSync58(fullPath)) {
|
|
106584
|
+
return {
|
|
106585
|
+
file: targetPath,
|
|
106586
|
+
status: "error",
|
|
106587
|
+
hunks: hunksTotal,
|
|
106588
|
+
hunksApplied: 0,
|
|
106589
|
+
hunksFailed: hunksTotal,
|
|
106590
|
+
errors: [
|
|
106591
|
+
{
|
|
106592
|
+
hunkIndex: 0,
|
|
106593
|
+
type: "file-not-found",
|
|
106594
|
+
message: `File not found for deletion: ${targetPath}`
|
|
106595
|
+
}
|
|
106596
|
+
]
|
|
106597
|
+
};
|
|
106598
|
+
}
|
|
106599
|
+
if (!dryRun) {
|
|
106600
|
+
try {
|
|
106601
|
+
unlinkSync17(fullPath);
|
|
106602
|
+
} catch (err2) {
|
|
106603
|
+
return {
|
|
106604
|
+
file: targetPath,
|
|
106605
|
+
status: "error",
|
|
106606
|
+
hunks: hunksTotal,
|
|
106607
|
+
hunksApplied: 0,
|
|
106608
|
+
hunksFailed: hunksTotal,
|
|
106609
|
+
errors: [
|
|
106610
|
+
{
|
|
106611
|
+
hunkIndex: 0,
|
|
106612
|
+
type: "file-not-found",
|
|
106613
|
+
message: `Failed to delete file: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
106614
|
+
}
|
|
106615
|
+
]
|
|
106616
|
+
};
|
|
106617
|
+
}
|
|
106618
|
+
}
|
|
106619
|
+
return {
|
|
106620
|
+
file: targetPath,
|
|
106621
|
+
status: "applied",
|
|
106622
|
+
hunks: hunksTotal,
|
|
106623
|
+
hunksApplied: hunksTotal,
|
|
106624
|
+
hunksFailed: 0
|
|
106625
|
+
};
|
|
106626
|
+
}
|
|
106627
|
+
if (!existsSync58(fullPath)) {
|
|
106628
|
+
return {
|
|
106629
|
+
file: targetPath,
|
|
106630
|
+
status: "error",
|
|
106631
|
+
hunks: hunksTotal,
|
|
106632
|
+
hunksApplied: 0,
|
|
106633
|
+
hunksFailed: hunksTotal,
|
|
106634
|
+
errors: [
|
|
106635
|
+
{
|
|
106636
|
+
hunkIndex: 0,
|
|
106637
|
+
type: "file-not-found",
|
|
106638
|
+
message: `File not found: ${targetPath}`
|
|
106639
|
+
}
|
|
106640
|
+
]
|
|
106641
|
+
};
|
|
106642
|
+
}
|
|
106643
|
+
let content;
|
|
106644
|
+
try {
|
|
106645
|
+
content = readFileSync39(fullPath, "utf-8");
|
|
106646
|
+
} catch (err2) {
|
|
106647
|
+
return {
|
|
106648
|
+
file: targetPath,
|
|
106649
|
+
status: "error",
|
|
106650
|
+
hunks: hunksTotal,
|
|
106651
|
+
hunksApplied: 0,
|
|
106652
|
+
hunksFailed: hunksTotal,
|
|
106653
|
+
errors: [
|
|
106654
|
+
{
|
|
106655
|
+
hunkIndex: 0,
|
|
106656
|
+
type: "file-not-found",
|
|
106657
|
+
message: `Could not read file: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
106658
|
+
}
|
|
106659
|
+
]
|
|
106660
|
+
};
|
|
106661
|
+
}
|
|
106662
|
+
if (hunksTotal === 0) {
|
|
106663
|
+
return {
|
|
106664
|
+
file: targetPath,
|
|
106665
|
+
status: "no-changes",
|
|
106666
|
+
hunks: 0,
|
|
106667
|
+
hunksApplied: 0,
|
|
106668
|
+
hunksFailed: 0
|
|
106669
|
+
};
|
|
106670
|
+
}
|
|
106671
|
+
const originalEndsWithNewline = content.endsWith(`
|
|
106672
|
+
`);
|
|
106673
|
+
const originalLineEnding = detectLineEnding(content);
|
|
106674
|
+
const hunkResult = applyHunks(content, fileDiff);
|
|
106675
|
+
if (!hunkResult.success) {
|
|
106676
|
+
return {
|
|
106677
|
+
file: targetPath,
|
|
106678
|
+
status: "error",
|
|
106679
|
+
hunks: hunksTotal,
|
|
106680
|
+
hunksApplied: 0,
|
|
106681
|
+
hunksFailed: hunksTotal,
|
|
106682
|
+
errors: hunkResult.error ? [hunkResult.error] : []
|
|
106683
|
+
};
|
|
106684
|
+
}
|
|
106685
|
+
const resultContent = hunkResult.appliedLines.join(`
|
|
106686
|
+
`);
|
|
106687
|
+
if (resultContent === "" && !dryRun && !allowDeletes && content.length > 0) {
|
|
106688
|
+
return {
|
|
106689
|
+
file: targetPath,
|
|
106690
|
+
status: "error",
|
|
106691
|
+
hunks: hunksTotal,
|
|
106692
|
+
hunksApplied: hunksTotal,
|
|
106693
|
+
hunksFailed: 0,
|
|
106694
|
+
errors: [
|
|
106695
|
+
{
|
|
106696
|
+
hunkIndex: 0,
|
|
106697
|
+
type: "delete-not-allowed",
|
|
106698
|
+
message: `Patch would delete all content from ${targetPath}. Set allowDeletes to true to permit file deletion.`
|
|
106699
|
+
}
|
|
106700
|
+
]
|
|
106701
|
+
};
|
|
106702
|
+
}
|
|
106703
|
+
let finalContent;
|
|
106704
|
+
if (resultContent === "") {
|
|
106705
|
+
finalContent = "";
|
|
106706
|
+
} else {
|
|
106707
|
+
const withLineEnding = originalLineEnding === `\r
|
|
106708
|
+
` ? resultContent.replace(/\n/g, `\r
|
|
106709
|
+
`) : resultContent;
|
|
106710
|
+
finalContent = ensureFinalNewline(withLineEnding, originalEndsWithNewline);
|
|
106711
|
+
}
|
|
106712
|
+
if (finalContent === content) {
|
|
106713
|
+
return {
|
|
106714
|
+
file: targetPath,
|
|
106715
|
+
status: "no-changes",
|
|
106716
|
+
hunks: hunksTotal,
|
|
106717
|
+
hunksApplied: hunksTotal,
|
|
106718
|
+
hunksFailed: 0
|
|
106719
|
+
};
|
|
106720
|
+
}
|
|
106721
|
+
if (!dryRun) {
|
|
106722
|
+
atomicWriteFileSync(fullPath, finalContent);
|
|
106723
|
+
}
|
|
106724
|
+
return {
|
|
106725
|
+
file: targetPath,
|
|
106726
|
+
status: "applied",
|
|
106727
|
+
hunks: hunksTotal,
|
|
106728
|
+
hunksApplied: hunksTotal,
|
|
106729
|
+
hunksFailed: 0
|
|
106730
|
+
};
|
|
106731
|
+
}
|
|
106732
|
+
function buildErrorResult(message) {
|
|
106733
|
+
return {
|
|
106734
|
+
success: false,
|
|
106735
|
+
files: [
|
|
106736
|
+
{
|
|
106737
|
+
file: "",
|
|
106738
|
+
status: "error",
|
|
106739
|
+
hunks: 0,
|
|
106740
|
+
hunksApplied: 0,
|
|
106741
|
+
hunksFailed: 0,
|
|
106742
|
+
errors: [
|
|
106743
|
+
{
|
|
106744
|
+
hunkIndex: 0,
|
|
106745
|
+
type: "context-mismatch",
|
|
106746
|
+
message
|
|
106747
|
+
}
|
|
106748
|
+
]
|
|
106749
|
+
}
|
|
106750
|
+
],
|
|
106751
|
+
summary: {
|
|
106752
|
+
totalFiles: 0,
|
|
106753
|
+
applied: 0,
|
|
106754
|
+
failed: 1,
|
|
106755
|
+
totalHunks: 0
|
|
106756
|
+
}
|
|
106757
|
+
};
|
|
106758
|
+
}
|
|
106759
|
+
var applyPatch = createSwarmTool({
|
|
106760
|
+
description: "Apply a unified diff patch to workspace files. Validates paths, matches context exactly, and writes atomically. Coder-scoped write tool.",
|
|
106761
|
+
args: {
|
|
106762
|
+
patch: exports_external.string().min(1).describe("Unified diff text to parse and apply"),
|
|
106763
|
+
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."),
|
|
106764
|
+
dryRun: exports_external.boolean().optional().default(false).describe("Validate without writing files (default: false)"),
|
|
106765
|
+
allowCreates: exports_external.boolean().optional().default(false).describe("Allow creating new files from patches with --- /dev/null (default: false)"),
|
|
106766
|
+
allowDeletes: exports_external.boolean().optional().default(false).describe("Allow deleting files from patches with +++ /dev/null (default: false)")
|
|
106767
|
+
},
|
|
106768
|
+
execute: async (args2, directory) => {
|
|
106769
|
+
if (!args2 || typeof args2 !== "object") {
|
|
106770
|
+
return JSON.stringify(buildErrorResult("Could not parse apply_patch arguments"), null, 2);
|
|
106771
|
+
}
|
|
106772
|
+
const obj = args2;
|
|
106773
|
+
const patchText = obj.patch ?? "";
|
|
106774
|
+
const files = obj.files ?? [];
|
|
106775
|
+
const dryRun = obj.dryRun ?? false;
|
|
106776
|
+
const allowCreates = obj.allowCreates ?? false;
|
|
106777
|
+
const allowDeletes = obj.allowDeletes ?? false;
|
|
106778
|
+
if (!existsSync58(directory)) {
|
|
106779
|
+
return JSON.stringify(buildErrorResult("Workspace directory does not exist"), null, 2);
|
|
106780
|
+
}
|
|
106781
|
+
if (files.length === 0) {
|
|
106782
|
+
return JSON.stringify(buildErrorResult("files array cannot be empty"), null, 2);
|
|
106783
|
+
}
|
|
106784
|
+
if (!patchText || patchText.trim() === "") {
|
|
106785
|
+
return JSON.stringify(buildErrorResult("patch text cannot be empty"), null, 2);
|
|
106786
|
+
}
|
|
106787
|
+
for (const filePath of files) {
|
|
106788
|
+
const validationError = validatePatchTargetPath(filePath, directory);
|
|
106789
|
+
if (validationError) {
|
|
106790
|
+
return JSON.stringify(buildErrorResult(validationError), null, 2);
|
|
106791
|
+
}
|
|
106792
|
+
}
|
|
106793
|
+
const { files: parsedFiles, error: parseError } = parseUnifiedDiff(patchText);
|
|
106794
|
+
if (parseError) {
|
|
106795
|
+
return JSON.stringify(buildErrorResult(parseError), null, 2);
|
|
106796
|
+
}
|
|
106797
|
+
if (parsedFiles.length === 0) {
|
|
106798
|
+
return JSON.stringify({
|
|
106799
|
+
success: true,
|
|
106800
|
+
dryRun,
|
|
106801
|
+
files: [],
|
|
106802
|
+
summary: { totalFiles: 0, applied: 0, failed: 0, totalHunks: 0 }
|
|
106803
|
+
}, null, 2);
|
|
106804
|
+
}
|
|
106805
|
+
const declaredFileSet = new Set(files);
|
|
106806
|
+
const undeclaredTargets = [];
|
|
106807
|
+
for (const fileDiff of parsedFiles) {
|
|
106808
|
+
const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
|
|
106809
|
+
if (targetPath && targetPath !== "/dev/null" && !declaredFileSet.has(targetPath)) {
|
|
106810
|
+
undeclaredTargets.push(targetPath);
|
|
106811
|
+
}
|
|
106812
|
+
}
|
|
106813
|
+
if (undeclaredTargets.length > 0) {
|
|
106814
|
+
return JSON.stringify(buildErrorResult(`Patch targets files not in the declared files array: ${undeclaredTargets.join(", ")}`), null, 2);
|
|
106815
|
+
}
|
|
106816
|
+
const parsedTargetSet = new Set(parsedFiles.map((fd) => fd.isDelete ? fd.oldPath : fd.newPath).filter(Boolean));
|
|
106817
|
+
const extraFiles = files.filter((f) => !parsedTargetSet.has(f));
|
|
106818
|
+
const fileResults = [];
|
|
106819
|
+
let totalApplied = 0;
|
|
106820
|
+
let totalFailed = 0;
|
|
106821
|
+
let totalHunks = 0;
|
|
106822
|
+
for (const fileDiff of parsedFiles) {
|
|
106823
|
+
const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
|
|
106824
|
+
const fullPath = path109.resolve(directory, targetPath);
|
|
106825
|
+
totalHunks += fileDiff.hunks.length;
|
|
106826
|
+
const result = processFileDiff(fileDiff, targetPath, fullPath, directory, dryRun, allowCreates, allowDeletes);
|
|
106827
|
+
fileResults.push(result);
|
|
106828
|
+
if (result.status === "applied" || result.status === "created") {
|
|
106829
|
+
totalApplied++;
|
|
106830
|
+
} else if (result.status === "error") {
|
|
106831
|
+
totalFailed++;
|
|
106832
|
+
}
|
|
106833
|
+
}
|
|
106834
|
+
const output = {
|
|
106835
|
+
success: totalFailed === 0,
|
|
106836
|
+
dryRun,
|
|
106837
|
+
files: fileResults,
|
|
106838
|
+
summary: {
|
|
106839
|
+
totalFiles: fileResults.length,
|
|
106840
|
+
applied: totalApplied,
|
|
106841
|
+
failed: totalFailed,
|
|
106842
|
+
totalHunks
|
|
106843
|
+
}
|
|
106844
|
+
};
|
|
106845
|
+
if (extraFiles.length > 0) {
|
|
106846
|
+
return JSON.stringify({
|
|
106847
|
+
...output,
|
|
106848
|
+
warnings: [
|
|
106849
|
+
`files[] contains entries not targeted by the patch: ${extraFiles.join(", ")}`
|
|
106850
|
+
]
|
|
106851
|
+
}, null, 2);
|
|
106852
|
+
}
|
|
106853
|
+
return JSON.stringify(output, null, 2);
|
|
106854
|
+
}
|
|
106855
|
+
});
|
|
106856
|
+
|
|
105995
106857
|
// src/tools/batch-symbols.ts
|
|
105996
106858
|
init_dist();
|
|
105997
106859
|
init_create_tool();
|
|
105998
106860
|
import * as fs72 from "node:fs";
|
|
105999
|
-
import * as
|
|
106861
|
+
import * as path110 from "node:path";
|
|
106000
106862
|
init_path_security();
|
|
106001
|
-
var
|
|
106002
|
-
function
|
|
106863
|
+
var WINDOWS_RESERVED_NAMES3 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
106864
|
+
function containsWindowsAttacks3(str) {
|
|
106003
106865
|
if (/:[^\\/]/.test(str)) {
|
|
106004
106866
|
return true;
|
|
106005
106867
|
}
|
|
106006
106868
|
const parts2 = str.split(/[/\\]/);
|
|
106007
106869
|
for (const part of parts2) {
|
|
106008
|
-
if (
|
|
106870
|
+
if (WINDOWS_RESERVED_NAMES3.test(part)) {
|
|
106009
106871
|
return true;
|
|
106010
106872
|
}
|
|
106011
106873
|
}
|
|
@@ -106013,14 +106875,14 @@ function containsWindowsAttacks2(str) {
|
|
|
106013
106875
|
}
|
|
106014
106876
|
function isPathInWorkspace2(filePath, workspace) {
|
|
106015
106877
|
try {
|
|
106016
|
-
const resolvedPath =
|
|
106878
|
+
const resolvedPath = path110.resolve(workspace, filePath);
|
|
106017
106879
|
if (!fs72.existsSync(resolvedPath)) {
|
|
106018
106880
|
return true;
|
|
106019
106881
|
}
|
|
106020
106882
|
const realWorkspace = fs72.realpathSync(workspace);
|
|
106021
106883
|
const realResolvedPath = fs72.realpathSync(resolvedPath);
|
|
106022
|
-
const relativePath =
|
|
106023
|
-
if (relativePath.startsWith("..") ||
|
|
106884
|
+
const relativePath = path110.relative(realWorkspace, realResolvedPath);
|
|
106885
|
+
if (relativePath.startsWith("..") || path110.isAbsolute(relativePath)) {
|
|
106024
106886
|
return false;
|
|
106025
106887
|
}
|
|
106026
106888
|
return true;
|
|
@@ -106029,7 +106891,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
106029
106891
|
}
|
|
106030
106892
|
}
|
|
106031
106893
|
function processFile2(file3, cwd, exportedOnly) {
|
|
106032
|
-
const ext =
|
|
106894
|
+
const ext = path110.extname(file3);
|
|
106033
106895
|
if (containsControlChars(file3)) {
|
|
106034
106896
|
return {
|
|
106035
106897
|
file: file3,
|
|
@@ -106046,7 +106908,7 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
106046
106908
|
errorType: "path-traversal"
|
|
106047
106909
|
};
|
|
106048
106910
|
}
|
|
106049
|
-
if (
|
|
106911
|
+
if (containsWindowsAttacks3(file3)) {
|
|
106050
106912
|
return {
|
|
106051
106913
|
file: file3,
|
|
106052
106914
|
success: false,
|
|
@@ -106062,7 +106924,7 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
106062
106924
|
errorType: "path-outside-workspace"
|
|
106063
106925
|
};
|
|
106064
106926
|
}
|
|
106065
|
-
const fullPath =
|
|
106927
|
+
const fullPath = path110.join(cwd, file3);
|
|
106066
106928
|
if (!fs72.existsSync(fullPath)) {
|
|
106067
106929
|
return {
|
|
106068
106930
|
file: file3,
|
|
@@ -106356,15 +107218,15 @@ init_task_id();
|
|
|
106356
107218
|
init_create_tool();
|
|
106357
107219
|
init_resolve_working_directory();
|
|
106358
107220
|
import * as fs73 from "node:fs";
|
|
106359
|
-
import * as
|
|
107221
|
+
import * as path111 from "node:path";
|
|
106360
107222
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
106361
107223
|
function isValidTaskId3(taskId) {
|
|
106362
107224
|
return isStrictTaskId(taskId);
|
|
106363
107225
|
}
|
|
106364
107226
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
106365
|
-
const normalizedWorkspace =
|
|
106366
|
-
const swarmPath =
|
|
106367
|
-
const normalizedPath =
|
|
107227
|
+
const normalizedWorkspace = path111.resolve(workspaceRoot);
|
|
107228
|
+
const swarmPath = path111.join(normalizedWorkspace, ".swarm", "evidence");
|
|
107229
|
+
const normalizedPath = path111.resolve(filePath);
|
|
106368
107230
|
return normalizedPath.startsWith(swarmPath);
|
|
106369
107231
|
}
|
|
106370
107232
|
function readEvidenceFile(evidencePath) {
|
|
@@ -106445,7 +107307,7 @@ var check_gate_status = createSwarmTool({
|
|
|
106445
107307
|
};
|
|
106446
107308
|
return JSON.stringify(errorResult, null, 2);
|
|
106447
107309
|
}
|
|
106448
|
-
const evidencePath =
|
|
107310
|
+
const evidencePath = path111.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
106449
107311
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
106450
107312
|
const errorResult = {
|
|
106451
107313
|
taskId: taskIdInput,
|
|
@@ -106542,7 +107404,7 @@ init_state();
|
|
|
106542
107404
|
init_create_tool();
|
|
106543
107405
|
init_resolve_working_directory();
|
|
106544
107406
|
import * as fs74 from "node:fs";
|
|
106545
|
-
import * as
|
|
107407
|
+
import * as path112 from "node:path";
|
|
106546
107408
|
function extractMatches(regex, text) {
|
|
106547
107409
|
return Array.from(text.matchAll(regex));
|
|
106548
107410
|
}
|
|
@@ -106694,10 +107556,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
106694
107556
|
let hasFileReadFailure = false;
|
|
106695
107557
|
for (const filePath of fileTargets) {
|
|
106696
107558
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
106697
|
-
const resolvedPath =
|
|
106698
|
-
const projectRoot =
|
|
106699
|
-
const
|
|
106700
|
-
const withinProject =
|
|
107559
|
+
const resolvedPath = path112.resolve(directory, normalizedPath);
|
|
107560
|
+
const projectRoot = path112.resolve(directory);
|
|
107561
|
+
const relative23 = path112.relative(projectRoot, resolvedPath);
|
|
107562
|
+
const withinProject = relative23 === "" || !relative23.startsWith("..") && !path112.isAbsolute(relative23);
|
|
106701
107563
|
if (!withinProject) {
|
|
106702
107564
|
blockedTasks.push({
|
|
106703
107565
|
task_id: task.id,
|
|
@@ -106752,8 +107614,8 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
106752
107614
|
blockedTasks
|
|
106753
107615
|
};
|
|
106754
107616
|
try {
|
|
106755
|
-
const evidenceDir =
|
|
106756
|
-
const evidencePath =
|
|
107617
|
+
const evidenceDir = path112.join(directory, ".swarm", "evidence", `${phase}`);
|
|
107618
|
+
const evidencePath = path112.join(evidenceDir, "completion-verify.json");
|
|
106757
107619
|
fs74.mkdirSync(evidenceDir, { recursive: true });
|
|
106758
107620
|
const evidenceBundle = {
|
|
106759
107621
|
schema_version: "1.0.0",
|
|
@@ -106831,11 +107693,11 @@ var completion_verify = createSwarmTool({
|
|
|
106831
107693
|
// src/tools/complexity-hotspots.ts
|
|
106832
107694
|
init_zod();
|
|
106833
107695
|
import * as fs76 from "node:fs";
|
|
106834
|
-
import * as
|
|
107696
|
+
import * as path114 from "node:path";
|
|
106835
107697
|
|
|
106836
107698
|
// src/quality/metrics.ts
|
|
106837
107699
|
import * as fs75 from "node:fs";
|
|
106838
|
-
import * as
|
|
107700
|
+
import * as path113 from "node:path";
|
|
106839
107701
|
var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
|
|
106840
107702
|
var MIN_DUPLICATION_LINES = 10;
|
|
106841
107703
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -106887,7 +107749,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
106887
107749
|
let totalComplexity = 0;
|
|
106888
107750
|
const analyzedFiles = [];
|
|
106889
107751
|
for (const file3 of files) {
|
|
106890
|
-
const fullPath =
|
|
107752
|
+
const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
|
|
106891
107753
|
if (!fs75.existsSync(fullPath)) {
|
|
106892
107754
|
continue;
|
|
106893
107755
|
}
|
|
@@ -107010,7 +107872,7 @@ function countGoExports(content) {
|
|
|
107010
107872
|
function getExportCountForFile(filePath) {
|
|
107011
107873
|
try {
|
|
107012
107874
|
const content = fs75.readFileSync(filePath, "utf-8");
|
|
107013
|
-
const ext =
|
|
107875
|
+
const ext = path113.extname(filePath).toLowerCase();
|
|
107014
107876
|
switch (ext) {
|
|
107015
107877
|
case ".ts":
|
|
107016
107878
|
case ".tsx":
|
|
@@ -107036,7 +107898,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
107036
107898
|
let totalExports = 0;
|
|
107037
107899
|
const analyzedFiles = [];
|
|
107038
107900
|
for (const file3 of files) {
|
|
107039
|
-
const fullPath =
|
|
107901
|
+
const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
|
|
107040
107902
|
if (!fs75.existsSync(fullPath)) {
|
|
107041
107903
|
continue;
|
|
107042
107904
|
}
|
|
@@ -107070,7 +107932,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
107070
107932
|
let duplicateLines = 0;
|
|
107071
107933
|
const analyzedFiles = [];
|
|
107072
107934
|
for (const file3 of files) {
|
|
107073
|
-
const fullPath =
|
|
107935
|
+
const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
|
|
107074
107936
|
if (!fs75.existsSync(fullPath)) {
|
|
107075
107937
|
continue;
|
|
107076
107938
|
}
|
|
@@ -107103,8 +107965,8 @@ function countCodeLines(content) {
|
|
|
107103
107965
|
return lines.length;
|
|
107104
107966
|
}
|
|
107105
107967
|
function isTestFile(filePath) {
|
|
107106
|
-
const basename16 =
|
|
107107
|
-
const _ext =
|
|
107968
|
+
const basename16 = path113.basename(filePath);
|
|
107969
|
+
const _ext = path113.extname(filePath).toLowerCase();
|
|
107108
107970
|
const testPatterns = [
|
|
107109
107971
|
".test.",
|
|
107110
107972
|
".spec.",
|
|
@@ -107185,8 +108047,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
107185
108047
|
}
|
|
107186
108048
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
107187
108049
|
}
|
|
107188
|
-
function matchesGlobSegment(
|
|
107189
|
-
const normalizedPath =
|
|
108050
|
+
function matchesGlobSegment(path114, glob) {
|
|
108051
|
+
const normalizedPath = path114.replace(/\\/g, "/");
|
|
107190
108052
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
107191
108053
|
if (normalizedPath.includes("//")) {
|
|
107192
108054
|
return false;
|
|
@@ -107217,8 +108079,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
107217
108079
|
function hasGlobstar(glob) {
|
|
107218
108080
|
return glob.includes("**");
|
|
107219
108081
|
}
|
|
107220
|
-
function globMatches(
|
|
107221
|
-
const normalizedPath =
|
|
108082
|
+
function globMatches(path114, glob) {
|
|
108083
|
+
const normalizedPath = path114.replace(/\\/g, "/");
|
|
107222
108084
|
if (!glob || glob === "") {
|
|
107223
108085
|
if (normalizedPath.includes("//")) {
|
|
107224
108086
|
return false;
|
|
@@ -107254,7 +108116,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
107254
108116
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
107255
108117
|
let testLines = 0;
|
|
107256
108118
|
let codeLines = 0;
|
|
107257
|
-
const srcDir =
|
|
108119
|
+
const srcDir = path113.join(workingDir, "src");
|
|
107258
108120
|
if (fs75.existsSync(srcDir)) {
|
|
107259
108121
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
107260
108122
|
codeLines += lines;
|
|
@@ -107262,14 +108124,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
107262
108124
|
}
|
|
107263
108125
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
107264
108126
|
for (const dir of possibleSrcDirs) {
|
|
107265
|
-
const dirPath =
|
|
108127
|
+
const dirPath = path113.join(workingDir, dir);
|
|
107266
108128
|
if (fs75.existsSync(dirPath)) {
|
|
107267
108129
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
107268
108130
|
codeLines += lines;
|
|
107269
108131
|
});
|
|
107270
108132
|
}
|
|
107271
108133
|
}
|
|
107272
|
-
const testsDir =
|
|
108134
|
+
const testsDir = path113.join(workingDir, "tests");
|
|
107273
108135
|
if (fs75.existsSync(testsDir)) {
|
|
107274
108136
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
107275
108137
|
testLines += lines;
|
|
@@ -107277,7 +108139,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
107277
108139
|
}
|
|
107278
108140
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
107279
108141
|
for (const dir of possibleTestDirs) {
|
|
107280
|
-
const dirPath =
|
|
108142
|
+
const dirPath = path113.join(workingDir, dir);
|
|
107281
108143
|
if (fs75.existsSync(dirPath) && dirPath !== testsDir) {
|
|
107282
108144
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
107283
108145
|
testLines += lines;
|
|
@@ -107292,7 +108154,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
107292
108154
|
try {
|
|
107293
108155
|
const entries = fs75.readdirSync(dirPath, { withFileTypes: true });
|
|
107294
108156
|
for (const entry of entries) {
|
|
107295
|
-
const fullPath =
|
|
108157
|
+
const fullPath = path113.join(dirPath, entry.name);
|
|
107296
108158
|
if (entry.isDirectory()) {
|
|
107297
108159
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
107298
108160
|
continue;
|
|
@@ -107300,7 +108162,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
107300
108162
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
107301
108163
|
} else if (entry.isFile()) {
|
|
107302
108164
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
107303
|
-
const ext =
|
|
108165
|
+
const ext = path113.extname(entry.name).toLowerCase();
|
|
107304
108166
|
const validExts = [
|
|
107305
108167
|
".ts",
|
|
107306
108168
|
".tsx",
|
|
@@ -107551,7 +108413,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
107551
108413
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
107552
108414
|
const filteredChurn = new Map;
|
|
107553
108415
|
for (const [file3, count] of churnMap) {
|
|
107554
|
-
const ext =
|
|
108416
|
+
const ext = path114.extname(file3).toLowerCase();
|
|
107555
108417
|
if (extSet.has(ext)) {
|
|
107556
108418
|
filteredChurn.set(file3, count);
|
|
107557
108419
|
}
|
|
@@ -107562,7 +108424,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
107562
108424
|
for (const [file3, churnCount] of filteredChurn) {
|
|
107563
108425
|
let fullPath = file3;
|
|
107564
108426
|
if (!fs76.existsSync(fullPath)) {
|
|
107565
|
-
fullPath =
|
|
108427
|
+
fullPath = path114.join(cwd, file3);
|
|
107566
108428
|
}
|
|
107567
108429
|
const complexity = getComplexityForFile2(fullPath);
|
|
107568
108430
|
if (complexity !== null) {
|
|
@@ -107731,8 +108593,8 @@ ${body2}`);
|
|
|
107731
108593
|
|
|
107732
108594
|
// src/council/council-evidence-writer.ts
|
|
107733
108595
|
init_task_file();
|
|
107734
|
-
import { appendFileSync as appendFileSync12, existsSync as
|
|
107735
|
-
import { join as
|
|
108596
|
+
import { appendFileSync as appendFileSync12, existsSync as existsSync63, mkdirSync as mkdirSync29, readFileSync as readFileSync45 } from "node:fs";
|
|
108597
|
+
import { join as join95 } from "node:path";
|
|
107736
108598
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
107737
108599
|
var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
|
|
107738
108600
|
var COUNCIL_GATE_NAME = "council";
|
|
@@ -107769,14 +108631,14 @@ async function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
107769
108631
|
if (!VALID_TASK_ID.test(synthesis.taskId)) {
|
|
107770
108632
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
107771
108633
|
}
|
|
107772
|
-
const dir =
|
|
107773
|
-
|
|
108634
|
+
const dir = join95(workingDir, EVIDENCE_DIR2);
|
|
108635
|
+
mkdirSync29(dir, { recursive: true });
|
|
107774
108636
|
const filePath = taskEvidencePath(workingDir, synthesis.taskId);
|
|
107775
108637
|
await _internals53.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
|
|
107776
108638
|
const existingRoot = Object.create(null);
|
|
107777
|
-
if (
|
|
108639
|
+
if (existsSync63(filePath)) {
|
|
107778
108640
|
try {
|
|
107779
|
-
const parsed = JSON.parse(
|
|
108641
|
+
const parsed = JSON.parse(readFileSync45(filePath, "utf-8"));
|
|
107780
108642
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
107781
108643
|
safeAssignOwnProps(existingRoot, parsed);
|
|
107782
108644
|
}
|
|
@@ -107807,15 +108669,15 @@ async function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
107807
108669
|
await atomicWriteFile(filePath, JSON.stringify(updated, null, 2));
|
|
107808
108670
|
});
|
|
107809
108671
|
try {
|
|
107810
|
-
const councilDir =
|
|
107811
|
-
|
|
108672
|
+
const councilDir = join95(workingDir, ".swarm", "council");
|
|
108673
|
+
mkdirSync29(councilDir, { recursive: true });
|
|
107812
108674
|
const auditLine = JSON.stringify({
|
|
107813
108675
|
round: synthesis.roundNumber,
|
|
107814
108676
|
verdict: synthesis.overallVerdict,
|
|
107815
108677
|
timestamp: synthesis.timestamp,
|
|
107816
108678
|
vetoedBy: synthesis.vetoedBy
|
|
107817
108679
|
});
|
|
107818
|
-
appendFileSync12(
|
|
108680
|
+
appendFileSync12(join95(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
|
|
107819
108681
|
`);
|
|
107820
108682
|
} catch (auditError) {
|
|
107821
108683
|
console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
|
|
@@ -108137,25 +108999,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
|
|
|
108137
108999
|
}
|
|
108138
109000
|
|
|
108139
109001
|
// src/council/criteria-store.ts
|
|
108140
|
-
import { existsSync as
|
|
108141
|
-
import { join as
|
|
109002
|
+
import { existsSync as existsSync64, mkdirSync as mkdirSync30, readFileSync as readFileSync46, writeFileSync as writeFileSync22 } from "node:fs";
|
|
109003
|
+
import { join as join96 } from "node:path";
|
|
108142
109004
|
var COUNCIL_DIR = ".swarm/council";
|
|
108143
109005
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
108144
|
-
const dir =
|
|
108145
|
-
|
|
109006
|
+
const dir = join96(workingDir, COUNCIL_DIR);
|
|
109007
|
+
mkdirSync30(dir, { recursive: true });
|
|
108146
109008
|
const payload = {
|
|
108147
109009
|
taskId,
|
|
108148
109010
|
criteria,
|
|
108149
109011
|
declaredAt: new Date().toISOString()
|
|
108150
109012
|
};
|
|
108151
|
-
|
|
109013
|
+
writeFileSync22(join96(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
|
|
108152
109014
|
}
|
|
108153
109015
|
function readCriteria(workingDir, taskId) {
|
|
108154
|
-
const filePath =
|
|
108155
|
-
if (!
|
|
109016
|
+
const filePath = join96(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
|
|
109017
|
+
if (!existsSync64(filePath))
|
|
108156
109018
|
return null;
|
|
108157
109019
|
try {
|
|
108158
|
-
const parsed = JSON.parse(
|
|
109020
|
+
const parsed = JSON.parse(readFileSync46(filePath, "utf-8"));
|
|
108159
109021
|
if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
|
|
108160
109022
|
return parsed;
|
|
108161
109023
|
}
|
|
@@ -108305,7 +109167,7 @@ var submit_council_verdicts = createSwarmTool({
|
|
|
108305
109167
|
init_zod();
|
|
108306
109168
|
init_loader();
|
|
108307
109169
|
import * as fs77 from "node:fs";
|
|
108308
|
-
import * as
|
|
109170
|
+
import * as path115 from "node:path";
|
|
108309
109171
|
|
|
108310
109172
|
// src/council/general-council-advisory.ts
|
|
108311
109173
|
var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
|
|
@@ -108733,10 +109595,10 @@ var convene_general_council = createSwarmTool({
|
|
|
108733
109595
|
const round1 = input.round1Responses;
|
|
108734
109596
|
const round2 = input.round2Responses ?? [];
|
|
108735
109597
|
const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
|
|
108736
|
-
const evidenceDir =
|
|
109598
|
+
const evidenceDir = path115.join(workingDir, ".swarm", "council", "general");
|
|
108737
109599
|
const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
|
|
108738
109600
|
const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
|
|
108739
|
-
const evidencePath =
|
|
109601
|
+
const evidencePath = path115.join(evidenceDir, evidenceFile);
|
|
108740
109602
|
try {
|
|
108741
109603
|
await fs77.promises.mkdir(evidenceDir, { recursive: true });
|
|
108742
109604
|
await fs77.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
|
|
@@ -109007,7 +109869,7 @@ init_state();
|
|
|
109007
109869
|
init_task_id();
|
|
109008
109870
|
init_create_tool();
|
|
109009
109871
|
import * as fs78 from "node:fs";
|
|
109010
|
-
import * as
|
|
109872
|
+
import * as path116 from "node:path";
|
|
109011
109873
|
function validateTaskIdFormat2(taskId) {
|
|
109012
109874
|
return validateTaskIdFormat(taskId);
|
|
109013
109875
|
}
|
|
@@ -109081,8 +109943,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109081
109943
|
};
|
|
109082
109944
|
}
|
|
109083
109945
|
}
|
|
109084
|
-
normalizedDir =
|
|
109085
|
-
const pathParts = normalizedDir.split(
|
|
109946
|
+
normalizedDir = path116.normalize(args2.working_directory);
|
|
109947
|
+
const pathParts = normalizedDir.split(path116.sep);
|
|
109086
109948
|
if (pathParts.includes("..")) {
|
|
109087
109949
|
return {
|
|
109088
109950
|
success: false,
|
|
@@ -109092,10 +109954,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109092
109954
|
]
|
|
109093
109955
|
};
|
|
109094
109956
|
}
|
|
109095
|
-
const resolvedDir =
|
|
109957
|
+
const resolvedDir = path116.resolve(normalizedDir);
|
|
109096
109958
|
try {
|
|
109097
109959
|
const realPath = fs78.realpathSync(resolvedDir);
|
|
109098
|
-
const planPath2 =
|
|
109960
|
+
const planPath2 = path116.join(realPath, ".swarm", "plan.json");
|
|
109099
109961
|
if (!fs78.existsSync(planPath2)) {
|
|
109100
109962
|
return {
|
|
109101
109963
|
success: false,
|
|
@@ -109116,9 +109978,9 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109116
109978
|
}
|
|
109117
109979
|
if (normalizedDir && fallbackDir) {
|
|
109118
109980
|
try {
|
|
109119
|
-
const canonicalWorkingDir = fs78.realpathSync(
|
|
109120
|
-
const canonicalProjectRoot = fs78.realpathSync(
|
|
109121
|
-
if (canonicalWorkingDir.startsWith(canonicalProjectRoot +
|
|
109981
|
+
const canonicalWorkingDir = fs78.realpathSync(path116.resolve(normalizedDir));
|
|
109982
|
+
const canonicalProjectRoot = fs78.realpathSync(path116.resolve(fallbackDir));
|
|
109983
|
+
if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path116.sep)) {
|
|
109122
109984
|
return {
|
|
109123
109985
|
success: false,
|
|
109124
109986
|
message: `working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,
|
|
@@ -109140,7 +110002,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109140
110002
|
};
|
|
109141
110003
|
}
|
|
109142
110004
|
const directory = normalizedDir || fallbackDir;
|
|
109143
|
-
const planPath =
|
|
110005
|
+
const planPath = path116.resolve(directory, ".swarm", "plan.json");
|
|
109144
110006
|
if (!fs78.existsSync(planPath)) {
|
|
109145
110007
|
return {
|
|
109146
110008
|
success: false,
|
|
@@ -109180,8 +110042,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
109180
110042
|
const normalizeErrors = [];
|
|
109181
110043
|
const dir = directory;
|
|
109182
110044
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
109183
|
-
if (
|
|
109184
|
-
const relativePath =
|
|
110045
|
+
if (path116.isAbsolute(file3)) {
|
|
110046
|
+
const relativePath = path116.relative(dir, file3).replace(/\\/g, "/");
|
|
109185
110047
|
if (relativePath.startsWith("..")) {
|
|
109186
110048
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
109187
110049
|
return file3;
|
|
@@ -109243,7 +110105,7 @@ var declare_scope = createSwarmTool({
|
|
|
109243
110105
|
init_zod();
|
|
109244
110106
|
import * as child_process7 from "node:child_process";
|
|
109245
110107
|
import * as fs79 from "node:fs";
|
|
109246
|
-
import * as
|
|
110108
|
+
import * as path117 from "node:path";
|
|
109247
110109
|
init_create_tool();
|
|
109248
110110
|
var MAX_DIFF_LINES = 500;
|
|
109249
110111
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -109272,20 +110134,20 @@ function validateBase(base) {
|
|
|
109272
110134
|
function validatePaths(paths) {
|
|
109273
110135
|
if (!paths)
|
|
109274
110136
|
return null;
|
|
109275
|
-
for (const
|
|
109276
|
-
if (!
|
|
110137
|
+
for (const path118 of paths) {
|
|
110138
|
+
if (!path118 || path118.length === 0) {
|
|
109277
110139
|
return "empty path not allowed";
|
|
109278
110140
|
}
|
|
109279
|
-
if (
|
|
110141
|
+
if (path118.length > MAX_PATH_LENGTH) {
|
|
109280
110142
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
109281
110143
|
}
|
|
109282
|
-
if (SHELL_METACHARACTERS2.test(
|
|
110144
|
+
if (SHELL_METACHARACTERS2.test(path118)) {
|
|
109283
110145
|
return "path contains shell metacharacters";
|
|
109284
110146
|
}
|
|
109285
|
-
if (
|
|
110147
|
+
if (path118.startsWith("-")) {
|
|
109286
110148
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
109287
110149
|
}
|
|
109288
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
110150
|
+
if (CONTROL_CHAR_PATTERN2.test(path118)) {
|
|
109289
110151
|
return "path contains control characters";
|
|
109290
110152
|
}
|
|
109291
110153
|
}
|
|
@@ -109393,8 +110255,8 @@ var diff = createSwarmTool({
|
|
|
109393
110255
|
if (parts2.length >= 3) {
|
|
109394
110256
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
109395
110257
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
109396
|
-
const
|
|
109397
|
-
files.push({ path:
|
|
110258
|
+
const path118 = parts2[2];
|
|
110259
|
+
files.push({ path: path118, additions, deletions });
|
|
109398
110260
|
}
|
|
109399
110261
|
}
|
|
109400
110262
|
const contractChanges = [];
|
|
@@ -109433,7 +110295,7 @@ var diff = createSwarmTool({
|
|
|
109433
110295
|
} else if (base === "unstaged") {
|
|
109434
110296
|
const oldRef = `:${file3.path}`;
|
|
109435
110297
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
109436
|
-
newContent = fs79.readFileSync(
|
|
110298
|
+
newContent = fs79.readFileSync(path117.join(directory, file3.path), "utf-8");
|
|
109437
110299
|
} else {
|
|
109438
110300
|
const oldRef = `${base}:${file3.path}`;
|
|
109439
110301
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
@@ -109510,12 +110372,12 @@ var diff = createSwarmTool({
|
|
|
109510
110372
|
init_zod();
|
|
109511
110373
|
import * as child_process8 from "node:child_process";
|
|
109512
110374
|
import * as fs80 from "node:fs";
|
|
109513
|
-
import * as
|
|
110375
|
+
import * as path118 from "node:path";
|
|
109514
110376
|
init_create_tool();
|
|
109515
110377
|
init_resolve_working_directory();
|
|
109516
110378
|
async function execGit2(workingDir, args2, options) {
|
|
109517
110379
|
try {
|
|
109518
|
-
const stdout = await new Promise((
|
|
110380
|
+
const stdout = await new Promise((resolve41, reject) => {
|
|
109519
110381
|
const execOpts = {
|
|
109520
110382
|
encoding: "utf-8",
|
|
109521
110383
|
cwd: workingDir,
|
|
@@ -109528,7 +110390,7 @@ async function execGit2(workingDir, args2, options) {
|
|
|
109528
110390
|
reject(error93);
|
|
109529
110391
|
return;
|
|
109530
110392
|
}
|
|
109531
|
-
|
|
110393
|
+
resolve41(output ?? "");
|
|
109532
110394
|
});
|
|
109533
110395
|
});
|
|
109534
110396
|
return stdout;
|
|
@@ -109579,7 +110441,7 @@ var diff_summary = createSwarmTool({
|
|
|
109579
110441
|
}
|
|
109580
110442
|
try {
|
|
109581
110443
|
let oldContent;
|
|
109582
|
-
const newContent = await fs80.promises.readFile(
|
|
110444
|
+
const newContent = await fs80.promises.readFile(path118.join(workingDir, filePath), "utf-8");
|
|
109583
110445
|
if (fileExistsInHead) {
|
|
109584
110446
|
oldContent = await execGit2(workingDir, ["show", `HEAD:${filePath}`], {
|
|
109585
110447
|
timeout: 5000,
|
|
@@ -109809,7 +110671,7 @@ init_zod();
|
|
|
109809
110671
|
init_create_tool();
|
|
109810
110672
|
init_path_security();
|
|
109811
110673
|
import * as fs81 from "node:fs";
|
|
109812
|
-
import * as
|
|
110674
|
+
import * as path119 from "node:path";
|
|
109813
110675
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
109814
110676
|
var MAX_EVIDENCE_FILES = 1000;
|
|
109815
110677
|
var EVIDENCE_DIR3 = ".swarm/evidence";
|
|
@@ -109836,9 +110698,9 @@ function validateRequiredTypes(input) {
|
|
|
109836
110698
|
return null;
|
|
109837
110699
|
}
|
|
109838
110700
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
109839
|
-
const normalizedCwd =
|
|
109840
|
-
const swarmPath =
|
|
109841
|
-
const normalizedPath =
|
|
110701
|
+
const normalizedCwd = path119.resolve(cwd);
|
|
110702
|
+
const swarmPath = path119.join(normalizedCwd, ".swarm");
|
|
110703
|
+
const normalizedPath = path119.resolve(filePath);
|
|
109842
110704
|
return normalizedPath.startsWith(swarmPath);
|
|
109843
110705
|
}
|
|
109844
110706
|
function parseCompletedTasks(planContent) {
|
|
@@ -109868,10 +110730,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
109868
110730
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
109869
110731
|
continue;
|
|
109870
110732
|
}
|
|
109871
|
-
const filePath =
|
|
110733
|
+
const filePath = path119.join(evidenceDir, filename);
|
|
109872
110734
|
try {
|
|
109873
|
-
const resolvedPath =
|
|
109874
|
-
const evidenceDirResolved =
|
|
110735
|
+
const resolvedPath = path119.resolve(filePath);
|
|
110736
|
+
const evidenceDirResolved = path119.resolve(evidenceDir);
|
|
109875
110737
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
109876
110738
|
continue;
|
|
109877
110739
|
}
|
|
@@ -109989,7 +110851,7 @@ var evidence_check = createSwarmTool({
|
|
|
109989
110851
|
return JSON.stringify(errorResult, null, 2);
|
|
109990
110852
|
}
|
|
109991
110853
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
109992
|
-
const planPath =
|
|
110854
|
+
const planPath = path119.join(cwd, PLAN_FILE);
|
|
109993
110855
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
109994
110856
|
const errorResult = {
|
|
109995
110857
|
error: "plan file path validation failed",
|
|
@@ -110021,7 +110883,7 @@ var evidence_check = createSwarmTool({
|
|
|
110021
110883
|
};
|
|
110022
110884
|
return JSON.stringify(result2, null, 2);
|
|
110023
110885
|
}
|
|
110024
|
-
const evidenceDir =
|
|
110886
|
+
const evidenceDir = path119.join(cwd, EVIDENCE_DIR3);
|
|
110025
110887
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
110026
110888
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
110027
110889
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -110040,7 +110902,7 @@ var evidence_check = createSwarmTool({
|
|
|
110040
110902
|
init_zod();
|
|
110041
110903
|
init_create_tool();
|
|
110042
110904
|
import * as fs82 from "node:fs";
|
|
110043
|
-
import * as
|
|
110905
|
+
import * as path120 from "node:path";
|
|
110044
110906
|
var EXT_MAP = {
|
|
110045
110907
|
python: ".py",
|
|
110046
110908
|
py: ".py",
|
|
@@ -110121,12 +110983,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
110121
110983
|
if (prefix) {
|
|
110122
110984
|
filename = `${prefix}_${filename}`;
|
|
110123
110985
|
}
|
|
110124
|
-
let filepath =
|
|
110125
|
-
const base =
|
|
110126
|
-
const ext =
|
|
110986
|
+
let filepath = path120.join(targetDir, filename);
|
|
110987
|
+
const base = path120.basename(filepath, path120.extname(filepath));
|
|
110988
|
+
const ext = path120.extname(filepath);
|
|
110127
110989
|
let counter = 1;
|
|
110128
110990
|
while (fs82.existsSync(filepath)) {
|
|
110129
|
-
filepath =
|
|
110991
|
+
filepath = path120.join(targetDir, `${base}_${counter}${ext}`);
|
|
110130
110992
|
counter++;
|
|
110131
110993
|
}
|
|
110132
110994
|
try {
|
|
@@ -110468,7 +111330,7 @@ init_create_tool();
|
|
|
110468
111330
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
110469
111331
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
110470
111332
|
var GITINGEST_MAX_RETRIES = 2;
|
|
110471
|
-
var delay = (ms) => new Promise((
|
|
111333
|
+
var delay = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
|
|
110472
111334
|
async function fetchGitingest(args2) {
|
|
110473
111335
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
110474
111336
|
try {
|
|
@@ -110557,7 +111419,7 @@ init_zod();
|
|
|
110557
111419
|
init_create_tool();
|
|
110558
111420
|
init_path_security();
|
|
110559
111421
|
import * as fs83 from "node:fs";
|
|
110560
|
-
import * as
|
|
111422
|
+
import * as path121 from "node:path";
|
|
110561
111423
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
110562
111424
|
var MAX_SYMBOL_LENGTH = 256;
|
|
110563
111425
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -110605,7 +111467,7 @@ function validateSymbolInput(symbol3) {
|
|
|
110605
111467
|
return null;
|
|
110606
111468
|
}
|
|
110607
111469
|
function isBinaryFile2(filePath, buffer) {
|
|
110608
|
-
const ext =
|
|
111470
|
+
const ext = path121.extname(filePath).toLowerCase();
|
|
110609
111471
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
110610
111472
|
return false;
|
|
110611
111473
|
}
|
|
@@ -110629,15 +111491,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
110629
111491
|
const imports = [];
|
|
110630
111492
|
let _resolvedTarget;
|
|
110631
111493
|
try {
|
|
110632
|
-
_resolvedTarget =
|
|
111494
|
+
_resolvedTarget = path121.resolve(targetFile);
|
|
110633
111495
|
} catch {
|
|
110634
111496
|
_resolvedTarget = targetFile;
|
|
110635
111497
|
}
|
|
110636
|
-
const targetBasename =
|
|
111498
|
+
const targetBasename = path121.basename(targetFile, path121.extname(targetFile));
|
|
110637
111499
|
const targetWithExt = targetFile;
|
|
110638
111500
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
110639
|
-
const normalizedTargetWithExt =
|
|
110640
|
-
const normalizedTargetWithoutExt =
|
|
111501
|
+
const normalizedTargetWithExt = path121.normalize(targetWithExt).replace(/\\/g, "/");
|
|
111502
|
+
const normalizedTargetWithoutExt = path121.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
110641
111503
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
110642
111504
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
110643
111505
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -110660,9 +111522,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
110660
111522
|
}
|
|
110661
111523
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
110662
111524
|
let isMatch = false;
|
|
110663
|
-
const _targetDir =
|
|
110664
|
-
const targetExt =
|
|
110665
|
-
const targetBasenameNoExt =
|
|
111525
|
+
const _targetDir = path121.dirname(targetFile);
|
|
111526
|
+
const targetExt = path121.extname(targetFile);
|
|
111527
|
+
const targetBasenameNoExt = path121.basename(targetFile, targetExt);
|
|
110666
111528
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
110667
111529
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
110668
111530
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -110730,10 +111592,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
110730
111592
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
110731
111593
|
for (const entry of entries) {
|
|
110732
111594
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
110733
|
-
stats.skippedDirs.push(
|
|
111595
|
+
stats.skippedDirs.push(path121.join(dir, entry));
|
|
110734
111596
|
continue;
|
|
110735
111597
|
}
|
|
110736
|
-
const fullPath =
|
|
111598
|
+
const fullPath = path121.join(dir, entry);
|
|
110737
111599
|
let stat9;
|
|
110738
111600
|
try {
|
|
110739
111601
|
stat9 = fs83.statSync(fullPath);
|
|
@@ -110747,7 +111609,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
110747
111609
|
if (stat9.isDirectory()) {
|
|
110748
111610
|
findSourceFiles2(fullPath, files, stats);
|
|
110749
111611
|
} else if (stat9.isFile()) {
|
|
110750
|
-
const ext =
|
|
111612
|
+
const ext = path121.extname(fullPath).toLowerCase();
|
|
110751
111613
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
110752
111614
|
files.push(fullPath);
|
|
110753
111615
|
}
|
|
@@ -110804,7 +111666,7 @@ var imports = createSwarmTool({
|
|
|
110804
111666
|
return JSON.stringify(errorResult, null, 2);
|
|
110805
111667
|
}
|
|
110806
111668
|
try {
|
|
110807
|
-
const targetFile =
|
|
111669
|
+
const targetFile = path121.resolve(file3);
|
|
110808
111670
|
if (!fs83.existsSync(targetFile)) {
|
|
110809
111671
|
const errorResult = {
|
|
110810
111672
|
error: `target file not found: ${file3}`,
|
|
@@ -110826,7 +111688,7 @@ var imports = createSwarmTool({
|
|
|
110826
111688
|
};
|
|
110827
111689
|
return JSON.stringify(errorResult, null, 2);
|
|
110828
111690
|
}
|
|
110829
|
-
const baseDir =
|
|
111691
|
+
const baseDir = path121.dirname(targetFile);
|
|
110830
111692
|
const scanStats = {
|
|
110831
111693
|
skippedDirs: [],
|
|
110832
111694
|
skippedFiles: 0,
|
|
@@ -111214,7 +112076,7 @@ init_zod();
|
|
|
111214
112076
|
init_config();
|
|
111215
112077
|
init_knowledge_store();
|
|
111216
112078
|
init_create_tool();
|
|
111217
|
-
import { existsSync as
|
|
112079
|
+
import { existsSync as existsSync69 } from "node:fs";
|
|
111218
112080
|
var DEFAULT_LIMIT = 10;
|
|
111219
112081
|
var MAX_LESSON_LENGTH = 200;
|
|
111220
112082
|
var VALID_CATEGORIES3 = [
|
|
@@ -111290,14 +112152,14 @@ function validateLimit(limit) {
|
|
|
111290
112152
|
}
|
|
111291
112153
|
async function readSwarmKnowledge(directory) {
|
|
111292
112154
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
111293
|
-
if (!
|
|
112155
|
+
if (!existsSync69(swarmPath)) {
|
|
111294
112156
|
return [];
|
|
111295
112157
|
}
|
|
111296
112158
|
return readKnowledge(swarmPath);
|
|
111297
112159
|
}
|
|
111298
112160
|
async function readHiveKnowledge() {
|
|
111299
112161
|
const hivePath = resolveHiveKnowledgePath();
|
|
111300
|
-
if (!
|
|
112162
|
+
if (!existsSync69(hivePath)) {
|
|
111301
112163
|
return [];
|
|
111302
112164
|
}
|
|
111303
112165
|
return readKnowledge(hivePath);
|
|
@@ -111723,11 +112585,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
111723
112585
|
init_zod();
|
|
111724
112586
|
init_constants();
|
|
111725
112587
|
import * as fs85 from "node:fs";
|
|
111726
|
-
import * as
|
|
112588
|
+
import * as path123 from "node:path";
|
|
111727
112589
|
|
|
111728
112590
|
// src/turbo/lean/conflicts.ts
|
|
111729
112591
|
import * as fs84 from "node:fs";
|
|
111730
|
-
import * as
|
|
112592
|
+
import * as path122 from "node:path";
|
|
111731
112593
|
var DEFAULT_GLOBAL_FILES = [
|
|
111732
112594
|
"package.json",
|
|
111733
112595
|
"package-lock.json",
|
|
@@ -111830,7 +112692,7 @@ function isGlobalFile(normalizedPath) {
|
|
|
111830
112692
|
}
|
|
111831
112693
|
return false;
|
|
111832
112694
|
}
|
|
111833
|
-
function
|
|
112695
|
+
function isProtectedPath3(normalizedPath) {
|
|
111834
112696
|
const lowerPath = normalizedPath.toLowerCase();
|
|
111835
112697
|
for (const pattern of DEFAULT_PROTECTED_PATTERNS) {
|
|
111836
112698
|
if (lowerPath.includes(pattern.toLowerCase())) {
|
|
@@ -111854,7 +112716,7 @@ function isProtectedPath2(normalizedPath) {
|
|
|
111854
112716
|
return false;
|
|
111855
112717
|
}
|
|
111856
112718
|
function readTaskScopes(directory, taskId) {
|
|
111857
|
-
const scopePath =
|
|
112719
|
+
const scopePath = path122.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
111858
112720
|
try {
|
|
111859
112721
|
if (!fs84.existsSync(scopePath)) {
|
|
111860
112722
|
return null;
|
|
@@ -111880,7 +112742,7 @@ function assessTaskRisk(files, hasDeclaredScope, hasInvalidScope, config3) {
|
|
|
111880
112742
|
files: globalFiles
|
|
111881
112743
|
};
|
|
111882
112744
|
}
|
|
111883
|
-
const protectedFiles = files.filter(
|
|
112745
|
+
const protectedFiles = files.filter(isProtectedPath3);
|
|
111884
112746
|
if (protectedFiles.length > 0) {
|
|
111885
112747
|
return {
|
|
111886
112748
|
category: "protected",
|
|
@@ -112242,7 +113104,7 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
112242
113104
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
112243
113105
|
init_create_tool();
|
|
112244
113106
|
function readPlanJson(directory) {
|
|
112245
|
-
const planPath =
|
|
113107
|
+
const planPath = path123.join(directory, ".swarm", "plan.json");
|
|
112246
113108
|
if (!fs85.existsSync(planPath)) {
|
|
112247
113109
|
return null;
|
|
112248
113110
|
}
|
|
@@ -112298,15 +113160,15 @@ init_config();
|
|
|
112298
113160
|
// src/turbo/lean/reviewer.ts
|
|
112299
113161
|
init_state();
|
|
112300
113162
|
import * as fs87 from "node:fs/promises";
|
|
112301
|
-
import * as
|
|
113163
|
+
import * as path125 from "node:path";
|
|
112302
113164
|
|
|
112303
113165
|
// src/turbo/lean/evidence.ts
|
|
112304
113166
|
init_bun_compat();
|
|
112305
113167
|
import { rmSync as rmSync6 } from "node:fs";
|
|
112306
113168
|
import * as fs86 from "node:fs/promises";
|
|
112307
|
-
import * as
|
|
113169
|
+
import * as path124 from "node:path";
|
|
112308
113170
|
function leanTurboEvidenceDir(directory, phase) {
|
|
112309
|
-
return
|
|
113171
|
+
return path124.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
112310
113172
|
}
|
|
112311
113173
|
function validateLaneId(laneId) {
|
|
112312
113174
|
if (laneId.length === 0) {
|
|
@@ -112328,16 +113190,16 @@ function validateLaneId(laneId) {
|
|
|
112328
113190
|
function laneEvidencePath(directory, phase, laneId) {
|
|
112329
113191
|
validateLaneId(laneId);
|
|
112330
113192
|
const expectedDir = leanTurboEvidenceDir(directory, phase);
|
|
112331
|
-
const resolvedPath =
|
|
112332
|
-
const resolvedDir =
|
|
112333
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
113193
|
+
const resolvedPath = path124.resolve(path124.join(expectedDir, `${laneId}.json`));
|
|
113194
|
+
const resolvedDir = path124.resolve(expectedDir);
|
|
113195
|
+
if (!resolvedPath.startsWith(resolvedDir + path124.sep) && resolvedPath !== resolvedDir) {
|
|
112334
113196
|
throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
|
|
112335
113197
|
}
|
|
112336
113198
|
return resolvedPath;
|
|
112337
113199
|
}
|
|
112338
113200
|
async function atomicWriteJson(filePath, data) {
|
|
112339
113201
|
const content = JSON.stringify(data, null, 2);
|
|
112340
|
-
const dir =
|
|
113202
|
+
const dir = path124.dirname(filePath);
|
|
112341
113203
|
await fs86.mkdir(dir, { recursive: true });
|
|
112342
113204
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
112343
113205
|
try {
|
|
@@ -112351,7 +113213,7 @@ async function atomicWriteJson(filePath, data) {
|
|
|
112351
113213
|
}
|
|
112352
113214
|
}
|
|
112353
113215
|
function phaseEvidencePath(directory, phase) {
|
|
112354
|
-
return
|
|
113216
|
+
return path124.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
|
|
112355
113217
|
}
|
|
112356
113218
|
async function writeLaneEvidence(directory, phase, evidence) {
|
|
112357
113219
|
const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
|
|
@@ -112395,7 +113257,7 @@ async function listLaneEvidence(directory, phase) {
|
|
|
112395
113257
|
if (entry === "lean-turbo-phase.json") {
|
|
112396
113258
|
continue;
|
|
112397
113259
|
}
|
|
112398
|
-
const filePath =
|
|
113260
|
+
const filePath = path124.join(evidenceDir, entry);
|
|
112399
113261
|
let content;
|
|
112400
113262
|
try {
|
|
112401
113263
|
content = await fs86.readFile(filePath, "utf-8");
|
|
@@ -112526,9 +113388,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
112526
113388
|
return { verdict, reason };
|
|
112527
113389
|
}
|
|
112528
113390
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
112529
|
-
const evidenceDir =
|
|
113391
|
+
const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
|
|
112530
113392
|
await fs87.mkdir(evidenceDir, { recursive: true });
|
|
112531
|
-
const evidencePath =
|
|
113393
|
+
const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
|
|
112532
113394
|
const content = JSON.stringify({
|
|
112533
113395
|
phase,
|
|
112534
113396
|
verdict,
|
|
@@ -113340,7 +114202,7 @@ init_lint();
|
|
|
113340
114202
|
init_spec_schema();
|
|
113341
114203
|
init_create_tool();
|
|
113342
114204
|
import * as fs88 from "node:fs";
|
|
113343
|
-
import * as
|
|
114205
|
+
import * as path126 from "node:path";
|
|
113344
114206
|
var SPEC_FILE_NAME = "spec.md";
|
|
113345
114207
|
var SWARM_DIR2 = ".swarm";
|
|
113346
114208
|
var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -113393,7 +114255,7 @@ var lint_spec = createSwarmTool({
|
|
|
113393
114255
|
async execute(_args, directory) {
|
|
113394
114256
|
const errors5 = [];
|
|
113395
114257
|
const warnings = [];
|
|
113396
|
-
const specPath =
|
|
114258
|
+
const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
113397
114259
|
if (!fs88.existsSync(specPath)) {
|
|
113398
114260
|
const result2 = {
|
|
113399
114261
|
valid: false,
|
|
@@ -113465,12 +114327,12 @@ var lint_spec = createSwarmTool({
|
|
|
113465
114327
|
// src/tools/mutation-test.ts
|
|
113466
114328
|
init_zod();
|
|
113467
114329
|
import * as fs89 from "node:fs";
|
|
113468
|
-
import * as
|
|
114330
|
+
import * as path128 from "node:path";
|
|
113469
114331
|
|
|
113470
114332
|
// src/mutation/engine.ts
|
|
113471
114333
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
113472
|
-
import { unlinkSync as
|
|
113473
|
-
import * as
|
|
114334
|
+
import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync24 } from "node:fs";
|
|
114335
|
+
import * as path127 from "node:path";
|
|
113474
114336
|
|
|
113475
114337
|
// src/mutation/equivalence.ts
|
|
113476
114338
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -113616,9 +114478,9 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
113616
114478
|
let patchFile;
|
|
113617
114479
|
try {
|
|
113618
114480
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
113619
|
-
patchFile =
|
|
114481
|
+
patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
113620
114482
|
try {
|
|
113621
|
-
|
|
114483
|
+
writeFileSync24(patchFile, patch.patch);
|
|
113622
114484
|
} catch (writeErr) {
|
|
113623
114485
|
error93 = `Failed to write patch file: ${writeErr}`;
|
|
113624
114486
|
outcome = "error";
|
|
@@ -113714,7 +114576,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
113714
114576
|
revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
|
|
113715
114577
|
}
|
|
113716
114578
|
try {
|
|
113717
|
-
|
|
114579
|
+
unlinkSync18(patchFile);
|
|
113718
114580
|
} catch (_unlinkErr) {}
|
|
113719
114581
|
}
|
|
113720
114582
|
}
|
|
@@ -114020,7 +114882,7 @@ var mutation_test = createSwarmTool({
|
|
|
114020
114882
|
];
|
|
114021
114883
|
for (const filePath of uniquePaths) {
|
|
114022
114884
|
try {
|
|
114023
|
-
const resolvedPath =
|
|
114885
|
+
const resolvedPath = path128.resolve(cwd, filePath);
|
|
114024
114886
|
sourceFiles.set(filePath, fs89.readFileSync(resolvedPath, "utf-8"));
|
|
114025
114887
|
} catch {}
|
|
114026
114888
|
}
|
|
@@ -114042,22 +114904,22 @@ init_config();
|
|
|
114042
114904
|
init_schema();
|
|
114043
114905
|
init_manager2();
|
|
114044
114906
|
import * as fs99 from "node:fs";
|
|
114045
|
-
import * as
|
|
114907
|
+
import * as path138 from "node:path";
|
|
114046
114908
|
|
|
114047
114909
|
// src/full-auto/phase-approval.ts
|
|
114048
114910
|
init_utils2();
|
|
114049
114911
|
init_logger();
|
|
114050
114912
|
init_state2();
|
|
114051
114913
|
import * as fs90 from "node:fs";
|
|
114052
|
-
import * as
|
|
114914
|
+
import * as path129 from "node:path";
|
|
114053
114915
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
114054
114916
|
function readEvidenceDir(directory, phase) {
|
|
114055
114917
|
try {
|
|
114056
|
-
const dirPath = validateSwarmPath(directory,
|
|
114918
|
+
const dirPath = validateSwarmPath(directory, path129.posix.join("evidence", String(phase)));
|
|
114057
114919
|
if (!fs90.existsSync(dirPath))
|
|
114058
114920
|
return [];
|
|
114059
114921
|
const entries = fs90.readdirSync(dirPath);
|
|
114060
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
114922
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path129.join(dirPath, e));
|
|
114061
114923
|
} catch {
|
|
114062
114924
|
return [];
|
|
114063
114925
|
}
|
|
@@ -114198,16 +115060,16 @@ init_plan_schema();
|
|
|
114198
115060
|
init_ledger();
|
|
114199
115061
|
init_manager();
|
|
114200
115062
|
import * as fs91 from "node:fs";
|
|
114201
|
-
import * as
|
|
115063
|
+
import * as path130 from "node:path";
|
|
114202
115064
|
async function writeCheckpoint(directory) {
|
|
114203
115065
|
try {
|
|
114204
115066
|
const plan = await loadPlan(directory);
|
|
114205
115067
|
if (!plan)
|
|
114206
115068
|
return;
|
|
114207
|
-
const swarmDir =
|
|
115069
|
+
const swarmDir = path130.join(directory, ".swarm");
|
|
114208
115070
|
fs91.mkdirSync(swarmDir, { recursive: true });
|
|
114209
|
-
const jsonPath =
|
|
114210
|
-
const mdPath =
|
|
115071
|
+
const jsonPath = path130.join(swarmDir, "SWARM_PLAN.json");
|
|
115072
|
+
const mdPath = path130.join(swarmDir, "SWARM_PLAN.md");
|
|
114211
115073
|
fs91.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
114212
115074
|
const md = derivePlanMarkdown(plan);
|
|
114213
115075
|
fs91.writeFileSync(mdPath, md, "utf8");
|
|
@@ -114226,7 +115088,7 @@ init_telemetry();
|
|
|
114226
115088
|
// src/turbo/lean/phase-ready.ts
|
|
114227
115089
|
init_file_locks();
|
|
114228
115090
|
import * as fs92 from "node:fs";
|
|
114229
|
-
import * as
|
|
115091
|
+
import * as path131 from "node:path";
|
|
114230
115092
|
init_state3();
|
|
114231
115093
|
var DEFAULT_CONFIG3 = {
|
|
114232
115094
|
phase_reviewer: true,
|
|
@@ -114235,7 +115097,7 @@ var DEFAULT_CONFIG3 = {
|
|
|
114235
115097
|
};
|
|
114236
115098
|
function defaultReadPlanJson(dir) {
|
|
114237
115099
|
try {
|
|
114238
|
-
const planPath =
|
|
115100
|
+
const planPath = path131.join(dir, ".swarm", "plan.json");
|
|
114239
115101
|
if (!fs92.existsSync(planPath))
|
|
114240
115102
|
return null;
|
|
114241
115103
|
const raw = fs92.readFileSync(planPath, "utf-8");
|
|
@@ -114250,7 +115112,7 @@ function defaultReadPlanJson(dir) {
|
|
|
114250
115112
|
}
|
|
114251
115113
|
function readReviewerEvidenceFromFile(directory, phase) {
|
|
114252
115114
|
try {
|
|
114253
|
-
const evidencePath =
|
|
115115
|
+
const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
|
|
114254
115116
|
if (!fs92.existsSync(evidencePath)) {
|
|
114255
115117
|
return null;
|
|
114256
115118
|
}
|
|
@@ -114270,7 +115132,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
|
|
|
114270
115132
|
}
|
|
114271
115133
|
function readCriticEvidenceFromFile(directory, phase) {
|
|
114272
115134
|
try {
|
|
114273
|
-
const evidencePath =
|
|
115135
|
+
const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
|
|
114274
115136
|
if (!fs92.existsSync(evidencePath)) {
|
|
114275
115137
|
return null;
|
|
114276
115138
|
}
|
|
@@ -114289,7 +115151,7 @@ function readCriticEvidenceFromFile(directory, phase) {
|
|
|
114289
115151
|
}
|
|
114290
115152
|
}
|
|
114291
115153
|
function listLaneEvidenceSync(directory, phase) {
|
|
114292
|
-
const evidenceDir =
|
|
115154
|
+
const evidenceDir = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
114293
115155
|
let entries;
|
|
114294
115156
|
try {
|
|
114295
115157
|
entries = fs92.readdirSync(evidenceDir);
|
|
@@ -114359,7 +115221,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
114359
115221
|
...DEFAULT_CONFIG3,
|
|
114360
115222
|
...actualConfig
|
|
114361
115223
|
};
|
|
114362
|
-
const statePath =
|
|
115224
|
+
const statePath = path131.join(directory, ".swarm", "turbo-state.json");
|
|
114363
115225
|
if (!fs92.existsSync(statePath)) {
|
|
114364
115226
|
return {
|
|
114365
115227
|
ok: false,
|
|
@@ -114547,7 +115409,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
114547
115409
|
}
|
|
114548
115410
|
}
|
|
114549
115411
|
if (mergedConfig.integrated_diff_required) {
|
|
114550
|
-
const evidencePath =
|
|
115412
|
+
const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
|
|
114551
115413
|
let hasDiff = false;
|
|
114552
115414
|
try {
|
|
114553
115415
|
const content = fs92.readFileSync(evidencePath, "utf-8");
|
|
@@ -114699,13 +115561,13 @@ init_qa_gate_profile();
|
|
|
114699
115561
|
init_manager();
|
|
114700
115562
|
init_state();
|
|
114701
115563
|
import * as fs93 from "node:fs";
|
|
114702
|
-
import * as
|
|
115564
|
+
import * as path132 from "node:path";
|
|
114703
115565
|
async function runDriftGate(ctx) {
|
|
114704
115566
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
114705
115567
|
let driftCheckEnabled = true;
|
|
114706
115568
|
let driftHasSpecMd = false;
|
|
114707
115569
|
try {
|
|
114708
|
-
const specMdPath =
|
|
115570
|
+
const specMdPath = path132.join(dir, ".swarm", "spec.md");
|
|
114709
115571
|
driftHasSpecMd = fs93.existsSync(specMdPath);
|
|
114710
115572
|
const gatePlan = await loadPlan(dir);
|
|
114711
115573
|
if (gatePlan) {
|
|
@@ -114733,7 +115595,7 @@ async function runDriftGate(ctx) {
|
|
|
114733
115595
|
}
|
|
114734
115596
|
let phaseType;
|
|
114735
115597
|
try {
|
|
114736
|
-
const planPath =
|
|
115598
|
+
const planPath = path132.join(dir, ".swarm", "plan.json");
|
|
114737
115599
|
if (fs93.existsSync(planPath)) {
|
|
114738
115600
|
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
114739
115601
|
const plan = JSON.parse(planRaw);
|
|
@@ -114752,7 +115614,7 @@ async function runDriftGate(ctx) {
|
|
|
114752
115614
|
};
|
|
114753
115615
|
}
|
|
114754
115616
|
try {
|
|
114755
|
-
const driftEvidencePath =
|
|
115617
|
+
const driftEvidencePath = path132.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
114756
115618
|
let driftVerdictFound = false;
|
|
114757
115619
|
let driftVerdictApproved = false;
|
|
114758
115620
|
try {
|
|
@@ -114788,7 +115650,7 @@ async function runDriftGate(ctx) {
|
|
|
114788
115650
|
let incompleteTaskCount = 0;
|
|
114789
115651
|
let planParseable = false;
|
|
114790
115652
|
try {
|
|
114791
|
-
const planPath =
|
|
115653
|
+
const planPath = path132.join(dir, ".swarm", "plan.json");
|
|
114792
115654
|
if (fs93.existsSync(planPath)) {
|
|
114793
115655
|
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
114794
115656
|
const plan = JSON.parse(planRaw);
|
|
@@ -114870,7 +115732,7 @@ init_qa_gate_profile();
|
|
|
114870
115732
|
init_manager();
|
|
114871
115733
|
init_state();
|
|
114872
115734
|
import * as fs94 from "node:fs";
|
|
114873
|
-
import * as
|
|
115735
|
+
import * as path133 from "node:path";
|
|
114874
115736
|
async function runFinalCouncilGate(ctx) {
|
|
114875
115737
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
114876
115738
|
let finalCouncilEnabled = false;
|
|
@@ -114887,7 +115749,7 @@ async function runFinalCouncilGate(ctx) {
|
|
|
114887
115749
|
const effective = getEffectiveGates(profile, overrides);
|
|
114888
115750
|
if (effective.final_council === true) {
|
|
114889
115751
|
finalCouncilEnabled = true;
|
|
114890
|
-
const fcPath =
|
|
115752
|
+
const fcPath = path133.join(dir, ".swarm", "evidence", "final-council.json");
|
|
114891
115753
|
let fcVerdictFound = false;
|
|
114892
115754
|
let _fcVerdict;
|
|
114893
115755
|
try {
|
|
@@ -115017,7 +115879,7 @@ init_qa_gate_profile();
|
|
|
115017
115879
|
init_manager();
|
|
115018
115880
|
init_state();
|
|
115019
115881
|
import * as fs95 from "node:fs";
|
|
115020
|
-
import * as
|
|
115882
|
+
import * as path134 from "node:path";
|
|
115021
115883
|
async function runHallucinationGate(ctx) {
|
|
115022
115884
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
115023
115885
|
try {
|
|
@@ -115030,7 +115892,7 @@ async function runHallucinationGate(ctx) {
|
|
|
115030
115892
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
115031
115893
|
const effective = getEffectiveGates(profile, overrides);
|
|
115032
115894
|
if (effective.hallucination_guard === true) {
|
|
115033
|
-
const hgPath =
|
|
115895
|
+
const hgPath = path134.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
115034
115896
|
let hgVerdictFound = false;
|
|
115035
115897
|
let hgVerdictApproved = false;
|
|
115036
115898
|
try {
|
|
@@ -115093,7 +115955,7 @@ init_qa_gate_profile();
|
|
|
115093
115955
|
init_manager();
|
|
115094
115956
|
init_state();
|
|
115095
115957
|
import * as fs96 from "node:fs";
|
|
115096
|
-
import * as
|
|
115958
|
+
import * as path135 from "node:path";
|
|
115097
115959
|
async function runMutationGate(ctx) {
|
|
115098
115960
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
115099
115961
|
try {
|
|
@@ -115106,7 +115968,7 @@ async function runMutationGate(ctx) {
|
|
|
115106
115968
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
115107
115969
|
const effective = getEffectiveGates(profile, overrides);
|
|
115108
115970
|
if (effective.mutation_test === true) {
|
|
115109
|
-
const mgPath =
|
|
115971
|
+
const mgPath = path135.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
115110
115972
|
let mgVerdictFound = false;
|
|
115111
115973
|
let mgVerdict;
|
|
115112
115974
|
try {
|
|
@@ -115169,7 +116031,7 @@ init_qa_gate_profile();
|
|
|
115169
116031
|
init_manager();
|
|
115170
116032
|
init_state();
|
|
115171
116033
|
import * as fs97 from "node:fs";
|
|
115172
|
-
import * as
|
|
116034
|
+
import * as path136 from "node:path";
|
|
115173
116035
|
async function runPhaseCouncilGate(ctx) {
|
|
115174
116036
|
const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
|
|
115175
116037
|
let councilModeEnabled = false;
|
|
@@ -115184,7 +116046,7 @@ async function runPhaseCouncilGate(ctx) {
|
|
|
115184
116046
|
const effective = getEffectiveGates(profile, overrides);
|
|
115185
116047
|
if (effective.council_mode === true) {
|
|
115186
116048
|
councilModeEnabled = true;
|
|
115187
|
-
const pcPath =
|
|
116049
|
+
const pcPath = path136.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
115188
116050
|
let pcVerdictFound = false;
|
|
115189
116051
|
let _pcVerdict;
|
|
115190
116052
|
let pcQuorumSize;
|
|
@@ -115699,7 +116561,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
115699
116561
|
}
|
|
115700
116562
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
115701
116563
|
try {
|
|
115702
|
-
const projectName =
|
|
116564
|
+
const projectName = path138.basename(dir);
|
|
115703
116565
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
115704
116566
|
if (curationResult) {
|
|
115705
116567
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -116142,7 +117004,7 @@ init_utils();
|
|
|
116142
117004
|
init_bun_compat();
|
|
116143
117005
|
init_create_tool();
|
|
116144
117006
|
import * as fs100 from "node:fs";
|
|
116145
|
-
import * as
|
|
117007
|
+
import * as path139 from "node:path";
|
|
116146
117008
|
var MAX_OUTPUT_BYTES6 = 52428800;
|
|
116147
117009
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
116148
117010
|
function isValidEcosystem(value) {
|
|
@@ -116170,16 +117032,16 @@ function validateArgs3(args2) {
|
|
|
116170
117032
|
function detectEcosystems(directory) {
|
|
116171
117033
|
const ecosystems = [];
|
|
116172
117034
|
const cwd = directory;
|
|
116173
|
-
if (fs100.existsSync(
|
|
117035
|
+
if (fs100.existsSync(path139.join(cwd, "package.json"))) {
|
|
116174
117036
|
ecosystems.push("npm");
|
|
116175
117037
|
}
|
|
116176
|
-
if (fs100.existsSync(
|
|
117038
|
+
if (fs100.existsSync(path139.join(cwd, "pyproject.toml")) || fs100.existsSync(path139.join(cwd, "requirements.txt"))) {
|
|
116177
117039
|
ecosystems.push("pip");
|
|
116178
117040
|
}
|
|
116179
|
-
if (fs100.existsSync(
|
|
117041
|
+
if (fs100.existsSync(path139.join(cwd, "Cargo.toml"))) {
|
|
116180
117042
|
ecosystems.push("cargo");
|
|
116181
117043
|
}
|
|
116182
|
-
if (fs100.existsSync(
|
|
117044
|
+
if (fs100.existsSync(path139.join(cwd, "go.mod"))) {
|
|
116183
117045
|
ecosystems.push("go");
|
|
116184
117046
|
}
|
|
116185
117047
|
try {
|
|
@@ -116188,13 +117050,13 @@ function detectEcosystems(directory) {
|
|
|
116188
117050
|
ecosystems.push("dotnet");
|
|
116189
117051
|
}
|
|
116190
117052
|
} catch {}
|
|
116191
|
-
if (fs100.existsSync(
|
|
117053
|
+
if (fs100.existsSync(path139.join(cwd, "Gemfile")) || fs100.existsSync(path139.join(cwd, "Gemfile.lock"))) {
|
|
116192
117054
|
ecosystems.push("ruby");
|
|
116193
117055
|
}
|
|
116194
|
-
if (fs100.existsSync(
|
|
117056
|
+
if (fs100.existsSync(path139.join(cwd, "pubspec.yaml"))) {
|
|
116195
117057
|
ecosystems.push("dart");
|
|
116196
117058
|
}
|
|
116197
|
-
if (fs100.existsSync(
|
|
117059
|
+
if (fs100.existsSync(path139.join(cwd, "composer.lock"))) {
|
|
116198
117060
|
ecosystems.push("composer");
|
|
116199
117061
|
}
|
|
116200
117062
|
return ecosystems;
|
|
@@ -116207,7 +117069,7 @@ async function runNpmAudit(directory) {
|
|
|
116207
117069
|
stderr: "pipe",
|
|
116208
117070
|
cwd: directory
|
|
116209
117071
|
});
|
|
116210
|
-
const timeoutPromise = new Promise((
|
|
117072
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116211
117073
|
const result = await Promise.race([
|
|
116212
117074
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
116213
117075
|
timeoutPromise
|
|
@@ -116327,7 +117189,7 @@ async function runPipAudit(directory) {
|
|
|
116327
117189
|
stderr: "pipe",
|
|
116328
117190
|
cwd: directory
|
|
116329
117191
|
});
|
|
116330
|
-
const timeoutPromise = new Promise((
|
|
117192
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116331
117193
|
const result = await Promise.race([
|
|
116332
117194
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
116333
117195
|
timeoutPromise
|
|
@@ -116455,7 +117317,7 @@ async function runCargoAudit(directory) {
|
|
|
116455
117317
|
stderr: "pipe",
|
|
116456
117318
|
cwd: directory
|
|
116457
117319
|
});
|
|
116458
|
-
const timeoutPromise = new Promise((
|
|
117320
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116459
117321
|
const result = await Promise.race([
|
|
116460
117322
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116461
117323
|
timeoutPromise
|
|
@@ -116579,7 +117441,7 @@ async function runGoAudit(directory) {
|
|
|
116579
117441
|
stderr: "pipe",
|
|
116580
117442
|
cwd: directory
|
|
116581
117443
|
});
|
|
116582
|
-
const timeoutPromise = new Promise((
|
|
117444
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116583
117445
|
const result = await Promise.race([
|
|
116584
117446
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116585
117447
|
timeoutPromise
|
|
@@ -116712,7 +117574,7 @@ async function runDotnetAudit(directory) {
|
|
|
116712
117574
|
stderr: "pipe",
|
|
116713
117575
|
cwd: directory
|
|
116714
117576
|
});
|
|
116715
|
-
const timeoutPromise = new Promise((
|
|
117577
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116716
117578
|
const result = await Promise.race([
|
|
116717
117579
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116718
117580
|
timeoutPromise
|
|
@@ -116828,7 +117690,7 @@ async function runBundleAudit(directory) {
|
|
|
116828
117690
|
stderr: "pipe",
|
|
116829
117691
|
cwd: directory
|
|
116830
117692
|
});
|
|
116831
|
-
const timeoutPromise = new Promise((
|
|
117693
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116832
117694
|
const result = await Promise.race([
|
|
116833
117695
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116834
117696
|
timeoutPromise
|
|
@@ -116973,7 +117835,7 @@ async function runDartAudit(directory) {
|
|
|
116973
117835
|
stderr: "pipe",
|
|
116974
117836
|
cwd: directory
|
|
116975
117837
|
});
|
|
116976
|
-
const timeoutPromise = new Promise((
|
|
117838
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
116977
117839
|
const result = await Promise.race([
|
|
116978
117840
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
116979
117841
|
timeoutPromise
|
|
@@ -117088,7 +117950,7 @@ async function runComposerAudit(directory) {
|
|
|
117088
117950
|
stderr: "pipe",
|
|
117089
117951
|
cwd: directory
|
|
117090
117952
|
});
|
|
117091
|
-
const timeoutPromise = new Promise((
|
|
117953
|
+
const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
|
|
117092
117954
|
const result = await Promise.race([
|
|
117093
117955
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
117094
117956
|
timeoutPromise
|
|
@@ -117331,7 +118193,7 @@ var pkg_audit = createSwarmTool({
|
|
|
117331
118193
|
init_zod();
|
|
117332
118194
|
init_manager2();
|
|
117333
118195
|
import * as fs101 from "node:fs";
|
|
117334
|
-
import * as
|
|
118196
|
+
import * as path140 from "node:path";
|
|
117335
118197
|
init_utils();
|
|
117336
118198
|
init_create_tool();
|
|
117337
118199
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -117454,7 +118316,7 @@ function isScaffoldFile(filePath) {
|
|
|
117454
118316
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
117455
118317
|
return true;
|
|
117456
118318
|
}
|
|
117457
|
-
const filename =
|
|
118319
|
+
const filename = path140.basename(filePath);
|
|
117458
118320
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
117459
118321
|
return true;
|
|
117460
118322
|
}
|
|
@@ -117471,7 +118333,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
117471
118333
|
if (regex.test(normalizedPath)) {
|
|
117472
118334
|
return true;
|
|
117473
118335
|
}
|
|
117474
|
-
const filename =
|
|
118336
|
+
const filename = path140.basename(filePath);
|
|
117475
118337
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
117476
118338
|
if (filenameRegex.test(filename)) {
|
|
117477
118339
|
return true;
|
|
@@ -117480,7 +118342,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
117480
118342
|
return false;
|
|
117481
118343
|
}
|
|
117482
118344
|
function isParserSupported(filePath) {
|
|
117483
|
-
const ext =
|
|
118345
|
+
const ext = path140.extname(filePath).toLowerCase();
|
|
117484
118346
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
117485
118347
|
}
|
|
117486
118348
|
function isPlanFile(filePath) {
|
|
@@ -117727,9 +118589,9 @@ async function placeholderScan(input, directory) {
|
|
|
117727
118589
|
let filesScanned = 0;
|
|
117728
118590
|
const filesWithFindings = new Set;
|
|
117729
118591
|
for (const filePath of changed_files) {
|
|
117730
|
-
const fullPath =
|
|
117731
|
-
const resolvedDirectory =
|
|
117732
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
118592
|
+
const fullPath = path140.isAbsolute(filePath) ? filePath : path140.resolve(directory, filePath);
|
|
118593
|
+
const resolvedDirectory = path140.resolve(directory);
|
|
118594
|
+
if (!fullPath.startsWith(resolvedDirectory + path140.sep) && fullPath !== resolvedDirectory) {
|
|
117733
118595
|
continue;
|
|
117734
118596
|
}
|
|
117735
118597
|
if (!fs101.existsSync(fullPath)) {
|
|
@@ -117738,7 +118600,7 @@ async function placeholderScan(input, directory) {
|
|
|
117738
118600
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
117739
118601
|
continue;
|
|
117740
118602
|
}
|
|
117741
|
-
const relativeFilePath =
|
|
118603
|
+
const relativeFilePath = path140.relative(directory, fullPath).replace(/\\/g, "/");
|
|
117742
118604
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
117743
118605
|
continue;
|
|
117744
118606
|
}
|
|
@@ -117811,7 +118673,7 @@ var placeholder_scan = createSwarmTool({
|
|
|
117811
118673
|
|
|
117812
118674
|
// src/tools/pre-check-batch.ts
|
|
117813
118675
|
import * as fs105 from "node:fs";
|
|
117814
|
-
import * as
|
|
118676
|
+
import * as path144 from "node:path";
|
|
117815
118677
|
init_zod();
|
|
117816
118678
|
init_manager2();
|
|
117817
118679
|
init_utils();
|
|
@@ -117952,7 +118814,7 @@ init_zod();
|
|
|
117952
118814
|
init_manager2();
|
|
117953
118815
|
init_detector();
|
|
117954
118816
|
import * as fs104 from "node:fs";
|
|
117955
|
-
import * as
|
|
118817
|
+
import * as path143 from "node:path";
|
|
117956
118818
|
import { extname as extname20 } from "node:path";
|
|
117957
118819
|
|
|
117958
118820
|
// src/sast/rules/c.ts
|
|
@@ -118668,7 +119530,7 @@ function executeRulesSync(filePath, content, language) {
|
|
|
118668
119530
|
// src/sast/semgrep.ts
|
|
118669
119531
|
import * as child_process9 from "node:child_process";
|
|
118670
119532
|
import * as fs102 from "node:fs";
|
|
118671
|
-
import * as
|
|
119533
|
+
import * as path141 from "node:path";
|
|
118672
119534
|
var semgrepAvailableCache = null;
|
|
118673
119535
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
118674
119536
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
@@ -118749,7 +119611,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
118749
119611
|
}
|
|
118750
119612
|
}
|
|
118751
119613
|
async function executeWithTimeout(command, args2, options) {
|
|
118752
|
-
return new Promise((
|
|
119614
|
+
return new Promise((resolve48) => {
|
|
118753
119615
|
const child = child_process9.spawn(command, args2, {
|
|
118754
119616
|
shell: false,
|
|
118755
119617
|
cwd: options.cwd
|
|
@@ -118758,7 +119620,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
118758
119620
|
let stderr = "";
|
|
118759
119621
|
const timeout = setTimeout(() => {
|
|
118760
119622
|
child.kill("SIGTERM");
|
|
118761
|
-
|
|
119623
|
+
resolve48({
|
|
118762
119624
|
stdout,
|
|
118763
119625
|
stderr: "Process timed out",
|
|
118764
119626
|
exitCode: 124
|
|
@@ -118772,7 +119634,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
118772
119634
|
});
|
|
118773
119635
|
child.on("close", (code) => {
|
|
118774
119636
|
clearTimeout(timeout);
|
|
118775
|
-
|
|
119637
|
+
resolve48({
|
|
118776
119638
|
stdout,
|
|
118777
119639
|
stderr,
|
|
118778
119640
|
exitCode: code ?? 0
|
|
@@ -118780,7 +119642,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
118780
119642
|
});
|
|
118781
119643
|
child.on("error", (err2) => {
|
|
118782
119644
|
clearTimeout(timeout);
|
|
118783
|
-
|
|
119645
|
+
resolve48({
|
|
118784
119646
|
stdout,
|
|
118785
119647
|
stderr: err2.message,
|
|
118786
119648
|
exitCode: 1
|
|
@@ -118855,7 +119717,7 @@ async function runSemgrep(options) {
|
|
|
118855
119717
|
}
|
|
118856
119718
|
function getRulesDirectory(projectRoot) {
|
|
118857
119719
|
if (projectRoot) {
|
|
118858
|
-
return
|
|
119720
|
+
return path141.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
118859
119721
|
}
|
|
118860
119722
|
return DEFAULT_RULES_DIR;
|
|
118861
119723
|
}
|
|
@@ -118876,24 +119738,24 @@ init_create_tool();
|
|
|
118876
119738
|
init_utils2();
|
|
118877
119739
|
import * as crypto11 from "node:crypto";
|
|
118878
119740
|
import * as fs103 from "node:fs";
|
|
118879
|
-
import * as
|
|
119741
|
+
import * as path142 from "node:path";
|
|
118880
119742
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
118881
119743
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
118882
119744
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
118883
119745
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
118884
119746
|
function normalizeFindingPath(directory, file3) {
|
|
118885
|
-
const resolved =
|
|
118886
|
-
const rel =
|
|
119747
|
+
const resolved = path142.isAbsolute(file3) ? file3 : path142.resolve(directory, file3);
|
|
119748
|
+
const rel = path142.relative(path142.resolve(directory), resolved);
|
|
118887
119749
|
return rel.replace(/\\/g, "/");
|
|
118888
119750
|
}
|
|
118889
119751
|
function baselineRelPath(phase) {
|
|
118890
|
-
return
|
|
119752
|
+
return path142.join("evidence", String(phase), "sast-baseline.json");
|
|
118891
119753
|
}
|
|
118892
119754
|
function tempRelPath(phase) {
|
|
118893
|
-
return
|
|
119755
|
+
return path142.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
118894
119756
|
}
|
|
118895
119757
|
function lockRelPath(phase) {
|
|
118896
|
-
return
|
|
119758
|
+
return path142.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
118897
119759
|
}
|
|
118898
119760
|
function getLine(lines, idx) {
|
|
118899
119761
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -118979,7 +119841,7 @@ async function acquireLock2(lockPath) {
|
|
|
118979
119841
|
};
|
|
118980
119842
|
} catch {
|
|
118981
119843
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
118982
|
-
await new Promise((
|
|
119844
|
+
await new Promise((resolve49) => setTimeout(resolve49, LOCK_RETRY_DELAYS_MS[attempt]));
|
|
118983
119845
|
}
|
|
118984
119846
|
}
|
|
118985
119847
|
}
|
|
@@ -119014,8 +119876,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
119014
119876
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
119015
119877
|
};
|
|
119016
119878
|
}
|
|
119017
|
-
fs103.mkdirSync(
|
|
119018
|
-
fs103.mkdirSync(
|
|
119879
|
+
fs103.mkdirSync(path142.dirname(baselinePath), { recursive: true });
|
|
119880
|
+
fs103.mkdirSync(path142.dirname(tempPath), { recursive: true });
|
|
119019
119881
|
const releaseLock = await acquireLock2(lockPath);
|
|
119020
119882
|
try {
|
|
119021
119883
|
let existing = null;
|
|
@@ -119288,9 +120150,9 @@ async function sastScan(input, directory, config3) {
|
|
|
119288
120150
|
_filesSkipped++;
|
|
119289
120151
|
continue;
|
|
119290
120152
|
}
|
|
119291
|
-
const resolvedPath =
|
|
119292
|
-
const resolvedDirectory =
|
|
119293
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
120153
|
+
const resolvedPath = path143.isAbsolute(filePath) ? filePath : path143.resolve(directory, filePath);
|
|
120154
|
+
const resolvedDirectory = path143.resolve(directory);
|
|
120155
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path143.sep) && resolvedPath !== resolvedDirectory) {
|
|
119294
120156
|
_filesSkipped++;
|
|
119295
120157
|
continue;
|
|
119296
120158
|
}
|
|
@@ -119605,20 +120467,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
119605
120467
|
let resolved;
|
|
119606
120468
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
119607
120469
|
if (isWinAbs) {
|
|
119608
|
-
resolved =
|
|
119609
|
-
} else if (
|
|
119610
|
-
resolved =
|
|
120470
|
+
resolved = path144.win32.resolve(inputPath);
|
|
120471
|
+
} else if (path144.isAbsolute(inputPath)) {
|
|
120472
|
+
resolved = path144.resolve(inputPath);
|
|
119611
120473
|
} else {
|
|
119612
|
-
resolved =
|
|
120474
|
+
resolved = path144.resolve(baseDir, inputPath);
|
|
119613
120475
|
}
|
|
119614
|
-
const workspaceResolved =
|
|
119615
|
-
let
|
|
120476
|
+
const workspaceResolved = path144.resolve(workspaceDir);
|
|
120477
|
+
let relative28;
|
|
119616
120478
|
if (isWinAbs) {
|
|
119617
|
-
|
|
120479
|
+
relative28 = path144.win32.relative(workspaceResolved, resolved);
|
|
119618
120480
|
} else {
|
|
119619
|
-
|
|
120481
|
+
relative28 = path144.relative(workspaceResolved, resolved);
|
|
119620
120482
|
}
|
|
119621
|
-
if (
|
|
120483
|
+
if (relative28.startsWith("..")) {
|
|
119622
120484
|
return "path traversal detected";
|
|
119623
120485
|
}
|
|
119624
120486
|
return null;
|
|
@@ -119681,7 +120543,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
119681
120543
|
if (typeof file3 !== "string") {
|
|
119682
120544
|
continue;
|
|
119683
120545
|
}
|
|
119684
|
-
const resolvedPath =
|
|
120546
|
+
const resolvedPath = path144.resolve(file3);
|
|
119685
120547
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
119686
120548
|
if (validationError) {
|
|
119687
120549
|
continue;
|
|
@@ -119838,7 +120700,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
119838
120700
|
skippedFiles++;
|
|
119839
120701
|
continue;
|
|
119840
120702
|
}
|
|
119841
|
-
const resolvedPath =
|
|
120703
|
+
const resolvedPath = path144.resolve(file3);
|
|
119842
120704
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
119843
120705
|
if (validationError) {
|
|
119844
120706
|
skippedFiles++;
|
|
@@ -119856,7 +120718,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
119856
120718
|
};
|
|
119857
120719
|
}
|
|
119858
120720
|
for (const file3 of validatedFiles) {
|
|
119859
|
-
const ext =
|
|
120721
|
+
const ext = path144.extname(file3).toLowerCase();
|
|
119860
120722
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
119861
120723
|
skippedFiles++;
|
|
119862
120724
|
continue;
|
|
@@ -120075,7 +120937,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
120075
120937
|
const preexistingFindings = [];
|
|
120076
120938
|
for (const finding of findings) {
|
|
120077
120939
|
const filePath = finding.location.file;
|
|
120078
|
-
const normalised =
|
|
120940
|
+
const normalised = path144.relative(directory, filePath).replace(/\\/g, "/");
|
|
120079
120941
|
const changedLines = changedLineRanges.get(normalised);
|
|
120080
120942
|
if (changedLines?.has(finding.location.line)) {
|
|
120081
120943
|
newFindings.push(finding);
|
|
@@ -120126,7 +120988,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
120126
120988
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
120127
120989
|
continue;
|
|
120128
120990
|
}
|
|
120129
|
-
changedFiles.push(
|
|
120991
|
+
changedFiles.push(path144.resolve(directory, file3));
|
|
120130
120992
|
}
|
|
120131
120993
|
if (changedFiles.length === 0) {
|
|
120132
120994
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -120327,9 +121189,9 @@ var pre_check_batch = createSwarmTool({
|
|
|
120327
121189
|
};
|
|
120328
121190
|
return JSON.stringify(errorResult, null, 2);
|
|
120329
121191
|
}
|
|
120330
|
-
const resolvedDirectory =
|
|
120331
|
-
const workspaceAnchor =
|
|
120332
|
-
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor +
|
|
121192
|
+
const resolvedDirectory = path144.resolve(typedArgs.directory);
|
|
121193
|
+
const workspaceAnchor = path144.resolve(directory);
|
|
121194
|
+
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path144.sep)) {
|
|
120333
121195
|
const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
|
|
120334
121196
|
const subDirResult = {
|
|
120335
121197
|
gates_passed: false,
|
|
@@ -120381,7 +121243,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
120381
121243
|
|
|
120382
121244
|
// src/tools/repo-map.ts
|
|
120383
121245
|
init_zod();
|
|
120384
|
-
import * as
|
|
121246
|
+
import * as path145 from "node:path";
|
|
120385
121247
|
init_path_security();
|
|
120386
121248
|
init_create_tool();
|
|
120387
121249
|
var VALID_ACTIONS = [
|
|
@@ -120406,7 +121268,7 @@ function validateFile(p) {
|
|
|
120406
121268
|
return "file contains control characters";
|
|
120407
121269
|
if (containsPathTraversal(p))
|
|
120408
121270
|
return "file contains path traversal";
|
|
120409
|
-
if (
|
|
121271
|
+
if (path145.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
120410
121272
|
return "file must be a workspace-relative path, not absolute";
|
|
120411
121273
|
}
|
|
120412
121274
|
return null;
|
|
@@ -120429,8 +121291,8 @@ function ok(action, payload) {
|
|
|
120429
121291
|
}
|
|
120430
121292
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
120431
121293
|
const normalized = input.replace(/\\/g, "/");
|
|
120432
|
-
if (
|
|
120433
|
-
const rel =
|
|
121294
|
+
if (path145.isAbsolute(normalized)) {
|
|
121295
|
+
const rel = path145.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
120434
121296
|
return normalizeGraphPath2(rel);
|
|
120435
121297
|
}
|
|
120436
121298
|
return normalizeGraphPath2(normalized);
|
|
@@ -120576,7 +121438,7 @@ var repo_map = createSwarmTool({
|
|
|
120576
121438
|
init_zod();
|
|
120577
121439
|
init_create_tool();
|
|
120578
121440
|
import * as fs106 from "node:fs";
|
|
120579
|
-
import * as
|
|
121441
|
+
import * as path146 from "node:path";
|
|
120580
121442
|
var SPEC_FILE = ".swarm/spec.md";
|
|
120581
121443
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
120582
121444
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -120645,7 +121507,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120645
121507
|
return [];
|
|
120646
121508
|
}
|
|
120647
121509
|
for (const entry of entries) {
|
|
120648
|
-
const entryPath =
|
|
121510
|
+
const entryPath = path146.join(evidenceDir, entry);
|
|
120649
121511
|
try {
|
|
120650
121512
|
const stat9 = fs106.statSync(entryPath);
|
|
120651
121513
|
if (!stat9.isDirectory()) {
|
|
@@ -120661,11 +121523,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120661
121523
|
if (entryPhase !== String(phase)) {
|
|
120662
121524
|
continue;
|
|
120663
121525
|
}
|
|
120664
|
-
const evidenceFilePath =
|
|
121526
|
+
const evidenceFilePath = path146.join(entryPath, "evidence.json");
|
|
120665
121527
|
try {
|
|
120666
|
-
const resolvedPath =
|
|
120667
|
-
const evidenceDirResolved =
|
|
120668
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
121528
|
+
const resolvedPath = path146.resolve(evidenceFilePath);
|
|
121529
|
+
const evidenceDirResolved = path146.resolve(evidenceDir);
|
|
121530
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path146.sep)) {
|
|
120669
121531
|
continue;
|
|
120670
121532
|
}
|
|
120671
121533
|
const stat9 = fs106.lstatSync(evidenceFilePath);
|
|
@@ -120699,7 +121561,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120699
121561
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
120700
121562
|
for (const file3 of diffEntry.files_changed) {
|
|
120701
121563
|
if (typeof file3 === "string") {
|
|
120702
|
-
touchedFiles.add(
|
|
121564
|
+
touchedFiles.add(path146.resolve(cwd, file3));
|
|
120703
121565
|
}
|
|
120704
121566
|
}
|
|
120705
121567
|
}
|
|
@@ -120712,8 +121574,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
120712
121574
|
}
|
|
120713
121575
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
120714
121576
|
try {
|
|
120715
|
-
const resolvedPath =
|
|
120716
|
-
const cwdResolved =
|
|
121577
|
+
const resolvedPath = path146.resolve(filePath);
|
|
121578
|
+
const cwdResolved = path146.resolve(cwd);
|
|
120717
121579
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
120718
121580
|
return false;
|
|
120719
121581
|
}
|
|
@@ -120847,7 +121709,7 @@ var req_coverage = createSwarmTool({
|
|
|
120847
121709
|
}, null, 2);
|
|
120848
121710
|
}
|
|
120849
121711
|
const cwd = inputDirectory || directory;
|
|
120850
|
-
const specPath =
|
|
121712
|
+
const specPath = path146.join(cwd, SPEC_FILE);
|
|
120851
121713
|
let specContent;
|
|
120852
121714
|
try {
|
|
120853
121715
|
specContent = fs106.readFileSync(specPath, "utf-8");
|
|
@@ -120874,7 +121736,7 @@ var req_coverage = createSwarmTool({
|
|
|
120874
121736
|
message: "No FR requirements found in spec.md"
|
|
120875
121737
|
}, null, 2);
|
|
120876
121738
|
}
|
|
120877
|
-
const evidenceDir =
|
|
121739
|
+
const evidenceDir = path146.join(cwd, EVIDENCE_DIR4);
|
|
120878
121740
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
120879
121741
|
const analyzedRequirements = [];
|
|
120880
121742
|
let coveredCount = 0;
|
|
@@ -120900,7 +121762,7 @@ var req_coverage = createSwarmTool({
|
|
|
120900
121762
|
requirements: analyzedRequirements
|
|
120901
121763
|
};
|
|
120902
121764
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
120903
|
-
const reportPath =
|
|
121765
|
+
const reportPath = path146.join(evidenceDir, reportFilename);
|
|
120904
121766
|
try {
|
|
120905
121767
|
if (!fs106.existsSync(evidenceDir)) {
|
|
120906
121768
|
fs106.mkdirSync(evidenceDir, { recursive: true });
|
|
@@ -120990,7 +121852,7 @@ init_qa_gate_profile();
|
|
|
120990
121852
|
init_file_locks();
|
|
120991
121853
|
import * as crypto12 from "node:crypto";
|
|
120992
121854
|
import * as fs107 from "node:fs";
|
|
120993
|
-
import * as
|
|
121855
|
+
import * as path147 from "node:path";
|
|
120994
121856
|
init_ledger();
|
|
120995
121857
|
init_manager();
|
|
120996
121858
|
init_state();
|
|
@@ -121071,8 +121933,8 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121071
121933
|
};
|
|
121072
121934
|
}
|
|
121073
121935
|
if (args2.working_directory && fallbackDir) {
|
|
121074
|
-
const resolvedTarget =
|
|
121075
|
-
const resolvedRoot =
|
|
121936
|
+
const resolvedTarget = path147.resolve(args2.working_directory);
|
|
121937
|
+
const resolvedRoot = path147.resolve(fallbackDir);
|
|
121076
121938
|
let fallbackExists = false;
|
|
121077
121939
|
try {
|
|
121078
121940
|
fs107.accessSync(resolvedRoot, fs107.constants.F_OK);
|
|
@@ -121081,7 +121943,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121081
121943
|
fallbackExists = false;
|
|
121082
121944
|
}
|
|
121083
121945
|
if (fallbackExists) {
|
|
121084
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
121946
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path147.sep);
|
|
121085
121947
|
if (isSubdirectory) {
|
|
121086
121948
|
return {
|
|
121087
121949
|
success: false,
|
|
@@ -121097,7 +121959,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121097
121959
|
let specMtime;
|
|
121098
121960
|
let specHash;
|
|
121099
121961
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
121100
|
-
const specPath =
|
|
121962
|
+
const specPath = path147.join(targetWorkspace, ".swarm", "spec.md");
|
|
121101
121963
|
try {
|
|
121102
121964
|
const stat9 = await fs107.promises.stat(specPath);
|
|
121103
121965
|
specMtime = stat9.mtime.toISOString();
|
|
@@ -121113,7 +121975,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121113
121975
|
}
|
|
121114
121976
|
}
|
|
121115
121977
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
121116
|
-
const contextPath =
|
|
121978
|
+
const contextPath = path147.join(targetWorkspace, ".swarm", "context.md");
|
|
121117
121979
|
let contextContent = "";
|
|
121118
121980
|
try {
|
|
121119
121981
|
contextContent = await fs107.promises.readFile(contextPath, "utf8");
|
|
@@ -121403,7 +122265,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121403
122265
|
}
|
|
121404
122266
|
await writeCheckpoint(dir).catch(() => {});
|
|
121405
122267
|
try {
|
|
121406
|
-
const markerPath =
|
|
122268
|
+
const markerPath = path147.join(dir, ".swarm", ".plan-write-marker");
|
|
121407
122269
|
const marker = JSON.stringify({
|
|
121408
122270
|
source: "save_plan",
|
|
121409
122271
|
timestamp: new Date().toISOString(),
|
|
@@ -121426,7 +122288,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
121426
122288
|
return {
|
|
121427
122289
|
success: true,
|
|
121428
122290
|
message: "Plan saved successfully",
|
|
121429
|
-
plan_path:
|
|
122291
|
+
plan_path: path147.join(dir, ".swarm", "plan.json"),
|
|
121430
122292
|
phases_count: plan.phases.length,
|
|
121431
122293
|
tasks_count: tasksCount,
|
|
121432
122294
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -121493,7 +122355,7 @@ var save_plan = createSwarmTool({
|
|
|
121493
122355
|
init_zod();
|
|
121494
122356
|
init_manager2();
|
|
121495
122357
|
import * as fs108 from "node:fs";
|
|
121496
|
-
import * as
|
|
122358
|
+
import * as path148 from "node:path";
|
|
121497
122359
|
|
|
121498
122360
|
// src/sbom/detectors/index.ts
|
|
121499
122361
|
init_utils();
|
|
@@ -122343,7 +123205,7 @@ function findManifestFiles(rootDir) {
|
|
|
122343
123205
|
try {
|
|
122344
123206
|
const entries = fs108.readdirSync(dir, { withFileTypes: true });
|
|
122345
123207
|
for (const entry of entries) {
|
|
122346
|
-
const fullPath =
|
|
123208
|
+
const fullPath = path148.join(dir, entry.name);
|
|
122347
123209
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
122348
123210
|
continue;
|
|
122349
123211
|
}
|
|
@@ -122352,7 +123214,7 @@ function findManifestFiles(rootDir) {
|
|
|
122352
123214
|
} else if (entry.isFile()) {
|
|
122353
123215
|
for (const pattern of patterns) {
|
|
122354
123216
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
122355
|
-
manifestFiles.push(
|
|
123217
|
+
manifestFiles.push(path148.relative(rootDir, fullPath));
|
|
122356
123218
|
break;
|
|
122357
123219
|
}
|
|
122358
123220
|
}
|
|
@@ -122370,11 +123232,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
122370
123232
|
try {
|
|
122371
123233
|
const entries = fs108.readdirSync(dir, { withFileTypes: true });
|
|
122372
123234
|
for (const entry of entries) {
|
|
122373
|
-
const fullPath =
|
|
123235
|
+
const fullPath = path148.join(dir, entry.name);
|
|
122374
123236
|
if (entry.isFile()) {
|
|
122375
123237
|
for (const pattern of patterns) {
|
|
122376
123238
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
122377
|
-
found.push(
|
|
123239
|
+
found.push(path148.relative(workingDir, fullPath));
|
|
122378
123240
|
break;
|
|
122379
123241
|
}
|
|
122380
123242
|
}
|
|
@@ -122387,11 +123249,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
122387
123249
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
122388
123250
|
const dirs = new Set;
|
|
122389
123251
|
for (const file3 of changedFiles) {
|
|
122390
|
-
let currentDir =
|
|
123252
|
+
let currentDir = path148.dirname(file3);
|
|
122391
123253
|
while (true) {
|
|
122392
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
122393
|
-
dirs.add(
|
|
122394
|
-
const parent =
|
|
123254
|
+
if (currentDir && currentDir !== "." && currentDir !== path148.sep) {
|
|
123255
|
+
dirs.add(path148.join(workingDir, currentDir));
|
|
123256
|
+
const parent = path148.dirname(currentDir);
|
|
122395
123257
|
if (parent === currentDir)
|
|
122396
123258
|
break;
|
|
122397
123259
|
currentDir = parent;
|
|
@@ -122475,7 +123337,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122475
123337
|
const changedFiles = obj.changed_files;
|
|
122476
123338
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
122477
123339
|
const workingDir = directory;
|
|
122478
|
-
const outputDir =
|
|
123340
|
+
const outputDir = path148.isAbsolute(relativeOutputDir) ? relativeOutputDir : path148.join(workingDir, relativeOutputDir);
|
|
122479
123341
|
let manifestFiles = [];
|
|
122480
123342
|
if (scope === "all") {
|
|
122481
123343
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -122498,7 +123360,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122498
123360
|
const processedFiles = [];
|
|
122499
123361
|
for (const manifestFile of manifestFiles) {
|
|
122500
123362
|
try {
|
|
122501
|
-
const fullPath =
|
|
123363
|
+
const fullPath = path148.isAbsolute(manifestFile) ? manifestFile : path148.join(workingDir, manifestFile);
|
|
122502
123364
|
if (!fs108.existsSync(fullPath)) {
|
|
122503
123365
|
continue;
|
|
122504
123366
|
}
|
|
@@ -122515,7 +123377,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122515
123377
|
const bom = generateCycloneDX(allComponents);
|
|
122516
123378
|
const bomJson = serializeCycloneDX(bom);
|
|
122517
123379
|
const filename = generateSbomFilename();
|
|
122518
|
-
const outputPath =
|
|
123380
|
+
const outputPath = path148.join(outputDir, filename);
|
|
122519
123381
|
fs108.writeFileSync(outputPath, bomJson, "utf-8");
|
|
122520
123382
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
122521
123383
|
try {
|
|
@@ -122560,7 +123422,7 @@ var sbom_generate = createSwarmTool({
|
|
|
122560
123422
|
init_zod();
|
|
122561
123423
|
init_create_tool();
|
|
122562
123424
|
import * as fs109 from "node:fs";
|
|
122563
|
-
import * as
|
|
123425
|
+
import * as path149 from "node:path";
|
|
122564
123426
|
var SPEC_CANDIDATES = [
|
|
122565
123427
|
"openapi.json",
|
|
122566
123428
|
"openapi.yaml",
|
|
@@ -122592,12 +123454,12 @@ function normalizePath5(p) {
|
|
|
122592
123454
|
}
|
|
122593
123455
|
function discoverSpecFile(cwd, specFileArg) {
|
|
122594
123456
|
if (specFileArg) {
|
|
122595
|
-
const resolvedPath =
|
|
122596
|
-
const normalizedCwd = cwd.endsWith(
|
|
123457
|
+
const resolvedPath = path149.resolve(cwd, specFileArg);
|
|
123458
|
+
const normalizedCwd = cwd.endsWith(path149.sep) ? cwd : cwd + path149.sep;
|
|
122597
123459
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
122598
123460
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
122599
123461
|
}
|
|
122600
|
-
const ext =
|
|
123462
|
+
const ext = path149.extname(resolvedPath).toLowerCase();
|
|
122601
123463
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
122602
123464
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
122603
123465
|
}
|
|
@@ -122611,7 +123473,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
122611
123473
|
return resolvedPath;
|
|
122612
123474
|
}
|
|
122613
123475
|
for (const candidate of SPEC_CANDIDATES) {
|
|
122614
|
-
const candidatePath =
|
|
123476
|
+
const candidatePath = path149.resolve(cwd, candidate);
|
|
122615
123477
|
if (fs109.existsSync(candidatePath)) {
|
|
122616
123478
|
const stats = fs109.statSync(candidatePath);
|
|
122617
123479
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -122623,7 +123485,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
122623
123485
|
}
|
|
122624
123486
|
function parseSpec(specFile) {
|
|
122625
123487
|
const content = fs109.readFileSync(specFile, "utf-8");
|
|
122626
|
-
const ext =
|
|
123488
|
+
const ext = path149.extname(specFile).toLowerCase();
|
|
122627
123489
|
if (ext === ".json") {
|
|
122628
123490
|
return parseJsonSpec(content);
|
|
122629
123491
|
}
|
|
@@ -122699,7 +123561,7 @@ function extractRoutes(cwd) {
|
|
|
122699
123561
|
return;
|
|
122700
123562
|
}
|
|
122701
123563
|
for (const entry of entries) {
|
|
122702
|
-
const fullPath =
|
|
123564
|
+
const fullPath = path149.join(dir, entry.name);
|
|
122703
123565
|
if (entry.isSymbolicLink()) {
|
|
122704
123566
|
continue;
|
|
122705
123567
|
}
|
|
@@ -122709,7 +123571,7 @@ function extractRoutes(cwd) {
|
|
|
122709
123571
|
}
|
|
122710
123572
|
walkDir(fullPath);
|
|
122711
123573
|
} else if (entry.isFile()) {
|
|
122712
|
-
const ext =
|
|
123574
|
+
const ext = path149.extname(entry.name).toLowerCase();
|
|
122713
123575
|
const baseName = entry.name.toLowerCase();
|
|
122714
123576
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
122715
123577
|
continue;
|
|
@@ -122878,7 +123740,7 @@ init_bun_compat();
|
|
|
122878
123740
|
init_path_security();
|
|
122879
123741
|
init_create_tool();
|
|
122880
123742
|
import * as fs110 from "node:fs";
|
|
122881
|
-
import * as
|
|
123743
|
+
import * as path150 from "node:path";
|
|
122882
123744
|
var DEFAULT_MAX_RESULTS = 100;
|
|
122883
123745
|
var DEFAULT_MAX_LINES = 200;
|
|
122884
123746
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -122901,24 +123763,24 @@ function matchesGlobs(filePath, globs) {
|
|
|
122901
123763
|
return true;
|
|
122902
123764
|
return globs.some((glob) => globMatch(glob, filePath));
|
|
122903
123765
|
}
|
|
122904
|
-
var
|
|
122905
|
-
function
|
|
123766
|
+
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
123767
|
+
function containsWindowsAttacks4(str) {
|
|
122906
123768
|
if (/:[^\\/]/.test(str))
|
|
122907
123769
|
return true;
|
|
122908
123770
|
const parts2 = str.split(/[/\\]/);
|
|
122909
123771
|
for (const part of parts2) {
|
|
122910
|
-
if (
|
|
123772
|
+
if (WINDOWS_RESERVED_NAMES4.test(part))
|
|
122911
123773
|
return true;
|
|
122912
123774
|
}
|
|
122913
123775
|
return false;
|
|
122914
123776
|
}
|
|
122915
123777
|
function isPathInWorkspace3(filePath, workspace) {
|
|
122916
123778
|
try {
|
|
122917
|
-
const resolvedPath =
|
|
123779
|
+
const resolvedPath = path150.resolve(workspace, filePath);
|
|
122918
123780
|
const realWorkspace = fs110.realpathSync(workspace);
|
|
122919
123781
|
const realResolvedPath = fs110.realpathSync(resolvedPath);
|
|
122920
|
-
const relativePath =
|
|
122921
|
-
if (relativePath.startsWith("..") ||
|
|
123782
|
+
const relativePath = path150.relative(realWorkspace, realResolvedPath);
|
|
123783
|
+
if (relativePath.startsWith("..") || path150.isAbsolute(relativePath)) {
|
|
122922
123784
|
return false;
|
|
122923
123785
|
}
|
|
122924
123786
|
return true;
|
|
@@ -122931,11 +123793,11 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
122931
123793
|
}
|
|
122932
123794
|
function findRgInEnvPath() {
|
|
122933
123795
|
const searchPath = process.env.PATH ?? "";
|
|
122934
|
-
for (const dir of searchPath.split(
|
|
123796
|
+
for (const dir of searchPath.split(path150.delimiter)) {
|
|
122935
123797
|
if (!dir)
|
|
122936
123798
|
continue;
|
|
122937
123799
|
const isWindows = process.platform === "win32";
|
|
122938
|
-
const candidate =
|
|
123800
|
+
const candidate = path150.join(dir, isWindows ? "rg.exe" : "rg");
|
|
122939
123801
|
if (fs110.existsSync(candidate))
|
|
122940
123802
|
return candidate;
|
|
122941
123803
|
}
|
|
@@ -122990,7 +123852,7 @@ async function ripgrepSearch(opts) {
|
|
|
122990
123852
|
stderr: "pipe",
|
|
122991
123853
|
cwd: opts.workspace
|
|
122992
123854
|
});
|
|
122993
|
-
const timeout = new Promise((
|
|
123855
|
+
const timeout = new Promise((resolve55) => setTimeout(() => resolve55("timeout"), REGEX_TIMEOUT_MS));
|
|
122994
123856
|
const exitPromise = proc.exited;
|
|
122995
123857
|
const result = await Promise.race([exitPromise, timeout]);
|
|
122996
123858
|
if (result === "timeout") {
|
|
@@ -123065,8 +123927,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
123065
123927
|
try {
|
|
123066
123928
|
const entries = fs110.readdirSync(dir, { withFileTypes: true });
|
|
123067
123929
|
for (const entry of entries) {
|
|
123068
|
-
const fullPath =
|
|
123069
|
-
const relativePath =
|
|
123930
|
+
const fullPath = path150.join(dir, entry.name);
|
|
123931
|
+
const relativePath = path150.relative(workspace, fullPath);
|
|
123070
123932
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
123071
123933
|
continue;
|
|
123072
123934
|
}
|
|
@@ -123107,7 +123969,7 @@ async function fallbackSearch(opts) {
|
|
|
123107
123969
|
const matches = [];
|
|
123108
123970
|
let total = 0;
|
|
123109
123971
|
for (const file3 of files) {
|
|
123110
|
-
const fullPath =
|
|
123972
|
+
const fullPath = path150.join(opts.workspace, file3);
|
|
123111
123973
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
123112
123974
|
continue;
|
|
123113
123975
|
}
|
|
@@ -123220,14 +124082,14 @@ var search = createSwarmTool({
|
|
|
123220
124082
|
message: "Exclude pattern contains path traversal sequence"
|
|
123221
124083
|
}, null, 2);
|
|
123222
124084
|
}
|
|
123223
|
-
if (include &&
|
|
124085
|
+
if (include && containsWindowsAttacks4(include)) {
|
|
123224
124086
|
return JSON.stringify({
|
|
123225
124087
|
error: true,
|
|
123226
124088
|
type: "path-escape",
|
|
123227
124089
|
message: "Include pattern contains invalid Windows-specific sequence"
|
|
123228
124090
|
}, null, 2);
|
|
123229
124091
|
}
|
|
123230
|
-
if (exclude &&
|
|
124092
|
+
if (exclude && containsWindowsAttacks4(exclude)) {
|
|
123231
124093
|
return JSON.stringify({
|
|
123232
124094
|
error: true,
|
|
123233
124095
|
type: "path-escape",
|
|
@@ -123520,7 +124382,7 @@ init_config();
|
|
|
123520
124382
|
init_schema();
|
|
123521
124383
|
init_create_tool();
|
|
123522
124384
|
import { mkdir as mkdir24, rename as rename10, writeFile as writeFile19 } from "node:fs/promises";
|
|
123523
|
-
import * as
|
|
124385
|
+
import * as path151 from "node:path";
|
|
123524
124386
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
123525
124387
|
var spec_write = createSwarmTool({
|
|
123526
124388
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -123561,8 +124423,8 @@ var spec_write = createSwarmTool({
|
|
|
123561
124423
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
123562
124424
|
}, null, 2);
|
|
123563
124425
|
}
|
|
123564
|
-
const target =
|
|
123565
|
-
await mkdir24(
|
|
124426
|
+
const target = path151.join(directory, ".swarm", "spec.md");
|
|
124427
|
+
await mkdir24(path151.dirname(target), { recursive: true });
|
|
123566
124428
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
123567
124429
|
let finalContent = content;
|
|
123568
124430
|
if (mode === "append") {
|
|
@@ -123591,14 +124453,14 @@ ${content}
|
|
|
123591
124453
|
init_zod();
|
|
123592
124454
|
init_loader();
|
|
123593
124455
|
import {
|
|
123594
|
-
existsSync as
|
|
123595
|
-
mkdirSync as
|
|
123596
|
-
readFileSync as
|
|
123597
|
-
renameSync as
|
|
123598
|
-
unlinkSync as
|
|
123599
|
-
writeFileSync as
|
|
124456
|
+
existsSync as existsSync85,
|
|
124457
|
+
mkdirSync as mkdirSync36,
|
|
124458
|
+
readFileSync as readFileSync72,
|
|
124459
|
+
renameSync as renameSync22,
|
|
124460
|
+
unlinkSync as unlinkSync20,
|
|
124461
|
+
writeFileSync as writeFileSync30
|
|
123600
124462
|
} from "node:fs";
|
|
123601
|
-
import
|
|
124463
|
+
import path152 from "node:path";
|
|
123602
124464
|
init_create_tool();
|
|
123603
124465
|
init_resolve_working_directory();
|
|
123604
124466
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -123728,9 +124590,9 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
123728
124590
|
}
|
|
123729
124591
|
});
|
|
123730
124592
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
123731
|
-
const mutationGatePath =
|
|
124593
|
+
const mutationGatePath = path152.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
123732
124594
|
try {
|
|
123733
|
-
const raw =
|
|
124595
|
+
const raw = readFileSync72(mutationGatePath, "utf-8");
|
|
123734
124596
|
const parsed = JSON.parse(raw);
|
|
123735
124597
|
const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
|
|
123736
124598
|
if (!gateEntry) {
|
|
@@ -123790,9 +124652,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
123790
124652
|
}
|
|
123791
124653
|
}
|
|
123792
124654
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
123793
|
-
const evidenceDir =
|
|
123794
|
-
|
|
123795
|
-
const evidenceFile =
|
|
124655
|
+
const evidenceDir = path152.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
124656
|
+
mkdirSync36(evidenceDir, { recursive: true });
|
|
124657
|
+
const evidenceFile = path152.join(evidenceDir, "phase-council.json");
|
|
123796
124658
|
const evidenceBundle = {
|
|
123797
124659
|
entries: [
|
|
123798
124660
|
{
|
|
@@ -123825,11 +124687,11 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
|
123825
124687
|
};
|
|
123826
124688
|
const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
|
|
123827
124689
|
try {
|
|
123828
|
-
|
|
123829
|
-
|
|
124690
|
+
writeFileSync30(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
124691
|
+
renameSync22(tempFile, evidenceFile);
|
|
123830
124692
|
} finally {
|
|
123831
|
-
if (
|
|
123832
|
-
|
|
124693
|
+
if (existsSync85(tempFile)) {
|
|
124694
|
+
unlinkSync20(tempFile);
|
|
123833
124695
|
}
|
|
123834
124696
|
}
|
|
123835
124697
|
}
|
|
@@ -123854,28 +124716,28 @@ init_zod();
|
|
|
123854
124716
|
init_path_security();
|
|
123855
124717
|
init_create_tool();
|
|
123856
124718
|
import * as fs111 from "node:fs";
|
|
123857
|
-
import * as
|
|
123858
|
-
var
|
|
123859
|
-
function
|
|
124719
|
+
import * as path153 from "node:path";
|
|
124720
|
+
var WINDOWS_RESERVED_NAMES5 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
124721
|
+
function containsWindowsAttacks5(str) {
|
|
123860
124722
|
if (/:[^\\/]/.test(str))
|
|
123861
124723
|
return true;
|
|
123862
124724
|
const parts2 = str.split(/[/\\]/);
|
|
123863
124725
|
for (const part of parts2) {
|
|
123864
|
-
if (
|
|
124726
|
+
if (WINDOWS_RESERVED_NAMES5.test(part))
|
|
123865
124727
|
return true;
|
|
123866
124728
|
}
|
|
123867
124729
|
return false;
|
|
123868
124730
|
}
|
|
123869
124731
|
function isPathInWorkspace4(filePath, workspace) {
|
|
123870
124732
|
try {
|
|
123871
|
-
const resolvedPath =
|
|
124733
|
+
const resolvedPath = path153.resolve(workspace, filePath);
|
|
123872
124734
|
if (!fs111.existsSync(resolvedPath)) {
|
|
123873
124735
|
return true;
|
|
123874
124736
|
}
|
|
123875
124737
|
const realWorkspace = fs111.realpathSync(workspace);
|
|
123876
124738
|
const realResolvedPath = fs111.realpathSync(resolvedPath);
|
|
123877
|
-
const relativePath =
|
|
123878
|
-
if (relativePath.startsWith("..") ||
|
|
124739
|
+
const relativePath = path153.relative(realWorkspace, realResolvedPath);
|
|
124740
|
+
if (relativePath.startsWith("..") || path153.isAbsolute(relativePath)) {
|
|
123879
124741
|
return false;
|
|
123880
124742
|
}
|
|
123881
124743
|
return true;
|
|
@@ -123890,7 +124752,7 @@ function validateFilePath(filePath, workspace) {
|
|
|
123890
124752
|
return false;
|
|
123891
124753
|
if (containsControlChars(filePath))
|
|
123892
124754
|
return false;
|
|
123893
|
-
if (
|
|
124755
|
+
if (containsWindowsAttacks5(filePath))
|
|
123894
124756
|
return false;
|
|
123895
124757
|
return isPathInWorkspace4(filePath, workspace);
|
|
123896
124758
|
}
|
|
@@ -123903,12 +124765,12 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123903
124765
|
if (contextBefore && contextBefore.length > 0) {
|
|
123904
124766
|
for (let i2 = 0;i2 <= lines.length - contextBefore.length; i2++) {
|
|
123905
124767
|
const slice = lines.slice(i2, i2 + contextBefore.length);
|
|
123906
|
-
if (
|
|
124768
|
+
if (arraysEqual2(slice, contextBefore)) {
|
|
123907
124769
|
const afterStart = i2 + contextBefore.length;
|
|
123908
124770
|
if (contextAfter && contextAfter.length > 0) {
|
|
123909
124771
|
for (let j = afterStart;j <= lines.length - contextAfter.length; j++) {
|
|
123910
124772
|
const afterSlice = lines.slice(j, j + contextAfter.length);
|
|
123911
|
-
if (
|
|
124773
|
+
if (arraysEqual2(afterSlice, contextAfter)) {
|
|
123912
124774
|
if (j === afterStart) {
|
|
123913
124775
|
return {
|
|
123914
124776
|
startLineIndex: i2,
|
|
@@ -123921,7 +124783,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123921
124783
|
const oldContentLines = oldContent.split(`
|
|
123922
124784
|
`);
|
|
123923
124785
|
const betweenLines = lines.slice(afterStart, j);
|
|
123924
|
-
if (
|
|
124786
|
+
if (arraysEqual2(betweenLines, oldContentLines)) {
|
|
123925
124787
|
return {
|
|
123926
124788
|
startLineIndex: i2,
|
|
123927
124789
|
endLineIndex: j - 1,
|
|
@@ -123947,7 +124809,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123947
124809
|
`);
|
|
123948
124810
|
for (let k = afterStart;k <= lines.length - oldContentLines.length; k++) {
|
|
123949
124811
|
const candidate = lines.slice(k, k + oldContentLines.length);
|
|
123950
|
-
if (
|
|
124812
|
+
if (arraysEqual2(candidate, oldContentLines)) {
|
|
123951
124813
|
return {
|
|
123952
124814
|
startLineIndex: i2,
|
|
123953
124815
|
endLineIndex: k + oldContentLines.length - 1,
|
|
@@ -123971,7 +124833,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123971
124833
|
} else if (contextAfter && contextAfter.length > 0) {
|
|
123972
124834
|
for (let j = 0;j <= lines.length - contextAfter.length; j++) {
|
|
123973
124835
|
const afterSlice = lines.slice(j, j + contextAfter.length);
|
|
123974
|
-
if (
|
|
124836
|
+
if (arraysEqual2(afterSlice, contextAfter)) {
|
|
123975
124837
|
return {
|
|
123976
124838
|
startLineIndex: 0,
|
|
123977
124839
|
endLineIndex: j - 1,
|
|
@@ -123983,7 +124845,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
123983
124845
|
}
|
|
123984
124846
|
return null;
|
|
123985
124847
|
}
|
|
123986
|
-
function
|
|
124848
|
+
function arraysEqual2(a, b) {
|
|
123987
124849
|
if (a.length !== b.length)
|
|
123988
124850
|
return false;
|
|
123989
124851
|
for (let i2 = 0;i2 < a.length; i2++) {
|
|
@@ -124083,7 +124945,7 @@ var suggestPatch = createSwarmTool({
|
|
|
124083
124945
|
});
|
|
124084
124946
|
continue;
|
|
124085
124947
|
}
|
|
124086
|
-
const fullPath =
|
|
124948
|
+
const fullPath = path153.resolve(directory, change.file);
|
|
124087
124949
|
if (!fs111.existsSync(fullPath)) {
|
|
124088
124950
|
errors5.push({
|
|
124089
124951
|
success: false,
|
|
@@ -124487,7 +125349,7 @@ init_zod();
|
|
|
124487
125349
|
init_manager2();
|
|
124488
125350
|
init_detector();
|
|
124489
125351
|
import * as fs112 from "node:fs";
|
|
124490
|
-
import * as
|
|
125352
|
+
import * as path154 from "node:path";
|
|
124491
125353
|
init_create_tool();
|
|
124492
125354
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
124493
125355
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -124553,7 +125415,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124553
125415
|
if (languages?.length) {
|
|
124554
125416
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
124555
125417
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
124556
|
-
const ext =
|
|
125418
|
+
const ext = path154.extname(file3.path).toLowerCase();
|
|
124557
125419
|
const langDef = getLanguageForExtension(ext);
|
|
124558
125420
|
const fileProfile = getProfileForFile(file3.path);
|
|
124559
125421
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -124566,7 +125428,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124566
125428
|
let skippedCount = 0;
|
|
124567
125429
|
for (const fileInfo of filesToCheck) {
|
|
124568
125430
|
const { path: filePath } = fileInfo;
|
|
124569
|
-
const fullPath =
|
|
125431
|
+
const fullPath = path154.isAbsolute(filePath) ? filePath : path154.join(directory, filePath);
|
|
124570
125432
|
const result = {
|
|
124571
125433
|
path: filePath,
|
|
124572
125434
|
language: "",
|
|
@@ -124615,7 +125477,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124615
125477
|
results.push(result);
|
|
124616
125478
|
continue;
|
|
124617
125479
|
}
|
|
124618
|
-
const ext =
|
|
125480
|
+
const ext = path154.extname(filePath).toLowerCase();
|
|
124619
125481
|
const langDef = getLanguageForExtension(ext);
|
|
124620
125482
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
124621
125483
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -124714,7 +125576,7 @@ init_utils();
|
|
|
124714
125576
|
init_create_tool();
|
|
124715
125577
|
init_path_security();
|
|
124716
125578
|
import * as fs113 from "node:fs";
|
|
124717
|
-
import * as
|
|
125579
|
+
import * as path155 from "node:path";
|
|
124718
125580
|
var MAX_TEXT_LENGTH = 200;
|
|
124719
125581
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
124720
125582
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -124780,9 +125642,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
124780
125642
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
124781
125643
|
}
|
|
124782
125644
|
try {
|
|
124783
|
-
const resolvedPath =
|
|
124784
|
-
const normalizedCwd =
|
|
124785
|
-
const normalizedResolved =
|
|
125645
|
+
const resolvedPath = path155.resolve(paths);
|
|
125646
|
+
const normalizedCwd = path155.resolve(cwd);
|
|
125647
|
+
const normalizedResolved = path155.resolve(resolvedPath);
|
|
124786
125648
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
124787
125649
|
return {
|
|
124788
125650
|
error: "paths must be within the current working directory",
|
|
@@ -124798,7 +125660,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
124798
125660
|
}
|
|
124799
125661
|
}
|
|
124800
125662
|
function isSupportedExtension(filePath) {
|
|
124801
|
-
const ext =
|
|
125663
|
+
const ext = path155.extname(filePath).toLowerCase();
|
|
124802
125664
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
124803
125665
|
}
|
|
124804
125666
|
function findSourceFiles3(dir, files = []) {
|
|
@@ -124813,7 +125675,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
124813
125675
|
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
124814
125676
|
continue;
|
|
124815
125677
|
}
|
|
124816
|
-
const fullPath =
|
|
125678
|
+
const fullPath = path155.join(dir, entry);
|
|
124817
125679
|
let stat9;
|
|
124818
125680
|
try {
|
|
124819
125681
|
stat9 = fs113.statSync(fullPath);
|
|
@@ -124925,7 +125787,7 @@ var todo_extract = createSwarmTool({
|
|
|
124925
125787
|
filesToScan.push(scanPath);
|
|
124926
125788
|
} else {
|
|
124927
125789
|
const errorResult = {
|
|
124928
|
-
error: `unsupported file extension: ${
|
|
125790
|
+
error: `unsupported file extension: ${path155.extname(scanPath)}`,
|
|
124929
125791
|
total: 0,
|
|
124930
125792
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
124931
125793
|
entries: []
|
|
@@ -124975,17 +125837,17 @@ init_schema();
|
|
|
124975
125837
|
init_qa_gate_profile();
|
|
124976
125838
|
init_gate_evidence();
|
|
124977
125839
|
import * as fs117 from "node:fs";
|
|
124978
|
-
import * as
|
|
125840
|
+
import * as path159 from "node:path";
|
|
124979
125841
|
|
|
124980
125842
|
// src/hooks/diff-scope.ts
|
|
124981
125843
|
init_bun_compat();
|
|
124982
125844
|
import * as fs115 from "node:fs";
|
|
124983
|
-
import * as
|
|
125845
|
+
import * as path157 from "node:path";
|
|
124984
125846
|
|
|
124985
125847
|
// src/utils/gitignore-warning.ts
|
|
124986
125848
|
init_bun_compat();
|
|
124987
125849
|
import * as fs114 from "node:fs";
|
|
124988
|
-
import * as
|
|
125850
|
+
import * as path156 from "node:path";
|
|
124989
125851
|
var _internals67 = { bunSpawn };
|
|
124990
125852
|
var _swarmGitExcludedChecked = false;
|
|
124991
125853
|
function fileCoversSwarm(content) {
|
|
@@ -125059,10 +125921,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
125059
125921
|
const excludeRelPath = excludePathRaw.trim();
|
|
125060
125922
|
if (!excludeRelPath)
|
|
125061
125923
|
return;
|
|
125062
|
-
const excludePath =
|
|
125924
|
+
const excludePath = path156.isAbsolute(excludeRelPath) ? excludeRelPath : path156.join(directory, excludeRelPath);
|
|
125063
125925
|
if (checkIgnoreExitCode !== 0) {
|
|
125064
125926
|
try {
|
|
125065
|
-
fs114.mkdirSync(
|
|
125927
|
+
fs114.mkdirSync(path156.dirname(excludePath), { recursive: true });
|
|
125066
125928
|
let existing = "";
|
|
125067
125929
|
try {
|
|
125068
125930
|
existing = fs114.readFileSync(excludePath, "utf8");
|
|
@@ -125106,7 +125968,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
125106
125968
|
var _internals68 = { bunSpawn };
|
|
125107
125969
|
function getDeclaredScope(taskId, directory) {
|
|
125108
125970
|
try {
|
|
125109
|
-
const planPath =
|
|
125971
|
+
const planPath = path157.join(directory, ".swarm", "plan.json");
|
|
125110
125972
|
if (!fs115.existsSync(planPath))
|
|
125111
125973
|
return null;
|
|
125112
125974
|
const raw = fs115.readFileSync(planPath, "utf-8");
|
|
@@ -125212,7 +126074,7 @@ init_telemetry();
|
|
|
125212
126074
|
// src/turbo/lean/task-completion.ts
|
|
125213
126075
|
init_file_locks();
|
|
125214
126076
|
import * as fs116 from "node:fs";
|
|
125215
|
-
import * as
|
|
126077
|
+
import * as path158 from "node:path";
|
|
125216
126078
|
var _internals69 = {
|
|
125217
126079
|
listActiveLocks,
|
|
125218
126080
|
verifyLeanTurboTaskCompletion
|
|
@@ -125231,7 +126093,7 @@ var TIER_3_PATTERNS = [
|
|
|
125231
126093
|
];
|
|
125232
126094
|
function matchesTier3Pattern(files) {
|
|
125233
126095
|
for (const file3 of files) {
|
|
125234
|
-
const fileName =
|
|
126096
|
+
const fileName = path158.basename(file3);
|
|
125235
126097
|
for (const pattern of TIER_3_PATTERNS) {
|
|
125236
126098
|
if (pattern.test(fileName)) {
|
|
125237
126099
|
return true;
|
|
@@ -125243,7 +126105,7 @@ function matchesTier3Pattern(files) {
|
|
|
125243
126105
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
125244
126106
|
let persisted = null;
|
|
125245
126107
|
try {
|
|
125246
|
-
const statePath =
|
|
126108
|
+
const statePath = path158.join(directory, ".swarm", "turbo-state.json");
|
|
125247
126109
|
if (!fs116.existsSync(statePath)) {
|
|
125248
126110
|
return {
|
|
125249
126111
|
ok: false,
|
|
@@ -125327,11 +126189,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
125327
126189
|
};
|
|
125328
126190
|
}
|
|
125329
126191
|
const phase = runState.phase ?? 0;
|
|
125330
|
-
const evidencePath =
|
|
125331
|
-
const expectedDir =
|
|
125332
|
-
const resolvedPath =
|
|
125333
|
-
const resolvedDir =
|
|
125334
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
126192
|
+
const evidencePath = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
126193
|
+
const expectedDir = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
126194
|
+
const resolvedPath = path158.resolve(evidencePath);
|
|
126195
|
+
const resolvedDir = path158.resolve(expectedDir);
|
|
126196
|
+
if (!resolvedPath.startsWith(resolvedDir + path158.sep) && resolvedPath !== resolvedDir) {
|
|
125335
126197
|
return {
|
|
125336
126198
|
ok: false,
|
|
125337
126199
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -125371,7 +126233,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
125371
126233
|
}
|
|
125372
126234
|
let filesTouched = [];
|
|
125373
126235
|
try {
|
|
125374
|
-
const planPath =
|
|
126236
|
+
const planPath = path158.join(directory, ".swarm", "plan.json");
|
|
125375
126237
|
const planRaw = fs116.readFileSync(planPath, "utf-8");
|
|
125376
126238
|
const plan = JSON.parse(planRaw);
|
|
125377
126239
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -125455,7 +126317,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
125455
126317
|
];
|
|
125456
126318
|
function matchesTier3Pattern2(files) {
|
|
125457
126319
|
for (const file3 of files) {
|
|
125458
|
-
const fileName =
|
|
126320
|
+
const fileName = path159.basename(file3);
|
|
125459
126321
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
125460
126322
|
if (pattern.test(fileName)) {
|
|
125461
126323
|
return true;
|
|
@@ -125494,7 +126356,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
125494
126356
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
125495
126357
|
const resolvedDir2 = workingDirectory;
|
|
125496
126358
|
try {
|
|
125497
|
-
const planPath =
|
|
126359
|
+
const planPath = path159.join(resolvedDir2, ".swarm", "plan.json");
|
|
125498
126360
|
const planRaw = fs117.readFileSync(planPath, "utf-8");
|
|
125499
126361
|
const plan = JSON.parse(planRaw);
|
|
125500
126362
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -125572,7 +126434,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
125572
126434
|
}
|
|
125573
126435
|
if (resolvedDir) {
|
|
125574
126436
|
try {
|
|
125575
|
-
const planPath =
|
|
126437
|
+
const planPath = path159.join(resolvedDir, ".swarm", "plan.json");
|
|
125576
126438
|
const planRaw = fs117.readFileSync(planPath, "utf-8");
|
|
125577
126439
|
const plan = JSON.parse(planRaw);
|
|
125578
126440
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -125808,7 +126670,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125808
126670
|
};
|
|
125809
126671
|
}
|
|
125810
126672
|
directory = resolveResult.directory;
|
|
125811
|
-
const planPath =
|
|
126673
|
+
const planPath = path159.join(directory, ".swarm", "plan.json");
|
|
125812
126674
|
if (!fs117.existsSync(planPath)) {
|
|
125813
126675
|
return {
|
|
125814
126676
|
success: false,
|
|
@@ -125817,9 +126679,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125817
126679
|
};
|
|
125818
126680
|
}
|
|
125819
126681
|
if (fallbackDir && directory !== fallbackDir) {
|
|
125820
|
-
const canonicalDir = fs117.realpathSync(
|
|
125821
|
-
const canonicalRoot = fs117.realpathSync(
|
|
125822
|
-
if (canonicalDir.startsWith(canonicalRoot +
|
|
126682
|
+
const canonicalDir = fs117.realpathSync(path159.resolve(directory));
|
|
126683
|
+
const canonicalRoot = fs117.realpathSync(path159.resolve(fallbackDir));
|
|
126684
|
+
if (canonicalDir.startsWith(canonicalRoot + path159.sep)) {
|
|
125823
126685
|
return {
|
|
125824
126686
|
success: false,
|
|
125825
126687
|
message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
|
|
@@ -125831,8 +126693,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125831
126693
|
}
|
|
125832
126694
|
if (args2.status === "in_progress") {
|
|
125833
126695
|
try {
|
|
125834
|
-
const evidencePath =
|
|
125835
|
-
fs117.mkdirSync(
|
|
126696
|
+
const evidencePath = path159.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
126697
|
+
fs117.mkdirSync(path159.dirname(evidencePath), { recursive: true });
|
|
125836
126698
|
const fd = fs117.openSync(evidencePath, "wx");
|
|
125837
126699
|
let writeOk = false;
|
|
125838
126700
|
try {
|
|
@@ -125856,7 +126718,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125856
126718
|
recoverTaskStateFromDelegations(args2.task_id, directory);
|
|
125857
126719
|
let phaseRequiresReviewer = true;
|
|
125858
126720
|
try {
|
|
125859
|
-
const planPath2 =
|
|
126721
|
+
const planPath2 = path159.join(directory, ".swarm", "plan.json");
|
|
125860
126722
|
const planRaw = fs117.readFileSync(planPath2, "utf-8");
|
|
125861
126723
|
const plan = JSON.parse(planRaw);
|
|
125862
126724
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
@@ -126085,7 +126947,7 @@ init_utils2();
|
|
|
126085
126947
|
init_redaction();
|
|
126086
126948
|
import { createHash as createHash12 } from "node:crypto";
|
|
126087
126949
|
import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
|
|
126088
|
-
import * as
|
|
126950
|
+
import * as path160 from "node:path";
|
|
126089
126951
|
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
126090
126952
|
var MAX_EVIDENCE_TEXT_LENGTH = 4000;
|
|
126091
126953
|
async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
@@ -126093,7 +126955,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
|
126093
126955
|
const capturedAt = now().toISOString();
|
|
126094
126956
|
const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
|
|
126095
126957
|
if (records.length > 0) {
|
|
126096
|
-
await mkdir25(
|
|
126958
|
+
await mkdir25(path160.dirname(filePath), { recursive: true });
|
|
126097
126959
|
await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
|
|
126098
126960
|
`)}
|
|
126099
126961
|
`, "utf-8");
|
|
@@ -126290,7 +127152,7 @@ init_schema3();
|
|
|
126290
127152
|
init_store();
|
|
126291
127153
|
init_create_tool();
|
|
126292
127154
|
init_resolve_working_directory();
|
|
126293
|
-
import * as
|
|
127155
|
+
import * as path161 from "node:path";
|
|
126294
127156
|
var FindingSchema2 = exports_external.object({
|
|
126295
127157
|
severity: exports_external.enum(["low", "medium", "high", "critical"]),
|
|
126296
127158
|
category: exports_external.string().min(1),
|
|
@@ -126354,7 +127216,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
126354
127216
|
if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
|
|
126355
127217
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
126356
127218
|
const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
|
|
126357
|
-
const result = await curateAndStoreSwarm(lessons,
|
|
127219
|
+
const result = await curateAndStoreSwarm(lessons, path161.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
|
|
126358
127220
|
knowledgeProposed = result.stored;
|
|
126359
127221
|
}
|
|
126360
127222
|
} catch {}
|
|
@@ -126390,7 +127252,7 @@ init_ledger();
|
|
|
126390
127252
|
init_manager();
|
|
126391
127253
|
init_create_tool();
|
|
126392
127254
|
import fs118 from "node:fs";
|
|
126393
|
-
import
|
|
127255
|
+
import path162 from "node:path";
|
|
126394
127256
|
function normalizeVerdict(verdict) {
|
|
126395
127257
|
switch (verdict) {
|
|
126396
127258
|
case "APPROVED":
|
|
@@ -126438,7 +127300,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
126438
127300
|
entries: [evidenceEntry]
|
|
126439
127301
|
};
|
|
126440
127302
|
const filename = "drift-verifier.json";
|
|
126441
|
-
const relativePath =
|
|
127303
|
+
const relativePath = path162.join("evidence", String(phase), filename);
|
|
126442
127304
|
let validatedPath;
|
|
126443
127305
|
try {
|
|
126444
127306
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126449,10 +127311,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
126449
127311
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126450
127312
|
}, null, 2);
|
|
126451
127313
|
}
|
|
126452
|
-
const evidenceDir =
|
|
127314
|
+
const evidenceDir = path162.dirname(validatedPath);
|
|
126453
127315
|
try {
|
|
126454
127316
|
await fs118.promises.mkdir(evidenceDir, { recursive: true });
|
|
126455
|
-
const tempPath =
|
|
127317
|
+
const tempPath = path162.join(evidenceDir, `.${filename}.tmp`);
|
|
126456
127318
|
await fs118.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126457
127319
|
await fs118.promises.rename(tempPath, validatedPath);
|
|
126458
127320
|
let snapshotInfo;
|
|
@@ -126549,7 +127411,7 @@ var write_drift_evidence = createSwarmTool({
|
|
|
126549
127411
|
init_zod();
|
|
126550
127412
|
init_loader();
|
|
126551
127413
|
import fs119 from "node:fs";
|
|
126552
|
-
import
|
|
127414
|
+
import path163 from "node:path";
|
|
126553
127415
|
init_utils2();
|
|
126554
127416
|
init_manager();
|
|
126555
127417
|
init_create_tool();
|
|
@@ -126637,7 +127499,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
126637
127499
|
timestamp: synthesis.timestamp
|
|
126638
127500
|
};
|
|
126639
127501
|
const filename = "final-council.json";
|
|
126640
|
-
const relativePath =
|
|
127502
|
+
const relativePath = path163.join("evidence", filename);
|
|
126641
127503
|
let validatedPath;
|
|
126642
127504
|
try {
|
|
126643
127505
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126651,10 +127513,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
126651
127513
|
const evidenceContent = {
|
|
126652
127514
|
entries: [evidenceEntry]
|
|
126653
127515
|
};
|
|
126654
|
-
const evidenceDir =
|
|
127516
|
+
const evidenceDir = path163.dirname(validatedPath);
|
|
126655
127517
|
try {
|
|
126656
127518
|
await fs119.promises.mkdir(evidenceDir, { recursive: true });
|
|
126657
|
-
const tempPath =
|
|
127519
|
+
const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
|
|
126658
127520
|
await fs119.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126659
127521
|
await fs119.promises.rename(tempPath, validatedPath);
|
|
126660
127522
|
return JSON.stringify({
|
|
@@ -126714,7 +127576,7 @@ init_zod();
|
|
|
126714
127576
|
init_utils2();
|
|
126715
127577
|
init_create_tool();
|
|
126716
127578
|
import fs120 from "node:fs";
|
|
126717
|
-
import
|
|
127579
|
+
import path164 from "node:path";
|
|
126718
127580
|
function normalizeVerdict2(verdict) {
|
|
126719
127581
|
switch (verdict) {
|
|
126720
127582
|
case "APPROVED":
|
|
@@ -126762,7 +127624,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126762
127624
|
entries: [evidenceEntry]
|
|
126763
127625
|
};
|
|
126764
127626
|
const filename = "hallucination-guard.json";
|
|
126765
|
-
const relativePath =
|
|
127627
|
+
const relativePath = path164.join("evidence", String(phase), filename);
|
|
126766
127628
|
let validatedPath;
|
|
126767
127629
|
try {
|
|
126768
127630
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126773,10 +127635,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126773
127635
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126774
127636
|
}, null, 2);
|
|
126775
127637
|
}
|
|
126776
|
-
const evidenceDir =
|
|
127638
|
+
const evidenceDir = path164.dirname(validatedPath);
|
|
126777
127639
|
try {
|
|
126778
127640
|
await fs120.promises.mkdir(evidenceDir, { recursive: true });
|
|
126779
|
-
const tempPath =
|
|
127641
|
+
const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
|
|
126780
127642
|
await fs120.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126781
127643
|
await fs120.promises.rename(tempPath, validatedPath);
|
|
126782
127644
|
return JSON.stringify({
|
|
@@ -126826,7 +127688,7 @@ init_zod();
|
|
|
126826
127688
|
init_utils2();
|
|
126827
127689
|
init_create_tool();
|
|
126828
127690
|
import fs121 from "node:fs";
|
|
126829
|
-
import
|
|
127691
|
+
import path165 from "node:path";
|
|
126830
127692
|
function normalizeVerdict3(verdict) {
|
|
126831
127693
|
switch (verdict) {
|
|
126832
127694
|
case "PASS":
|
|
@@ -126900,7 +127762,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126900
127762
|
entries: [evidenceEntry]
|
|
126901
127763
|
};
|
|
126902
127764
|
const filename = "mutation-gate.json";
|
|
126903
|
-
const relativePath =
|
|
127765
|
+
const relativePath = path165.join("evidence", String(phase), filename);
|
|
126904
127766
|
let validatedPath;
|
|
126905
127767
|
try {
|
|
126906
127768
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126911,10 +127773,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126911
127773
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126912
127774
|
}, null, 2);
|
|
126913
127775
|
}
|
|
126914
|
-
const evidenceDir =
|
|
127776
|
+
const evidenceDir = path165.dirname(validatedPath);
|
|
126915
127777
|
try {
|
|
126916
127778
|
await fs121.promises.mkdir(evidenceDir, { recursive: true });
|
|
126917
|
-
const tempPath =
|
|
127779
|
+
const tempPath = path165.join(evidenceDir, `.${filename}.tmp`);
|
|
126918
127780
|
await fs121.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126919
127781
|
await fs121.promises.rename(tempPath, validatedPath);
|
|
126920
127782
|
return JSON.stringify({
|
|
@@ -127050,7 +127912,8 @@ var TOOL_MANIFEST = defineHandlers({
|
|
|
127050
127912
|
lean_turbo_runner_status: () => lean_turbo_runner_status,
|
|
127051
127913
|
lean_turbo_review: () => lean_turbo_review,
|
|
127052
127914
|
lean_turbo_run_phase: () => lean_turbo_run_phase,
|
|
127053
|
-
lean_turbo_status: () => lean_turbo_status
|
|
127915
|
+
lean_turbo_status: () => lean_turbo_status,
|
|
127916
|
+
apply_patch: () => applyPatch
|
|
127054
127917
|
});
|
|
127055
127918
|
|
|
127056
127919
|
// src/tools/plugin-registration.ts
|
|
@@ -127180,6 +128043,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
127180
128043
|
const msg = err3 instanceof Error ? err3.message : String(err3);
|
|
127181
128044
|
log("loadSnapshot timed out or failed (non-fatal)", { error: msg });
|
|
127182
128045
|
});
|
|
128046
|
+
initTelemetry(ctx.directory);
|
|
127183
128047
|
const repoGraphHook = createRepoGraphBuilderHook(ctx.directory);
|
|
127184
128048
|
queueMicrotask(() => {
|
|
127185
128049
|
const watchdog = setTimeout(() => {
|
|
@@ -127196,7 +128060,6 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
127196
128060
|
error: msg
|
|
127197
128061
|
});
|
|
127198
128062
|
});
|
|
127199
|
-
initTelemetry(ctx.directory);
|
|
127200
128063
|
writeSwarmConfigExampleIfNew(ctx.directory);
|
|
127201
128064
|
writeProjectConfigIfNew(ctx.directory, config3.quiet);
|
|
127202
128065
|
if (config3.version_check !== false) {
|
|
@@ -127361,7 +128224,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
127361
128224
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
127362
128225
|
preflightTriggerManager = new PTM(automationConfig);
|
|
127363
128226
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
127364
|
-
const swarmDir =
|
|
128227
|
+
const swarmDir = path167.resolve(ctx.directory, ".swarm");
|
|
127365
128228
|
statusArtifact = new ASA(swarmDir);
|
|
127366
128229
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
127367
128230
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -127875,7 +128738,7 @@ ${promptRaw}`;
|
|
|
127875
128738
|
const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
|
|
127876
128739
|
let desc = meta3.description || "";
|
|
127877
128740
|
if (!desc || desc === "No description provided") {
|
|
127878
|
-
desc =
|
|
128741
|
+
desc = path167.basename(path167.dirname(s.skillPath));
|
|
127879
128742
|
}
|
|
127880
128743
|
desc = desc.replace(/,/g, ";");
|
|
127881
128744
|
return `file:${s.skillPath} (-- ${desc})`;
|
|
@@ -127885,7 +128748,7 @@ ${promptRaw}`;
|
|
|
127885
128748
|
|
|
127886
128749
|
${promptRaw}`;
|
|
127887
128750
|
argsRecord.prompt = newPrompt;
|
|
127888
|
-
const skillNames = topSkills.map((s) => `${
|
|
128751
|
+
const skillNames = topSkills.map((s) => `${path167.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
127889
128752
|
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
127890
128753
|
for (const skill of topSkills) {
|
|
127891
128754
|
try {
|