opencode-swarm 7.50.4 → 7.51.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/cli/index.js +54 -15
- package/dist/index.js +1324 -566
- package/dist/lang/backend.d.ts +1 -0
- package/dist/tools/git-blame.d.ts +21 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/suggest-patch.d.ts +1 -0
- package/dist/tools/test-runner.d.ts +3 -2
- 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.51.1",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -191,7 +191,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
191
191
|
agents: ["architect", "reviewer", "critic_oversight"]
|
|
192
192
|
},
|
|
193
193
|
syntax_check: {
|
|
194
|
-
description: "syntax
|
|
194
|
+
description: "check syntax of source files using tree-sitter parsers across multiple languages, returning per-file errors",
|
|
195
195
|
agents: ["architect", "coder", "test_engineer"]
|
|
196
196
|
},
|
|
197
197
|
placeholder_scan: {
|
|
@@ -199,7 +199,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
199
199
|
agents: ["architect", "reviewer"]
|
|
200
200
|
},
|
|
201
201
|
imports: {
|
|
202
|
-
description: "
|
|
202
|
+
description: "find all consumers that import from a given file — use before refactoring shared modules to avoid breaking unseen dependents",
|
|
203
203
|
agents: [
|
|
204
204
|
"architect",
|
|
205
205
|
"sme",
|
|
@@ -217,11 +217,11 @@ var init_tool_metadata = __esm(() => {
|
|
|
217
217
|
]
|
|
218
218
|
},
|
|
219
219
|
lint: {
|
|
220
|
-
description: "
|
|
220
|
+
description: "run project linter in check or fix mode; supports biome, eslint, ruff, clippy, and more, returns structured results",
|
|
221
221
|
agents: ["architect", "reviewer", "coder"]
|
|
222
222
|
},
|
|
223
223
|
secretscan: {
|
|
224
|
-
description: "
|
|
224
|
+
description: "scan for secrets (API keys, tokens, passwords) via regex and entropy; returns redacted previews, excludes common dirs",
|
|
225
225
|
agents: ["architect", "reviewer", "critic_oversight"]
|
|
226
226
|
},
|
|
227
227
|
sast_scan: {
|
|
@@ -229,7 +229,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
229
229
|
agents: ["architect", "reviewer", "critic_oversight"]
|
|
230
230
|
},
|
|
231
231
|
build_check: {
|
|
232
|
-
description: "build
|
|
232
|
+
description: "discover and run build, typecheck, and test commands for various project ecosystems in the working directory",
|
|
233
233
|
agents: ["architect", "coder", "test_engineer"]
|
|
234
234
|
},
|
|
235
235
|
pre_check_batch: {
|
|
@@ -241,7 +241,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
241
241
|
agents: ["architect"]
|
|
242
242
|
},
|
|
243
243
|
symbols: {
|
|
244
|
-
description: "
|
|
244
|
+
description: "extract exported symbols (functions, classes, interfaces, types) from source files; supports TypeScript, JavaScript, and Python",
|
|
245
245
|
agents: [
|
|
246
246
|
"architect",
|
|
247
247
|
"sme",
|
|
@@ -312,7 +312,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
312
312
|
agents: ["architect"]
|
|
313
313
|
},
|
|
314
314
|
checkpoint: {
|
|
315
|
-
description: "
|
|
315
|
+
description: "create named git checkpoints for save, restore, and delete — use before risky operations to enable rollback",
|
|
316
316
|
agents: ["architect"]
|
|
317
317
|
},
|
|
318
318
|
pkg_audit: {
|
|
@@ -356,6 +356,10 @@ var init_tool_metadata = __esm(() => {
|
|
|
356
356
|
"explorer"
|
|
357
357
|
]
|
|
358
358
|
},
|
|
359
|
+
git_blame: {
|
|
360
|
+
description: "per-line git blame metadata: sha, author, date, summary for each line in a file",
|
|
361
|
+
agents: ["reviewer", "explorer", "architect"]
|
|
362
|
+
},
|
|
359
363
|
gitingest: {
|
|
360
364
|
description: "fetch a GitHub repository full content via gitingest.com",
|
|
361
365
|
agents: ["architect", "docs", "explorer"]
|
|
@@ -74605,11 +74609,14 @@ async function defaultSelectTestFramework(profile, dir) {
|
|
|
74605
74609
|
function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}) {
|
|
74606
74610
|
const scope = opts.scope ?? "all";
|
|
74607
74611
|
const coverage = opts.coverage ?? false;
|
|
74612
|
+
const bail = opts.bail ?? false;
|
|
74608
74613
|
switch (framework) {
|
|
74609
74614
|
case "bun": {
|
|
74610
74615
|
const args2 = ["bun", "test"];
|
|
74611
74616
|
if (coverage)
|
|
74612
74617
|
args2.push("--coverage");
|
|
74618
|
+
if (bail)
|
|
74619
|
+
args2.push("--bail");
|
|
74613
74620
|
if (scope !== "all" && files.length > 0)
|
|
74614
74621
|
args2.push(...files);
|
|
74615
74622
|
return args2;
|
|
@@ -74625,6 +74632,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
74625
74632
|
];
|
|
74626
74633
|
if (coverage)
|
|
74627
74634
|
args2.push("--coverage");
|
|
74635
|
+
if (bail)
|
|
74636
|
+
args2.push("--bail");
|
|
74628
74637
|
if (scope !== "all" && files.length > 0)
|
|
74629
74638
|
args2.push(...files);
|
|
74630
74639
|
return args2;
|
|
@@ -74633,12 +74642,16 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
74633
74642
|
const args2 = ["npx", "jest", "--json"];
|
|
74634
74643
|
if (coverage)
|
|
74635
74644
|
args2.push("--coverage");
|
|
74645
|
+
if (bail)
|
|
74646
|
+
args2.push("--bail");
|
|
74636
74647
|
if (scope !== "all" && files.length > 0)
|
|
74637
74648
|
args2.push(...files);
|
|
74638
74649
|
return args2;
|
|
74639
74650
|
}
|
|
74640
74651
|
case "mocha": {
|
|
74641
74652
|
const args2 = ["npx", "mocha"];
|
|
74653
|
+
if (bail)
|
|
74654
|
+
args2.push("--bail");
|
|
74642
74655
|
if (scope !== "all" && files.length > 0)
|
|
74643
74656
|
args2.push(...files);
|
|
74644
74657
|
return args2;
|
|
@@ -74648,6 +74661,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
74648
74661
|
const args2 = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
|
|
74649
74662
|
if (coverage)
|
|
74650
74663
|
args2.push("--cov=.", "--cov-report=term-missing");
|
|
74664
|
+
if (bail)
|
|
74665
|
+
args2.push("-x");
|
|
74651
74666
|
if (scope !== "all" && files.length > 0)
|
|
74652
74667
|
args2.push(...files);
|
|
74653
74668
|
return args2;
|
|
@@ -74701,6 +74716,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
74701
74716
|
return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
|
|
74702
74717
|
case "rspec": {
|
|
74703
74718
|
const args2 = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
|
|
74719
|
+
if (bail)
|
|
74720
|
+
args2.push("--fail-fast");
|
|
74704
74721
|
if (scope !== "all" && files.length > 0)
|
|
74705
74722
|
args2.push(...files);
|
|
74706
74723
|
return args2;
|
|
@@ -76675,6 +76692,10 @@ function validateArgs2(args2) {
|
|
|
76675
76692
|
if (typeof obj.coverage !== "boolean")
|
|
76676
76693
|
return false;
|
|
76677
76694
|
}
|
|
76695
|
+
if (obj.bail !== undefined) {
|
|
76696
|
+
if (typeof obj.bail !== "boolean")
|
|
76697
|
+
return false;
|
|
76698
|
+
}
|
|
76678
76699
|
if (obj.timeout_ms !== undefined) {
|
|
76679
76700
|
if (typeof obj.timeout_ms !== "number")
|
|
76680
76701
|
return false;
|
|
@@ -76750,7 +76771,7 @@ async function detectTestFrameworkViaDispatch(cwd) {
|
|
|
76750
76771
|
return "none";
|
|
76751
76772
|
}
|
|
76752
76773
|
}
|
|
76753
|
-
async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir) {
|
|
76774
|
+
async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir, bail) {
|
|
76754
76775
|
if (framework === "none")
|
|
76755
76776
|
return null;
|
|
76756
76777
|
try {
|
|
@@ -76759,7 +76780,8 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
|
|
|
76759
76780
|
if (backend?.buildTestCommand) {
|
|
76760
76781
|
const cmd = backend.buildTestCommand(framework, files, baseDir, {
|
|
76761
76782
|
scope,
|
|
76762
|
-
coverage
|
|
76783
|
+
coverage,
|
|
76784
|
+
bail
|
|
76763
76785
|
});
|
|
76764
76786
|
if (cmd)
|
|
76765
76787
|
return cmd;
|
|
@@ -77128,12 +77150,14 @@ function getTargetedExecutionUnsupportedReason(framework) {
|
|
|
77128
77150
|
return null;
|
|
77129
77151
|
}
|
|
77130
77152
|
}
|
|
77131
|
-
function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
77153
|
+
function buildTestCommand2(framework, scope, files, coverage, baseDir, bail) {
|
|
77132
77154
|
switch (framework) {
|
|
77133
77155
|
case "bun": {
|
|
77134
77156
|
const args2 = ["bun", "test"];
|
|
77135
77157
|
if (coverage)
|
|
77136
77158
|
args2.push("--coverage");
|
|
77159
|
+
if (bail)
|
|
77160
|
+
args2.push("--bail");
|
|
77137
77161
|
if (scope !== "all" && files.length > 0) {
|
|
77138
77162
|
args2.push(...files);
|
|
77139
77163
|
}
|
|
@@ -77150,6 +77174,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
77150
77174
|
];
|
|
77151
77175
|
if (coverage)
|
|
77152
77176
|
args2.push("--coverage");
|
|
77177
|
+
if (bail)
|
|
77178
|
+
args2.push("--bail=1");
|
|
77153
77179
|
if (scope !== "all" && files.length > 0) {
|
|
77154
77180
|
args2.push(...files);
|
|
77155
77181
|
}
|
|
@@ -77159,6 +77185,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
77159
77185
|
const args2 = ["npx", "jest", "--json"];
|
|
77160
77186
|
if (coverage)
|
|
77161
77187
|
args2.push("--coverage");
|
|
77188
|
+
if (bail)
|
|
77189
|
+
args2.push("--bail");
|
|
77162
77190
|
if (scope !== "all" && files.length > 0) {
|
|
77163
77191
|
args2.push(...files);
|
|
77164
77192
|
}
|
|
@@ -77166,6 +77194,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
77166
77194
|
}
|
|
77167
77195
|
case "mocha": {
|
|
77168
77196
|
const args2 = ["npx", "mocha"];
|
|
77197
|
+
if (bail)
|
|
77198
|
+
args2.push("--bail");
|
|
77169
77199
|
if (scope !== "all" && files.length > 0) {
|
|
77170
77200
|
args2.push(...files);
|
|
77171
77201
|
}
|
|
@@ -77176,6 +77206,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
77176
77206
|
const args2 = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
|
|
77177
77207
|
if (coverage)
|
|
77178
77208
|
args2.push("--cov=.", "--cov-report=term-missing");
|
|
77209
|
+
if (bail)
|
|
77210
|
+
args2.push("-x");
|
|
77179
77211
|
if (scope !== "all" && files.length > 0) {
|
|
77180
77212
|
args2.push(...files);
|
|
77181
77213
|
}
|
|
@@ -77232,6 +77264,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
77232
77264
|
return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
|
|
77233
77265
|
case "rspec": {
|
|
77234
77266
|
const args2 = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
|
|
77267
|
+
if (bail)
|
|
77268
|
+
args2.push("--fail-fast");
|
|
77235
77269
|
if (scope !== "all" && files.length > 0) {
|
|
77236
77270
|
args2.push(...files);
|
|
77237
77271
|
}
|
|
@@ -77617,7 +77651,7 @@ async function readBoundedStream(stream, maxBytes) {
|
|
|
77617
77651
|
}
|
|
77618
77652
|
return { text: decoder.decode(combined), truncated };
|
|
77619
77653
|
}
|
|
77620
|
-
async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
77654
|
+
async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail) {
|
|
77621
77655
|
if (scope !== "all" && files.length > 0) {
|
|
77622
77656
|
const unsupportedReason = getTargetedExecutionUnsupportedReason(framework);
|
|
77623
77657
|
if (unsupportedReason) {
|
|
@@ -77632,7 +77666,7 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
77632
77666
|
}
|
|
77633
77667
|
}
|
|
77634
77668
|
const useDispatchBuild = process.env.SWARM_LANG_BACKEND !== "legacy";
|
|
77635
|
-
const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd) ?? buildTestCommand2(framework, scope, files, coverage, cwd) : buildTestCommand2(framework, scope, files, coverage, cwd);
|
|
77669
|
+
const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd, bail) ?? buildTestCommand2(framework, scope, files, coverage, cwd, bail) : buildTestCommand2(framework, scope, files, coverage, cwd, bail);
|
|
77636
77670
|
if (!command) {
|
|
77637
77671
|
return {
|
|
77638
77672
|
success: false,
|
|
@@ -77980,6 +78014,7 @@ var init_test_runner = __esm(() => {
|
|
|
77980
78014
|
scope: exports_external.enum(["all", "convention", "graph", "impact"]).optional().describe('Test scope: "all" runs full suite, "convention" accepts direct test files or maps source files to tests by naming, "graph" finds related tests via imports from source files, "impact" finds tests covering changed source files via test-impact analysis'),
|
|
77981
78015
|
files: exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
|
|
77982
78016
|
coverage: exports_external.boolean().optional().describe("Enable coverage reporting if supported"),
|
|
78017
|
+
bail: exports_external.boolean().optional().describe("Stop running tests after the first failure. Default false. Note: coverage may be incomplete when bail=true with coverage=true."),
|
|
77983
78018
|
timeout_ms: exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
|
|
77984
78019
|
allow_full_suite: exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
|
|
77985
78020
|
working_directory: exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
@@ -78080,6 +78115,7 @@ var init_test_runner = __esm(() => {
|
|
|
78080
78115
|
}
|
|
78081
78116
|
const _files = args2.files || [];
|
|
78082
78117
|
const coverage = args2.coverage || false;
|
|
78118
|
+
const bail = args2.bail || false;
|
|
78083
78119
|
const timeout_ms = Math.min(args2.timeout_ms || DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
|
|
78084
78120
|
const useDispatch = process.env.SWARM_LANG_BACKEND !== "legacy";
|
|
78085
78121
|
let framework;
|
|
@@ -78318,7 +78354,7 @@ var init_test_runner = __esm(() => {
|
|
|
78318
78354
|
};
|
|
78319
78355
|
return JSON.stringify(errorResult, null, 2);
|
|
78320
78356
|
}
|
|
78321
|
-
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir);
|
|
78357
|
+
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir, bail);
|
|
78322
78358
|
recordAndAnalyzeResults(result, testFiles, workingDir, _files.length > 0 ? _files : undefined, result.testCases);
|
|
78323
78359
|
let historyReport;
|
|
78324
78360
|
if (!result.success && result.totals && result.totals.failed > 0) {
|
|
@@ -78334,6 +78370,9 @@ var init_test_runner = __esm(() => {
|
|
|
78334
78370
|
if (graphFallbackReason && result.message) {
|
|
78335
78371
|
result.message = `${result.message} (${graphFallbackReason})`;
|
|
78336
78372
|
}
|
|
78373
|
+
if (bail && coverage && result.message) {
|
|
78374
|
+
result.message = `${result.message} (coverage may be incomplete: bail=true stopped early)`;
|
|
78375
|
+
}
|
|
78337
78376
|
return JSON.stringify(result, null, 2);
|
|
78338
78377
|
}
|
|
78339
78378
|
});
|
|
@@ -78538,7 +78577,7 @@ async function runLintCheck(dir, linter, timeoutMs) {
|
|
|
78538
78577
|
async function runTestsCheck(_dir, scope, timeoutMs) {
|
|
78539
78578
|
const startTime = Date.now();
|
|
78540
78579
|
try {
|
|
78541
|
-
const result = await runTests("none", scope, [], false, timeoutMs, _dir);
|
|
78580
|
+
const result = await runTests("none", scope, [], false, timeoutMs, _dir, false);
|
|
78542
78581
|
if (!result.success) {
|
|
78543
78582
|
return {
|
|
78544
78583
|
type: "tests",
|
|
@@ -91330,7 +91369,7 @@ async function scanDocIndex(directory) {
|
|
|
91330
91369
|
const resolvedDirectory = await realpath3(directory).catch(() => directory);
|
|
91331
91370
|
const discoveredFiles = [];
|
|
91332
91371
|
let rootReadable = false;
|
|
91333
|
-
const
|
|
91372
|
+
const walkDir2 = async (dir) => {
|
|
91334
91373
|
let entries;
|
|
91335
91374
|
try {
|
|
91336
91375
|
entries = await readdir6(dir, { withFileTypes: true });
|
|
@@ -91358,8 +91397,8 @@ async function scanDocIndex(directory) {
|
|
|
91358
91397
|
}
|
|
91359
91398
|
}
|
|
91360
91399
|
if (isDir) {
|
|
91361
|
-
if (!
|
|
91362
|
-
await
|
|
91400
|
+
if (!SKIP_DIRECTORIES4.has(entry.name)) {
|
|
91401
|
+
await walkDir2(path94.join(dir, entry.name));
|
|
91363
91402
|
}
|
|
91364
91403
|
continue;
|
|
91365
91404
|
}
|
|
@@ -91401,7 +91440,7 @@ async function scanDocIndex(directory) {
|
|
|
91401
91440
|
});
|
|
91402
91441
|
}
|
|
91403
91442
|
};
|
|
91404
|
-
await
|
|
91443
|
+
await walkDir2(directory);
|
|
91405
91444
|
if (!rootReadable) {
|
|
91406
91445
|
return {
|
|
91407
91446
|
manifest: {
|
|
@@ -91546,13 +91585,13 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
91546
91585
|
}
|
|
91547
91586
|
return { extracted: extractedCount, skipped: skippedCount, details };
|
|
91548
91587
|
}
|
|
91549
|
-
var
|
|
91588
|
+
var SKIP_DIRECTORIES4, SKIP_PATTERNS, MAX_SUMMARY_LENGTH = 200, MAX_INDEXED_FILES = 100, READ_LINES_LIMIT = 30, MIN_LESSON_LENGTH = 15, MAX_CONSTRAINTS_PER_DOC = 5, MAX_CONSTRAINT_LENGTH = 200, RELEVANCE_THRESHOLD = 0.1, DEDUP_THRESHOLD = 0.6, CONSTRAINT_PATTERNS, ACTION_WORDS, doc_scan, doc_extract;
|
|
91550
91589
|
var init_doc_scan = __esm(() => {
|
|
91551
91590
|
init_zod();
|
|
91552
91591
|
init_schema();
|
|
91553
91592
|
init_knowledge_store();
|
|
91554
91593
|
init_create_tool();
|
|
91555
|
-
|
|
91594
|
+
SKIP_DIRECTORIES4 = new Set([
|
|
91556
91595
|
"node_modules",
|
|
91557
91596
|
".git",
|
|
91558
91597
|
".swarm",
|
|
@@ -92406,11 +92445,11 @@ __export(exports_design_doc_drift, {
|
|
|
92406
92445
|
runDesignDocDriftCheck: () => runDesignDocDriftCheck,
|
|
92407
92446
|
_internals: () => _internals60
|
|
92408
92447
|
});
|
|
92409
|
-
import * as
|
|
92410
|
-
import * as
|
|
92448
|
+
import * as fs99 from "node:fs";
|
|
92449
|
+
import * as path138 from "node:path";
|
|
92411
92450
|
function mtimeMsOrNull(absPath) {
|
|
92412
92451
|
try {
|
|
92413
|
-
return
|
|
92452
|
+
return fs99.statSync(absPath).mtimeMs;
|
|
92414
92453
|
} catch {
|
|
92415
92454
|
return null;
|
|
92416
92455
|
}
|
|
@@ -92418,40 +92457,40 @@ function mtimeMsOrNull(absPath) {
|
|
|
92418
92457
|
function resolveAnchorWithin(directory, anchor) {
|
|
92419
92458
|
if (!anchor || typeof anchor !== "string")
|
|
92420
92459
|
return null;
|
|
92421
|
-
const root =
|
|
92422
|
-
const resolved =
|
|
92423
|
-
const rel =
|
|
92424
|
-
if (rel.startsWith("..") ||
|
|
92460
|
+
const root = path138.resolve(directory);
|
|
92461
|
+
const resolved = path138.resolve(root, anchor);
|
|
92462
|
+
const rel = path138.relative(root, resolved);
|
|
92463
|
+
if (rel.startsWith("..") || path138.isAbsolute(rel))
|
|
92425
92464
|
return null;
|
|
92426
92465
|
return resolved;
|
|
92427
92466
|
}
|
|
92428
92467
|
async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
92429
92468
|
try {
|
|
92430
|
-
const root =
|
|
92431
|
-
const outAbs =
|
|
92432
|
-
const outRel =
|
|
92433
|
-
if (outRel.startsWith("..") ||
|
|
92469
|
+
const root = path138.resolve(directory);
|
|
92470
|
+
const outAbs = path138.resolve(root, outDir);
|
|
92471
|
+
const outRel = path138.relative(root, outAbs);
|
|
92472
|
+
if (outRel.startsWith("..") || path138.isAbsolute(outRel)) {
|
|
92434
92473
|
return null;
|
|
92435
92474
|
}
|
|
92436
92475
|
const docMtimes = new Map;
|
|
92437
92476
|
const checkedDocs = [];
|
|
92438
92477
|
const missingDocs = [];
|
|
92439
92478
|
for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
|
|
92440
|
-
const abs =
|
|
92479
|
+
const abs = path138.join(outAbs, relFile);
|
|
92441
92480
|
const mtime = mtimeMsOrNull(abs);
|
|
92442
92481
|
docMtimes.set(docName, mtime);
|
|
92443
92482
|
if (mtime === null) {
|
|
92444
|
-
missingDocs.push(
|
|
92483
|
+
missingDocs.push(path138.join(outDir, relFile));
|
|
92445
92484
|
} else {
|
|
92446
|
-
checkedDocs.push(
|
|
92485
|
+
checkedDocs.push(path138.join(outDir, relFile));
|
|
92447
92486
|
}
|
|
92448
92487
|
}
|
|
92449
|
-
const traceabilityAbs =
|
|
92488
|
+
const traceabilityAbs = path138.join(outAbs, TRACEABILITY_REL);
|
|
92450
92489
|
let registry3 = null;
|
|
92451
92490
|
try {
|
|
92452
|
-
const stat9 = await
|
|
92491
|
+
const stat9 = await fs99.promises.stat(traceabilityAbs);
|
|
92453
92492
|
if (stat9.size <= MAX_TRACEABILITY_BYTES) {
|
|
92454
|
-
const raw = await
|
|
92493
|
+
const raw = await fs99.promises.readFile(traceabilityAbs, "utf-8");
|
|
92455
92494
|
const parsed = JSON.parse(raw);
|
|
92456
92495
|
registry3 = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
92457
92496
|
}
|
|
@@ -92459,7 +92498,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
92459
92498
|
registry3 = null;
|
|
92460
92499
|
}
|
|
92461
92500
|
const noDocs = checkedDocs.length === 0 || registry3 === null;
|
|
92462
|
-
const specMtime = mtimeMsOrNull(
|
|
92501
|
+
const specMtime = mtimeMsOrNull(path138.join(root, ".swarm", "spec.md"));
|
|
92463
92502
|
const staleSections = [];
|
|
92464
92503
|
if (!noDocs && Array.isArray(registry3?.sections)) {
|
|
92465
92504
|
for (const section of registry3.sections) {
|
|
@@ -92515,8 +92554,8 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
92515
92554
|
};
|
|
92516
92555
|
const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
|
|
92517
92556
|
const filePath = validateSwarmPath(directory, filename);
|
|
92518
|
-
await
|
|
92519
|
-
await
|
|
92557
|
+
await fs99.promises.mkdir(path138.dirname(filePath), { recursive: true });
|
|
92558
|
+
await fs99.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
92520
92559
|
getGlobalEventBus().publish("curator.docdrift.completed", {
|
|
92521
92560
|
phase,
|
|
92522
92561
|
verdict,
|
|
@@ -92546,10 +92585,10 @@ var init_design_doc_drift = __esm(() => {
|
|
|
92546
92585
|
domain: "domain.md",
|
|
92547
92586
|
"technical-spec": "technical-spec.md",
|
|
92548
92587
|
"behavior-spec": "behavior-spec.md",
|
|
92549
|
-
"reference-impl":
|
|
92550
|
-
"idiom-notes":
|
|
92588
|
+
"reference-impl": path138.join("reference", "reference-impl.md"),
|
|
92589
|
+
"idiom-notes": path138.join("reference", "idiom-notes.md")
|
|
92551
92590
|
};
|
|
92552
|
-
TRACEABILITY_REL =
|
|
92591
|
+
TRACEABILITY_REL = path138.join("reference", "traceability.json");
|
|
92553
92592
|
_internals60 = {
|
|
92554
92593
|
mtimeMsOrNull,
|
|
92555
92594
|
resolveAnchorWithin,
|
|
@@ -92564,12 +92603,12 @@ __export(exports_project_context, {
|
|
|
92564
92603
|
_internals: () => _internals71,
|
|
92565
92604
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
92566
92605
|
});
|
|
92567
|
-
import * as
|
|
92568
|
-
import * as
|
|
92606
|
+
import * as fs123 from "node:fs";
|
|
92607
|
+
import * as path167 from "node:path";
|
|
92569
92608
|
function detectFileExists2(directory, pattern) {
|
|
92570
92609
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
92571
92610
|
try {
|
|
92572
|
-
const files =
|
|
92611
|
+
const files = fs123.readdirSync(directory);
|
|
92573
92612
|
const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
|
|
92574
92613
|
return files.some((f) => regex.test(f));
|
|
92575
92614
|
} catch {
|
|
@@ -92577,7 +92616,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92577
92616
|
}
|
|
92578
92617
|
}
|
|
92579
92618
|
try {
|
|
92580
|
-
|
|
92619
|
+
fs123.accessSync(path167.join(directory, pattern));
|
|
92581
92620
|
return true;
|
|
92582
92621
|
} catch {
|
|
92583
92622
|
return false;
|
|
@@ -92586,7 +92625,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92586
92625
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
92587
92626
|
let pkgRaw;
|
|
92588
92627
|
try {
|
|
92589
|
-
pkgRaw =
|
|
92628
|
+
pkgRaw = fs123.readFileSync(path167.join(directory, "package.json"), "utf-8");
|
|
92590
92629
|
} catch {
|
|
92591
92630
|
return null;
|
|
92592
92631
|
}
|
|
@@ -92695,7 +92734,7 @@ var init_project_context = __esm(() => {
|
|
|
92695
92734
|
init_package();
|
|
92696
92735
|
init_agents2();
|
|
92697
92736
|
init_critic();
|
|
92698
|
-
import * as
|
|
92737
|
+
import * as path168 from "node:path";
|
|
92699
92738
|
|
|
92700
92739
|
// src/background/index.ts
|
|
92701
92740
|
init_event_bus();
|
|
@@ -95459,7 +95498,29 @@ init_path_security();
|
|
|
95459
95498
|
import * as fs49 from "node:fs";
|
|
95460
95499
|
import * as path79 from "node:path";
|
|
95461
95500
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
95501
|
+
var MAX_WORKSPACE_RESULTS = 50;
|
|
95502
|
+
var MAX_WORKSPACE_SCANNED_FILES = 200;
|
|
95503
|
+
var WORKSPACE_TIMEOUT_MS = 1e4;
|
|
95462
95504
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
95505
|
+
var SYMBOL_EXTENSIONS = new Set([
|
|
95506
|
+
".ts",
|
|
95507
|
+
".tsx",
|
|
95508
|
+
".js",
|
|
95509
|
+
".jsx",
|
|
95510
|
+
".mjs",
|
|
95511
|
+
".cjs",
|
|
95512
|
+
".py"
|
|
95513
|
+
]);
|
|
95514
|
+
var SKIP_DIRECTORIES2 = new Set([
|
|
95515
|
+
"node_modules",
|
|
95516
|
+
".git",
|
|
95517
|
+
"dist",
|
|
95518
|
+
"build",
|
|
95519
|
+
"out",
|
|
95520
|
+
".next",
|
|
95521
|
+
"coverage",
|
|
95522
|
+
"__pycache__"
|
|
95523
|
+
]);
|
|
95463
95524
|
function containsWindowsAttacks(str) {
|
|
95464
95525
|
if (/:[^\\/]/.test(str)) {
|
|
95465
95526
|
return true;
|
|
@@ -95704,28 +95765,135 @@ function extractPythonSymbols(filePath, cwd) {
|
|
|
95704
95765
|
return a.name.localeCompare(b.name);
|
|
95705
95766
|
});
|
|
95706
95767
|
}
|
|
95768
|
+
function findSourceFiles(cwd, maxFiles) {
|
|
95769
|
+
const files = [];
|
|
95770
|
+
walkDir(cwd, cwd, files, maxFiles);
|
|
95771
|
+
return files;
|
|
95772
|
+
}
|
|
95773
|
+
function walkDir(currentDir, rootDir, files, maxFiles) {
|
|
95774
|
+
let entries;
|
|
95775
|
+
try {
|
|
95776
|
+
entries = fs49.readdirSync(currentDir, { withFileTypes: true });
|
|
95777
|
+
} catch {
|
|
95778
|
+
return;
|
|
95779
|
+
}
|
|
95780
|
+
entries.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
|
|
95781
|
+
for (const entry of entries) {
|
|
95782
|
+
if (files.length >= maxFiles)
|
|
95783
|
+
return;
|
|
95784
|
+
if (SKIP_DIRECTORIES2.has(entry.name))
|
|
95785
|
+
continue;
|
|
95786
|
+
const fullPath = path79.join(currentDir, entry.name);
|
|
95787
|
+
if (entry.isDirectory()) {
|
|
95788
|
+
walkDir(fullPath, rootDir, files, maxFiles);
|
|
95789
|
+
} else if (entry.isFile() && SYMBOL_EXTENSIONS.has(path79.extname(entry.name).toLowerCase())) {
|
|
95790
|
+
files.push(path79.relative(rootDir, fullPath));
|
|
95791
|
+
}
|
|
95792
|
+
}
|
|
95793
|
+
}
|
|
95794
|
+
function searchWorkspaceSymbols(cwd, name2, exportedOnly = true) {
|
|
95795
|
+
const startTime = Date.now();
|
|
95796
|
+
const sourceFiles = findSourceFiles(cwd, MAX_WORKSPACE_SCANNED_FILES);
|
|
95797
|
+
const files = [];
|
|
95798
|
+
let scannedCount = 0;
|
|
95799
|
+
let truncated = false;
|
|
95800
|
+
if (sourceFiles.length >= MAX_WORKSPACE_SCANNED_FILES) {
|
|
95801
|
+
truncated = true;
|
|
95802
|
+
}
|
|
95803
|
+
let totalSymbols = 0;
|
|
95804
|
+
for (const relFile of sourceFiles) {
|
|
95805
|
+
if (Date.now() - startTime > WORKSPACE_TIMEOUT_MS) {
|
|
95806
|
+
truncated = true;
|
|
95807
|
+
break;
|
|
95808
|
+
}
|
|
95809
|
+
scannedCount++;
|
|
95810
|
+
let syms;
|
|
95811
|
+
const ext = path79.extname(relFile).toLowerCase();
|
|
95812
|
+
switch (ext) {
|
|
95813
|
+
case ".ts":
|
|
95814
|
+
case ".tsx":
|
|
95815
|
+
case ".js":
|
|
95816
|
+
case ".jsx":
|
|
95817
|
+
case ".mjs":
|
|
95818
|
+
case ".cjs":
|
|
95819
|
+
syms = extractTSSymbols(relFile, cwd);
|
|
95820
|
+
break;
|
|
95821
|
+
case ".py":
|
|
95822
|
+
syms = extractPythonSymbols(relFile, cwd);
|
|
95823
|
+
break;
|
|
95824
|
+
default:
|
|
95825
|
+
continue;
|
|
95826
|
+
}
|
|
95827
|
+
if (exportedOnly) {
|
|
95828
|
+
syms = syms.filter((s) => s.exported);
|
|
95829
|
+
}
|
|
95830
|
+
if (name2) {
|
|
95831
|
+
syms = syms.filter((s) => s.name.includes(name2));
|
|
95832
|
+
}
|
|
95833
|
+
if (syms.length > 0) {
|
|
95834
|
+
const remaining = MAX_WORKSPACE_RESULTS - totalSymbols;
|
|
95835
|
+
if (remaining <= 0) {
|
|
95836
|
+
truncated = true;
|
|
95837
|
+
break;
|
|
95838
|
+
}
|
|
95839
|
+
const cappedSyms = syms.slice(0, remaining);
|
|
95840
|
+
files.push({
|
|
95841
|
+
file: relFile,
|
|
95842
|
+
symbolCount: cappedSyms.length,
|
|
95843
|
+
symbols: cappedSyms
|
|
95844
|
+
});
|
|
95845
|
+
totalSymbols += cappedSyms.length;
|
|
95846
|
+
if (totalSymbols >= MAX_WORKSPACE_RESULTS) {
|
|
95847
|
+
truncated = syms.length > remaining || scannedCount < sourceFiles.length;
|
|
95848
|
+
break;
|
|
95849
|
+
}
|
|
95850
|
+
}
|
|
95851
|
+
}
|
|
95852
|
+
return {
|
|
95853
|
+
query: { workspace: true, name: name2 },
|
|
95854
|
+
fileCount: files.length,
|
|
95855
|
+
scannedFileCount: scannedCount,
|
|
95856
|
+
totalSymbols,
|
|
95857
|
+
files,
|
|
95858
|
+
truncated
|
|
95859
|
+
};
|
|
95860
|
+
}
|
|
95707
95861
|
var symbols = createSwarmTool({
|
|
95708
95862
|
description: "Extract all exported symbols from a source file: functions with signatures, " + "classes with public members, interfaces, types, enums, constants. " + "Supports TypeScript/JavaScript and Python. Use for architect planning, " + "designer scaffolding, and understanding module public API surface.",
|
|
95709
95863
|
args: {
|
|
95710
|
-
file: exports_external.string().describe('File path to extract symbols from (e.g., "src/auth/login.ts")'),
|
|
95711
|
-
exported_only: exports_external.boolean().default(true).describe("If true, only return exported/public symbols. If false, include all top-level symbols.")
|
|
95864
|
+
file: exports_external.string().optional().describe('File path to extract symbols from (e.g., "src/auth/login.ts"). Required when not using workspace mode.'),
|
|
95865
|
+
exported_only: exports_external.boolean().default(true).describe("If true, only return exported/public symbols. If false, include all top-level symbols."),
|
|
95866
|
+
workspace: exports_external.boolean().optional().describe("When true, search across the workspace instead of a single file. Returns per-file symbol summaries."),
|
|
95867
|
+
name: exports_external.string().optional().describe("Search for symbols by name (case-sensitive substring match). When provided without workspace, only searches the specified file.")
|
|
95712
95868
|
},
|
|
95713
95869
|
execute: async (args2, directory) => {
|
|
95714
95870
|
let file3;
|
|
95715
95871
|
let exportedOnly = true;
|
|
95872
|
+
let workspace = false;
|
|
95873
|
+
let name2;
|
|
95716
95874
|
try {
|
|
95717
95875
|
const obj = args2;
|
|
95718
|
-
file3 =
|
|
95876
|
+
file3 = obj.file != null && typeof obj.file === "string" ? obj.file : undefined;
|
|
95719
95877
|
exportedOnly = obj.exported_only === true;
|
|
95878
|
+
workspace = obj.workspace === true;
|
|
95879
|
+
name2 = obj.name != null && typeof obj.name === "string" ? obj.name : undefined;
|
|
95720
95880
|
} catch {
|
|
95721
95881
|
return JSON.stringify({
|
|
95722
95882
|
file: "<unknown>",
|
|
95723
|
-
error: "Invalid arguments: could not extract
|
|
95883
|
+
error: "Invalid arguments: could not extract parameters",
|
|
95724
95884
|
symbols: []
|
|
95725
95885
|
}, null, 2);
|
|
95726
95886
|
}
|
|
95727
95887
|
const cwd = directory;
|
|
95728
|
-
|
|
95888
|
+
if (workspace) {
|
|
95889
|
+
return JSON.stringify(searchWorkspaceSymbols(cwd, name2, exportedOnly), null, 2);
|
|
95890
|
+
}
|
|
95891
|
+
if (!file3) {
|
|
95892
|
+
return JSON.stringify({
|
|
95893
|
+
error: "file parameter is required when not using workspace mode",
|
|
95894
|
+
symbols: []
|
|
95895
|
+
}, null, 2);
|
|
95896
|
+
}
|
|
95729
95897
|
if (containsControlChars(file3)) {
|
|
95730
95898
|
return JSON.stringify({
|
|
95731
95899
|
file: file3,
|
|
@@ -95754,6 +95922,7 @@ var symbols = createSwarmTool({
|
|
|
95754
95922
|
symbols: []
|
|
95755
95923
|
}, null, 2);
|
|
95756
95924
|
}
|
|
95925
|
+
const ext = path79.extname(file3);
|
|
95757
95926
|
let syms;
|
|
95758
95927
|
switch (ext) {
|
|
95759
95928
|
case ".ts":
|
|
@@ -95777,6 +95946,9 @@ var symbols = createSwarmTool({
|
|
|
95777
95946
|
if (exportedOnly) {
|
|
95778
95947
|
syms = syms.filter((s) => s.exported);
|
|
95779
95948
|
}
|
|
95949
|
+
if (name2) {
|
|
95950
|
+
syms = syms.filter((s) => s.name.includes(name2));
|
|
95951
|
+
}
|
|
95780
95952
|
return JSON.stringify({
|
|
95781
95953
|
file: file3,
|
|
95782
95954
|
symbolCount: syms.length,
|
|
@@ -95925,7 +96097,7 @@ var _internals43 = {
|
|
|
95925
96097
|
extractPythonSymbols,
|
|
95926
96098
|
parseFileImports
|
|
95927
96099
|
};
|
|
95928
|
-
var
|
|
96100
|
+
var SKIP_DIRECTORIES3 = new Set([
|
|
95929
96101
|
"node_modules",
|
|
95930
96102
|
".git",
|
|
95931
96103
|
"dist",
|
|
@@ -96158,7 +96330,7 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
96158
96330
|
if (isWalkBudgetExceeded(ctx) || isFileCapReached(ctx, files.length)) {
|
|
96159
96331
|
break;
|
|
96160
96332
|
}
|
|
96161
|
-
if (
|
|
96333
|
+
if (SKIP_DIRECTORIES3.has(entry.name)) {
|
|
96162
96334
|
ctx.stats.skippedDirs++;
|
|
96163
96335
|
continue;
|
|
96164
96336
|
}
|
|
@@ -98162,7 +98334,7 @@ var DEFAULT_SKIP_DIRS = new Set([
|
|
|
98162
98334
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
98163
98335
|
var DEFAULT_MAX_FILES = 1e4;
|
|
98164
98336
|
var SOURCE_EXT_SET = new Set(SOURCE_EXTENSIONS2);
|
|
98165
|
-
function
|
|
98337
|
+
function findSourceFiles2(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
|
|
98166
98338
|
const out2 = [];
|
|
98167
98339
|
const stack = [workspaceRoot];
|
|
98168
98340
|
while (stack.length > 0) {
|
|
@@ -98199,7 +98371,7 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
|
|
|
98199
98371
|
}
|
|
98200
98372
|
async function buildRepoGraph(workspaceRoot, options = {}) {
|
|
98201
98373
|
const skipDirs = options.skipDirs ? new Set([...DEFAULT_SKIP_DIRS, ...options.skipDirs]) : DEFAULT_SKIP_DIRS;
|
|
98202
|
-
let files =
|
|
98374
|
+
let files = findSourceFiles2(workspaceRoot, skipDirs);
|
|
98203
98375
|
const cap = typeof options.maxFiles === "number" && options.maxFiles > 0 ? options.maxFiles : DEFAULT_MAX_FILES;
|
|
98204
98376
|
if (files.length > cap) {
|
|
98205
98377
|
files = files.slice(0, cap);
|
|
@@ -110252,10 +110424,12 @@ var diff = createSwarmTool({
|
|
|
110252
110424
|
description: "Analyze git diff for changed files, exports, interfaces, and function signatures. Returns structured output with contract change detection.",
|
|
110253
110425
|
args: {
|
|
110254
110426
|
base: exports_external.string().optional().describe('Base ref to diff against (default: HEAD). Use "staged" for staged changes, "unstaged" for working tree changes.'),
|
|
110255
|
-
paths: exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope.")
|
|
110427
|
+
paths: exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope."),
|
|
110428
|
+
summaryOnly: exports_external.boolean().optional().describe("When true, return only file list with additions/deletions counts and hasContractChanges. No hunk content or AST diff. Default false.")
|
|
110256
110429
|
},
|
|
110257
110430
|
async execute(args2, directory, _ctx) {
|
|
110258
110431
|
const typedArgs = args2;
|
|
110432
|
+
const summaryOnly = typedArgs.summaryOnly === true;
|
|
110259
110433
|
try {
|
|
110260
110434
|
let fileExistsInRef = function(refPath) {
|
|
110261
110435
|
try {
|
|
@@ -110333,13 +110507,6 @@ var diff = createSwarmTool({
|
|
|
110333
110507
|
cwd: directory,
|
|
110334
110508
|
stdio: ["ignore", "pipe", "pipe"]
|
|
110335
110509
|
});
|
|
110336
|
-
const fullDiffOutput = child_process7.execFileSync("git", fullDiffArgs, {
|
|
110337
|
-
encoding: "utf-8",
|
|
110338
|
-
timeout: DIFF_TIMEOUT_MS,
|
|
110339
|
-
maxBuffer: MAX_BUFFER_BYTES,
|
|
110340
|
-
cwd: directory,
|
|
110341
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
110342
|
-
});
|
|
110343
110510
|
const files = [];
|
|
110344
110511
|
const numstatLines = numstatOutput.split(`
|
|
110345
110512
|
`);
|
|
@@ -110354,6 +110521,50 @@ var diff = createSwarmTool({
|
|
|
110354
110521
|
files.push({ path: path118, additions, deletions });
|
|
110355
110522
|
}
|
|
110356
110523
|
}
|
|
110524
|
+
if (summaryOnly) {
|
|
110525
|
+
let hasContractChanges2 = false;
|
|
110526
|
+
try {
|
|
110527
|
+
const contractDiffArgs = [...gitArgs, "-U0"];
|
|
110528
|
+
if (typedArgs.paths?.length) {
|
|
110529
|
+
contractDiffArgs.push("--", ...typedArgs.paths);
|
|
110530
|
+
}
|
|
110531
|
+
const contractDiffOutput = child_process7.execFileSync("git", contractDiffArgs, {
|
|
110532
|
+
encoding: "utf-8",
|
|
110533
|
+
timeout: DIFF_TIMEOUT_MS,
|
|
110534
|
+
maxBuffer: MAX_BUFFER_BYTES,
|
|
110535
|
+
cwd: directory,
|
|
110536
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
110537
|
+
});
|
|
110538
|
+
const contractDiffLines = contractDiffOutput.split(`
|
|
110539
|
+
`);
|
|
110540
|
+
for (const line of contractDiffLines) {
|
|
110541
|
+
for (const pattern of CONTRACT_PATTERNS) {
|
|
110542
|
+
if (pattern.test(line)) {
|
|
110543
|
+
hasContractChanges2 = true;
|
|
110544
|
+
break;
|
|
110545
|
+
}
|
|
110546
|
+
}
|
|
110547
|
+
if (hasContractChanges2)
|
|
110548
|
+
break;
|
|
110549
|
+
}
|
|
110550
|
+
} catch {
|
|
110551
|
+
hasContractChanges2 = true;
|
|
110552
|
+
}
|
|
110553
|
+
const result2 = {
|
|
110554
|
+
files,
|
|
110555
|
+
contractChanges: [],
|
|
110556
|
+
hasContractChanges: hasContractChanges2,
|
|
110557
|
+
summary: `${files.length} files changed (summary only)`
|
|
110558
|
+
};
|
|
110559
|
+
return JSON.stringify(result2, null, 2);
|
|
110560
|
+
}
|
|
110561
|
+
const fullDiffOutput = child_process7.execFileSync("git", fullDiffArgs, {
|
|
110562
|
+
encoding: "utf-8",
|
|
110563
|
+
timeout: DIFF_TIMEOUT_MS,
|
|
110564
|
+
maxBuffer: MAX_BUFFER_BYTES,
|
|
110565
|
+
cwd: directory,
|
|
110566
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
110567
|
+
});
|
|
110357
110568
|
const contractChanges = [];
|
|
110358
110569
|
const diffLines = fullDiffOutput.split(`
|
|
110359
110570
|
`);
|
|
@@ -111419,13 +111630,389 @@ var get_qa_gate_profile = createSwarmTool({
|
|
|
111419
111630
|
}
|
|
111420
111631
|
});
|
|
111421
111632
|
|
|
111633
|
+
// src/tools/git-blame.ts
|
|
111634
|
+
init_zod();
|
|
111635
|
+
init_path_security();
|
|
111636
|
+
init_create_tool();
|
|
111637
|
+
import * as child_process9 from "node:child_process";
|
|
111638
|
+
import * as fs83 from "node:fs";
|
|
111639
|
+
import * as path121 from "node:path";
|
|
111640
|
+
var BLAME_TIMEOUT_MS = 30000;
|
|
111641
|
+
var MAX_OUTPUT_LINES2 = 500;
|
|
111642
|
+
var MAX_PATH_LENGTH2 = 500;
|
|
111643
|
+
var MAX_LINE_NUMBER = 1e6;
|
|
111644
|
+
var SHELL_METACHARACTERS3 = /[;|&$`(){}<>!'"]/;
|
|
111645
|
+
var BINARY_EXTENSIONS = new Set([
|
|
111646
|
+
".png",
|
|
111647
|
+
".jpg",
|
|
111648
|
+
".jpeg",
|
|
111649
|
+
".gif",
|
|
111650
|
+
".bmp",
|
|
111651
|
+
".ico",
|
|
111652
|
+
".svg",
|
|
111653
|
+
".webp",
|
|
111654
|
+
".mp3",
|
|
111655
|
+
".mp4",
|
|
111656
|
+
".wav",
|
|
111657
|
+
".avi",
|
|
111658
|
+
".mov",
|
|
111659
|
+
".wmv",
|
|
111660
|
+
".flv",
|
|
111661
|
+
".zip",
|
|
111662
|
+
".tar",
|
|
111663
|
+
".gz",
|
|
111664
|
+
".rar",
|
|
111665
|
+
".7z",
|
|
111666
|
+
".bz2",
|
|
111667
|
+
".pdf",
|
|
111668
|
+
".doc",
|
|
111669
|
+
".docx",
|
|
111670
|
+
".xls",
|
|
111671
|
+
".xlsx",
|
|
111672
|
+
".ppt",
|
|
111673
|
+
".pptx",
|
|
111674
|
+
".exe",
|
|
111675
|
+
".dll",
|
|
111676
|
+
".so",
|
|
111677
|
+
".dylib",
|
|
111678
|
+
".bin",
|
|
111679
|
+
".dat",
|
|
111680
|
+
".o",
|
|
111681
|
+
".obj",
|
|
111682
|
+
".woff",
|
|
111683
|
+
".woff2",
|
|
111684
|
+
".ttf",
|
|
111685
|
+
".eot",
|
|
111686
|
+
".otf",
|
|
111687
|
+
".sqlite",
|
|
111688
|
+
".db"
|
|
111689
|
+
]);
|
|
111690
|
+
function validateFilePath(filePath) {
|
|
111691
|
+
if (!filePath || filePath.length === 0) {
|
|
111692
|
+
return "file path is required";
|
|
111693
|
+
}
|
|
111694
|
+
if (filePath.length > MAX_PATH_LENGTH2) {
|
|
111695
|
+
return `file path exceeds maximum length of ${MAX_PATH_LENGTH2}`;
|
|
111696
|
+
}
|
|
111697
|
+
if (path121.isAbsolute(filePath)) {
|
|
111698
|
+
return "absolute paths are not allowed; use a relative path from the project root";
|
|
111699
|
+
}
|
|
111700
|
+
if (containsPathTraversal(filePath)) {
|
|
111701
|
+
return "path traversal detected";
|
|
111702
|
+
}
|
|
111703
|
+
if (containsControlChars(filePath)) {
|
|
111704
|
+
return "file path contains control characters";
|
|
111705
|
+
}
|
|
111706
|
+
if (SHELL_METACHARACTERS3.test(filePath)) {
|
|
111707
|
+
return "file path contains shell metacharacters";
|
|
111708
|
+
}
|
|
111709
|
+
if (filePath.startsWith("-")) {
|
|
111710
|
+
return 'file path cannot start with "-"';
|
|
111711
|
+
}
|
|
111712
|
+
return null;
|
|
111713
|
+
}
|
|
111714
|
+
function validateLineNumber(value, name2) {
|
|
111715
|
+
if (typeof value === "undefined")
|
|
111716
|
+
return null;
|
|
111717
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
|
|
111718
|
+
return `${name2} must be a positive integer`;
|
|
111719
|
+
}
|
|
111720
|
+
if (value > MAX_LINE_NUMBER) {
|
|
111721
|
+
return `${name2} exceeds maximum value of ${MAX_LINE_NUMBER}`;
|
|
111722
|
+
}
|
|
111723
|
+
return null;
|
|
111724
|
+
}
|
|
111725
|
+
function isBinaryFile2(filePath) {
|
|
111726
|
+
const ext = path121.extname(filePath).toLowerCase();
|
|
111727
|
+
return BINARY_EXTENSIONS.has(ext);
|
|
111728
|
+
}
|
|
111729
|
+
function parsePorcelainBlame(output, linesCap) {
|
|
111730
|
+
const entries = [];
|
|
111731
|
+
const outputLines = output.split(`
|
|
111732
|
+
`);
|
|
111733
|
+
const cappedLines = outputLines.slice(0, linesCap * 8);
|
|
111734
|
+
const commitCache = new Map;
|
|
111735
|
+
let currentSha = "";
|
|
111736
|
+
let currentLine = 0;
|
|
111737
|
+
let currentAuthor = "";
|
|
111738
|
+
let currentAuthorTime = "";
|
|
111739
|
+
let currentSummary = "";
|
|
111740
|
+
for (const rawLine of cappedLines) {
|
|
111741
|
+
const headerMatch = rawLine.match(/^([0-9a-f]{40})\s+(\d+)\s+(\d+)/);
|
|
111742
|
+
if (headerMatch) {
|
|
111743
|
+
currentSha = headerMatch[1];
|
|
111744
|
+
currentLine = Number.parseInt(headerMatch[3], 10);
|
|
111745
|
+
const cached3 = commitCache.get(currentSha);
|
|
111746
|
+
if (cached3) {
|
|
111747
|
+
currentAuthor = cached3.author;
|
|
111748
|
+
currentAuthorTime = cached3.authorTime;
|
|
111749
|
+
currentSummary = cached3.summary;
|
|
111750
|
+
} else {
|
|
111751
|
+
currentAuthor = "";
|
|
111752
|
+
currentAuthorTime = "";
|
|
111753
|
+
currentSummary = "";
|
|
111754
|
+
}
|
|
111755
|
+
continue;
|
|
111756
|
+
}
|
|
111757
|
+
if (rawLine.startsWith("author ")) {
|
|
111758
|
+
currentAuthor = rawLine.slice(7);
|
|
111759
|
+
let meta3 = commitCache.get(currentSha);
|
|
111760
|
+
if (!meta3) {
|
|
111761
|
+
meta3 = { author: "", authorTime: "", summary: "" };
|
|
111762
|
+
commitCache.set(currentSha, meta3);
|
|
111763
|
+
}
|
|
111764
|
+
meta3.author = currentAuthor;
|
|
111765
|
+
continue;
|
|
111766
|
+
}
|
|
111767
|
+
if (rawLine.startsWith("author-time ")) {
|
|
111768
|
+
currentAuthorTime = rawLine.slice(12);
|
|
111769
|
+
let meta3 = commitCache.get(currentSha);
|
|
111770
|
+
if (!meta3) {
|
|
111771
|
+
meta3 = { author: "", authorTime: "", summary: "" };
|
|
111772
|
+
commitCache.set(currentSha, meta3);
|
|
111773
|
+
}
|
|
111774
|
+
meta3.authorTime = currentAuthorTime;
|
|
111775
|
+
continue;
|
|
111776
|
+
}
|
|
111777
|
+
if (rawLine.startsWith("summary ")) {
|
|
111778
|
+
currentSummary = rawLine.slice(8);
|
|
111779
|
+
let meta3 = commitCache.get(currentSha);
|
|
111780
|
+
if (!meta3) {
|
|
111781
|
+
meta3 = { author: "", authorTime: "", summary: "" };
|
|
111782
|
+
commitCache.set(currentSha, meta3);
|
|
111783
|
+
}
|
|
111784
|
+
meta3.summary = currentSummary;
|
|
111785
|
+
continue;
|
|
111786
|
+
}
|
|
111787
|
+
if (rawLine.startsWith("\t")) {
|
|
111788
|
+
entries.push({
|
|
111789
|
+
line: currentLine,
|
|
111790
|
+
sha: currentSha.slice(0, 8),
|
|
111791
|
+
author: currentAuthor,
|
|
111792
|
+
authorTime: currentAuthorTime,
|
|
111793
|
+
summary: currentSummary,
|
|
111794
|
+
content: rawLine.slice(1)
|
|
111795
|
+
});
|
|
111796
|
+
if (entries.length >= linesCap)
|
|
111797
|
+
break;
|
|
111798
|
+
}
|
|
111799
|
+
}
|
|
111800
|
+
return entries.slice(0, linesCap);
|
|
111801
|
+
}
|
|
111802
|
+
var git_blame = createSwarmTool({
|
|
111803
|
+
description: "Analyze per-line git blame metadata for a file. Returns sha (abbreviated), author, date (ISO), summary, and content for each line. Uses git blame --porcelain. Rejects binary files and validates paths.",
|
|
111804
|
+
args: {
|
|
111805
|
+
file: exports_external.string().describe("Relative file path to blame (required, relative to project root)"),
|
|
111806
|
+
start: exports_external.number().optional().describe("Optional start line number (1-indexed). Requires end parameter."),
|
|
111807
|
+
end: exports_external.number().optional().describe("Optional end line number (1-indexed, inclusive). Requires start parameter.")
|
|
111808
|
+
},
|
|
111809
|
+
async execute(args2, directory) {
|
|
111810
|
+
let fileInput;
|
|
111811
|
+
let startInput;
|
|
111812
|
+
let endInput;
|
|
111813
|
+
try {
|
|
111814
|
+
if (args2 && typeof args2 === "object") {
|
|
111815
|
+
const obj = args2;
|
|
111816
|
+
fileInput = typeof obj.file === "string" ? obj.file : undefined;
|
|
111817
|
+
startInput = typeof obj.start === "number" ? obj.start : undefined;
|
|
111818
|
+
endInput = typeof obj.end === "number" ? obj.end : undefined;
|
|
111819
|
+
}
|
|
111820
|
+
} catch {}
|
|
111821
|
+
if (!fileInput) {
|
|
111822
|
+
return JSON.stringify({
|
|
111823
|
+
error: "file path is required",
|
|
111824
|
+
file: String(fileInput ?? ""),
|
|
111825
|
+
lineCount: 0,
|
|
111826
|
+
lines: []
|
|
111827
|
+
});
|
|
111828
|
+
}
|
|
111829
|
+
const file3 = fileInput;
|
|
111830
|
+
const pathError = validateFilePath(file3);
|
|
111831
|
+
if (pathError) {
|
|
111832
|
+
return JSON.stringify({
|
|
111833
|
+
error: pathError,
|
|
111834
|
+
file: file3,
|
|
111835
|
+
lineCount: 0,
|
|
111836
|
+
lines: []
|
|
111837
|
+
});
|
|
111838
|
+
}
|
|
111839
|
+
const startError = validateLineNumber(startInput, "start");
|
|
111840
|
+
if (startError) {
|
|
111841
|
+
return JSON.stringify({
|
|
111842
|
+
error: startError,
|
|
111843
|
+
file: file3,
|
|
111844
|
+
lineCount: 0,
|
|
111845
|
+
lines: []
|
|
111846
|
+
});
|
|
111847
|
+
}
|
|
111848
|
+
const endError = validateLineNumber(endInput, "end");
|
|
111849
|
+
if (endError) {
|
|
111850
|
+
return JSON.stringify({
|
|
111851
|
+
error: endError,
|
|
111852
|
+
file: file3,
|
|
111853
|
+
lineCount: 0,
|
|
111854
|
+
lines: []
|
|
111855
|
+
});
|
|
111856
|
+
}
|
|
111857
|
+
if (startInput !== undefined && endInput === undefined || startInput === undefined && endInput !== undefined) {
|
|
111858
|
+
return JSON.stringify({
|
|
111859
|
+
error: "both start and end must be provided together for a line range",
|
|
111860
|
+
file: file3,
|
|
111861
|
+
lineCount: 0,
|
|
111862
|
+
lines: []
|
|
111863
|
+
});
|
|
111864
|
+
}
|
|
111865
|
+
if (startInput !== undefined && endInput !== undefined && startInput > endInput) {
|
|
111866
|
+
return JSON.stringify({
|
|
111867
|
+
error: "start must be less than or equal to end",
|
|
111868
|
+
file: file3,
|
|
111869
|
+
lineCount: 0,
|
|
111870
|
+
lines: []
|
|
111871
|
+
});
|
|
111872
|
+
}
|
|
111873
|
+
const resolvedPath = path121.resolve(directory, file3);
|
|
111874
|
+
if (!fs83.existsSync(resolvedPath)) {
|
|
111875
|
+
return JSON.stringify({
|
|
111876
|
+
error: `file not found: ${file3}`,
|
|
111877
|
+
file: file3,
|
|
111878
|
+
lineCount: 0,
|
|
111879
|
+
lines: []
|
|
111880
|
+
});
|
|
111881
|
+
}
|
|
111882
|
+
const realDir = fs83.realpathSync(directory);
|
|
111883
|
+
const realPath = fs83.realpathSync(resolvedPath);
|
|
111884
|
+
const relative25 = path121.relative(realDir, realPath);
|
|
111885
|
+
if (relative25.startsWith("..") || path121.isAbsolute(relative25)) {
|
|
111886
|
+
return JSON.stringify({
|
|
111887
|
+
error: "file path resolves outside the workspace",
|
|
111888
|
+
file: file3,
|
|
111889
|
+
lineCount: 0,
|
|
111890
|
+
lines: []
|
|
111891
|
+
});
|
|
111892
|
+
}
|
|
111893
|
+
const stat9 = fs83.statSync(resolvedPath);
|
|
111894
|
+
if (stat9.isDirectory()) {
|
|
111895
|
+
return JSON.stringify({
|
|
111896
|
+
error: "path is a directory, not a file",
|
|
111897
|
+
file: file3,
|
|
111898
|
+
lineCount: 0,
|
|
111899
|
+
lines: []
|
|
111900
|
+
});
|
|
111901
|
+
}
|
|
111902
|
+
if (isBinaryFile2(file3)) {
|
|
111903
|
+
return JSON.stringify({
|
|
111904
|
+
error: "binary files are not supported for git blame",
|
|
111905
|
+
file: file3,
|
|
111906
|
+
lineCount: 0,
|
|
111907
|
+
lines: []
|
|
111908
|
+
});
|
|
111909
|
+
}
|
|
111910
|
+
const gitArgs = ["blame", "--porcelain"];
|
|
111911
|
+
if (startInput !== undefined && endInput !== undefined) {
|
|
111912
|
+
gitArgs.push("-L", `${startInput},${endInput}`);
|
|
111913
|
+
}
|
|
111914
|
+
gitArgs.push("--", file3);
|
|
111915
|
+
const result = child_process9.spawnSync("git", gitArgs, {
|
|
111916
|
+
cwd: directory,
|
|
111917
|
+
encoding: "utf-8",
|
|
111918
|
+
timeout: BLAME_TIMEOUT_MS,
|
|
111919
|
+
windowsHide: true,
|
|
111920
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
111921
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
111922
|
+
});
|
|
111923
|
+
if (result.error) {
|
|
111924
|
+
const isTimeout = "code" in result.error && result.error.code === "ETIMEDOUT";
|
|
111925
|
+
if (isTimeout) {
|
|
111926
|
+
return JSON.stringify({
|
|
111927
|
+
error: "git blame timed out",
|
|
111928
|
+
file: file3,
|
|
111929
|
+
lineCount: 0,
|
|
111930
|
+
lines: []
|
|
111931
|
+
});
|
|
111932
|
+
}
|
|
111933
|
+
const message = result.error instanceof Error ? result.error.message : String(result.error);
|
|
111934
|
+
if (message.includes("ENOENT") || message.includes("not found")) {
|
|
111935
|
+
return JSON.stringify({
|
|
111936
|
+
error: "git is not available or not in PATH",
|
|
111937
|
+
file: file3,
|
|
111938
|
+
lineCount: 0,
|
|
111939
|
+
lines: []
|
|
111940
|
+
});
|
|
111941
|
+
}
|
|
111942
|
+
return JSON.stringify({
|
|
111943
|
+
error: `git execution failed: ${message}`,
|
|
111944
|
+
file: file3,
|
|
111945
|
+
lineCount: 0,
|
|
111946
|
+
lines: []
|
|
111947
|
+
});
|
|
111948
|
+
}
|
|
111949
|
+
if (result.status !== 0) {
|
|
111950
|
+
const stderr = (result.stderr ?? "").trim();
|
|
111951
|
+
if (stderr.includes("not a git repository") || stderr.includes("not in a git repository")) {
|
|
111952
|
+
return JSON.stringify({
|
|
111953
|
+
error: "not a git repository",
|
|
111954
|
+
file: file3,
|
|
111955
|
+
lineCount: 0,
|
|
111956
|
+
lines: []
|
|
111957
|
+
});
|
|
111958
|
+
}
|
|
111959
|
+
if (stderr.includes("no such path") || stderr.includes("did not match any files")) {
|
|
111960
|
+
return JSON.stringify({
|
|
111961
|
+
error: `file not tracked by git: ${file3}`,
|
|
111962
|
+
file: file3,
|
|
111963
|
+
lineCount: 0,
|
|
111964
|
+
lines: []
|
|
111965
|
+
});
|
|
111966
|
+
}
|
|
111967
|
+
return JSON.stringify({
|
|
111968
|
+
error: `git blame failed: ${stderr || `exit code ${result.status}`}`,
|
|
111969
|
+
file: file3,
|
|
111970
|
+
lineCount: 0,
|
|
111971
|
+
lines: []
|
|
111972
|
+
});
|
|
111973
|
+
}
|
|
111974
|
+
if (result.signal === "SIGTERM" || result.signal === "SIGKILL") {
|
|
111975
|
+
return JSON.stringify({
|
|
111976
|
+
error: "git blame timed out",
|
|
111977
|
+
file: file3,
|
|
111978
|
+
lineCount: 0,
|
|
111979
|
+
lines: []
|
|
111980
|
+
});
|
|
111981
|
+
}
|
|
111982
|
+
const stdout = result.stdout ?? "";
|
|
111983
|
+
if (!stdout.trim()) {
|
|
111984
|
+
return JSON.stringify({
|
|
111985
|
+
error: "no blame output (file may be empty or untracked)",
|
|
111986
|
+
file: file3,
|
|
111987
|
+
lineCount: 0,
|
|
111988
|
+
lines: []
|
|
111989
|
+
});
|
|
111990
|
+
}
|
|
111991
|
+
const rawEntries = parsePorcelainBlame(stdout, MAX_OUTPUT_LINES2);
|
|
111992
|
+
const lines = rawEntries.map((entry) => ({
|
|
111993
|
+
line: entry.line,
|
|
111994
|
+
sha: entry.sha,
|
|
111995
|
+
author: entry.author,
|
|
111996
|
+
date: Number.parseInt(entry.authorTime, 10) > 0 ? new Date(Number.parseInt(entry.authorTime, 10) * 1000).toISOString().slice(0, 10) : entry.authorTime,
|
|
111997
|
+
summary: entry.summary,
|
|
111998
|
+
content: entry.content
|
|
111999
|
+
}));
|
|
112000
|
+
const resultJson = {
|
|
112001
|
+
file: file3,
|
|
112002
|
+
lineCount: lines.length,
|
|
112003
|
+
lines
|
|
112004
|
+
};
|
|
112005
|
+
return JSON.stringify(resultJson, null, 2);
|
|
112006
|
+
}
|
|
112007
|
+
});
|
|
112008
|
+
|
|
111422
112009
|
// src/tools/gitingest.ts
|
|
111423
112010
|
init_zod();
|
|
111424
112011
|
init_create_tool();
|
|
111425
112012
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
111426
112013
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
111427
112014
|
var GITINGEST_MAX_RETRIES = 2;
|
|
111428
|
-
var delay = (ms) => new Promise((
|
|
112015
|
+
var delay = (ms) => new Promise((resolve44) => setTimeout(resolve44, ms));
|
|
111429
112016
|
async function fetchGitingest(args2) {
|
|
111430
112017
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
111431
112018
|
try {
|
|
@@ -111513,8 +112100,8 @@ var gitingest = createSwarmTool({
|
|
|
111513
112100
|
init_zod();
|
|
111514
112101
|
init_create_tool();
|
|
111515
112102
|
init_path_security();
|
|
111516
|
-
import * as
|
|
111517
|
-
import * as
|
|
112103
|
+
import * as fs84 from "node:fs";
|
|
112104
|
+
import * as path122 from "node:path";
|
|
111518
112105
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
111519
112106
|
var MAX_SYMBOL_LENGTH = 256;
|
|
111520
112107
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -111561,8 +112148,8 @@ function validateSymbolInput(symbol3) {
|
|
|
111561
112148
|
}
|
|
111562
112149
|
return null;
|
|
111563
112150
|
}
|
|
111564
|
-
function
|
|
111565
|
-
const ext =
|
|
112151
|
+
function isBinaryFile3(filePath, buffer) {
|
|
112152
|
+
const ext = path122.extname(filePath).toLowerCase();
|
|
111566
112153
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
111567
112154
|
return false;
|
|
111568
112155
|
}
|
|
@@ -111586,15 +112173,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
111586
112173
|
const imports = [];
|
|
111587
112174
|
let _resolvedTarget;
|
|
111588
112175
|
try {
|
|
111589
|
-
_resolvedTarget =
|
|
112176
|
+
_resolvedTarget = path122.resolve(targetFile);
|
|
111590
112177
|
} catch {
|
|
111591
112178
|
_resolvedTarget = targetFile;
|
|
111592
112179
|
}
|
|
111593
|
-
const targetBasename =
|
|
112180
|
+
const targetBasename = path122.basename(targetFile, path122.extname(targetFile));
|
|
111594
112181
|
const targetWithExt = targetFile;
|
|
111595
112182
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
111596
|
-
const normalizedTargetWithExt =
|
|
111597
|
-
const normalizedTargetWithoutExt =
|
|
112183
|
+
const normalizedTargetWithExt = path122.normalize(targetWithExt).replace(/\\/g, "/");
|
|
112184
|
+
const normalizedTargetWithoutExt = path122.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
111598
112185
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
111599
112186
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
111600
112187
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -111617,9 +112204,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
111617
112204
|
}
|
|
111618
112205
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
111619
112206
|
let isMatch = false;
|
|
111620
|
-
const _targetDir =
|
|
111621
|
-
const targetExt =
|
|
111622
|
-
const targetBasenameNoExt =
|
|
112207
|
+
const _targetDir = path122.dirname(targetFile);
|
|
112208
|
+
const targetExt = path122.extname(targetFile);
|
|
112209
|
+
const targetBasenameNoExt = path122.basename(targetFile, targetExt);
|
|
111623
112210
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
111624
112211
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
111625
112212
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -111659,7 +112246,7 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
111659
112246
|
}
|
|
111660
112247
|
return imports;
|
|
111661
112248
|
}
|
|
111662
|
-
var
|
|
112249
|
+
var SKIP_DIRECTORIES5 = new Set([
|
|
111663
112250
|
"node_modules",
|
|
111664
112251
|
".git",
|
|
111665
112252
|
"dist",
|
|
@@ -111673,10 +112260,10 @@ var SKIP_DIRECTORIES4 = new Set([
|
|
|
111673
112260
|
".svn",
|
|
111674
112261
|
".hg"
|
|
111675
112262
|
]);
|
|
111676
|
-
function
|
|
112263
|
+
function findSourceFiles3(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
111677
112264
|
let entries;
|
|
111678
112265
|
try {
|
|
111679
|
-
entries =
|
|
112266
|
+
entries = fs84.readdirSync(dir);
|
|
111680
112267
|
} catch (e) {
|
|
111681
112268
|
stats.fileErrors.push({
|
|
111682
112269
|
path: dir,
|
|
@@ -111686,14 +112273,14 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
111686
112273
|
}
|
|
111687
112274
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
111688
112275
|
for (const entry of entries) {
|
|
111689
|
-
if (
|
|
111690
|
-
stats.skippedDirs.push(
|
|
112276
|
+
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
112277
|
+
stats.skippedDirs.push(path122.join(dir, entry));
|
|
111691
112278
|
continue;
|
|
111692
112279
|
}
|
|
111693
|
-
const fullPath =
|
|
112280
|
+
const fullPath = path122.join(dir, entry);
|
|
111694
112281
|
let stat9;
|
|
111695
112282
|
try {
|
|
111696
|
-
stat9 =
|
|
112283
|
+
stat9 = fs84.statSync(fullPath);
|
|
111697
112284
|
} catch (e) {
|
|
111698
112285
|
stats.fileErrors.push({
|
|
111699
112286
|
path: fullPath,
|
|
@@ -111702,9 +112289,9 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
111702
112289
|
continue;
|
|
111703
112290
|
}
|
|
111704
112291
|
if (stat9.isDirectory()) {
|
|
111705
|
-
|
|
112292
|
+
findSourceFiles3(fullPath, files, stats);
|
|
111706
112293
|
} else if (stat9.isFile()) {
|
|
111707
|
-
const ext =
|
|
112294
|
+
const ext = path122.extname(fullPath).toLowerCase();
|
|
111708
112295
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
111709
112296
|
files.push(fullPath);
|
|
111710
112297
|
}
|
|
@@ -111761,8 +112348,8 @@ var imports = createSwarmTool({
|
|
|
111761
112348
|
return JSON.stringify(errorResult, null, 2);
|
|
111762
112349
|
}
|
|
111763
112350
|
try {
|
|
111764
|
-
const targetFile =
|
|
111765
|
-
if (!
|
|
112351
|
+
const targetFile = path122.resolve(file3);
|
|
112352
|
+
if (!fs84.existsSync(targetFile)) {
|
|
111766
112353
|
const errorResult = {
|
|
111767
112354
|
error: `target file not found: ${file3}`,
|
|
111768
112355
|
target: file3,
|
|
@@ -111772,7 +112359,7 @@ var imports = createSwarmTool({
|
|
|
111772
112359
|
};
|
|
111773
112360
|
return JSON.stringify(errorResult, null, 2);
|
|
111774
112361
|
}
|
|
111775
|
-
const targetStat =
|
|
112362
|
+
const targetStat = fs84.statSync(targetFile);
|
|
111776
112363
|
if (!targetStat.isFile()) {
|
|
111777
112364
|
const errorResult = {
|
|
111778
112365
|
error: "target must be a file, not a directory",
|
|
@@ -111783,13 +112370,13 @@ var imports = createSwarmTool({
|
|
|
111783
112370
|
};
|
|
111784
112371
|
return JSON.stringify(errorResult, null, 2);
|
|
111785
112372
|
}
|
|
111786
|
-
const baseDir =
|
|
112373
|
+
const baseDir = path122.dirname(targetFile);
|
|
111787
112374
|
const scanStats = {
|
|
111788
112375
|
skippedDirs: [],
|
|
111789
112376
|
skippedFiles: 0,
|
|
111790
112377
|
fileErrors: []
|
|
111791
112378
|
};
|
|
111792
|
-
const sourceFiles =
|
|
112379
|
+
const sourceFiles = findSourceFiles3(baseDir, [], scanStats);
|
|
111793
112380
|
const filesToScan = sourceFiles.filter((f) => f !== targetFile).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).slice(0, MAX_CONSUMERS * 10);
|
|
111794
112381
|
const consumers = [];
|
|
111795
112382
|
let skippedFileCount = 0;
|
|
@@ -111798,13 +112385,13 @@ var imports = createSwarmTool({
|
|
|
111798
112385
|
if (consumers.length >= MAX_CONSUMERS)
|
|
111799
112386
|
break;
|
|
111800
112387
|
try {
|
|
111801
|
-
const stat9 =
|
|
112388
|
+
const stat9 = fs84.statSync(filePath);
|
|
111802
112389
|
if (stat9.size > MAX_FILE_SIZE_BYTES7) {
|
|
111803
112390
|
skippedFileCount++;
|
|
111804
112391
|
continue;
|
|
111805
112392
|
}
|
|
111806
|
-
const buffer =
|
|
111807
|
-
if (
|
|
112393
|
+
const buffer = fs84.readFileSync(filePath);
|
|
112394
|
+
if (isBinaryFile3(filePath, buffer)) {
|
|
111808
112395
|
skippedFileCount++;
|
|
111809
112396
|
continue;
|
|
111810
112397
|
}
|
|
@@ -112171,7 +112758,7 @@ init_zod();
|
|
|
112171
112758
|
init_config();
|
|
112172
112759
|
init_knowledge_store();
|
|
112173
112760
|
init_create_tool();
|
|
112174
|
-
import { existsSync as
|
|
112761
|
+
import { existsSync as existsSync70 } from "node:fs";
|
|
112175
112762
|
var DEFAULT_LIMIT = 10;
|
|
112176
112763
|
var MAX_LESSON_LENGTH = 200;
|
|
112177
112764
|
var VALID_CATEGORIES3 = [
|
|
@@ -112247,14 +112834,14 @@ function validateLimit(limit) {
|
|
|
112247
112834
|
}
|
|
112248
112835
|
async function readSwarmKnowledge(directory) {
|
|
112249
112836
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
112250
|
-
if (!
|
|
112837
|
+
if (!existsSync70(swarmPath)) {
|
|
112251
112838
|
return [];
|
|
112252
112839
|
}
|
|
112253
112840
|
return readKnowledge(swarmPath);
|
|
112254
112841
|
}
|
|
112255
112842
|
async function readHiveKnowledge() {
|
|
112256
112843
|
const hivePath = resolveHiveKnowledgePath();
|
|
112257
|
-
if (!
|
|
112844
|
+
if (!existsSync70(hivePath)) {
|
|
112258
112845
|
return [];
|
|
112259
112846
|
}
|
|
112260
112847
|
return readKnowledge(hivePath);
|
|
@@ -112679,12 +113266,12 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
112679
113266
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
112680
113267
|
init_zod();
|
|
112681
113268
|
init_constants();
|
|
112682
|
-
import * as
|
|
112683
|
-
import * as
|
|
113269
|
+
import * as fs86 from "node:fs";
|
|
113270
|
+
import * as path124 from "node:path";
|
|
112684
113271
|
|
|
112685
113272
|
// src/turbo/lean/conflicts.ts
|
|
112686
|
-
import * as
|
|
112687
|
-
import * as
|
|
113273
|
+
import * as fs85 from "node:fs";
|
|
113274
|
+
import * as path123 from "node:path";
|
|
112688
113275
|
var DEFAULT_GLOBAL_FILES = [
|
|
112689
113276
|
"package.json",
|
|
112690
113277
|
"package-lock.json",
|
|
@@ -112811,12 +113398,12 @@ function isProtectedPath3(normalizedPath) {
|
|
|
112811
113398
|
return false;
|
|
112812
113399
|
}
|
|
112813
113400
|
function readTaskScopes(directory, taskId) {
|
|
112814
|
-
const scopePath =
|
|
113401
|
+
const scopePath = path123.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
112815
113402
|
try {
|
|
112816
|
-
if (!
|
|
113403
|
+
if (!fs85.existsSync(scopePath)) {
|
|
112817
113404
|
return null;
|
|
112818
113405
|
}
|
|
112819
|
-
const raw =
|
|
113406
|
+
const raw = fs85.readFileSync(scopePath, "utf-8");
|
|
112820
113407
|
const parsed = JSON.parse(raw);
|
|
112821
113408
|
if (!parsed || !Array.isArray(parsed.files)) {
|
|
112822
113409
|
return null;
|
|
@@ -113199,12 +113786,12 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
113199
113786
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
113200
113787
|
init_create_tool();
|
|
113201
113788
|
function readPlanJson(directory) {
|
|
113202
|
-
const planPath =
|
|
113203
|
-
if (!
|
|
113789
|
+
const planPath = path124.join(directory, ".swarm", "plan.json");
|
|
113790
|
+
if (!fs86.existsSync(planPath)) {
|
|
113204
113791
|
return null;
|
|
113205
113792
|
}
|
|
113206
113793
|
try {
|
|
113207
|
-
return JSON.parse(
|
|
113794
|
+
return JSON.parse(fs86.readFileSync(planPath, "utf-8"));
|
|
113208
113795
|
} catch {
|
|
113209
113796
|
return null;
|
|
113210
113797
|
}
|
|
@@ -113254,16 +113841,16 @@ init_config();
|
|
|
113254
113841
|
|
|
113255
113842
|
// src/turbo/lean/reviewer.ts
|
|
113256
113843
|
init_state();
|
|
113257
|
-
import * as
|
|
113258
|
-
import * as
|
|
113844
|
+
import * as fs88 from "node:fs/promises";
|
|
113845
|
+
import * as path126 from "node:path";
|
|
113259
113846
|
|
|
113260
113847
|
// src/turbo/lean/evidence.ts
|
|
113261
113848
|
init_bun_compat();
|
|
113262
113849
|
import { rmSync as rmSync6 } from "node:fs";
|
|
113263
|
-
import * as
|
|
113264
|
-
import * as
|
|
113850
|
+
import * as fs87 from "node:fs/promises";
|
|
113851
|
+
import * as path125 from "node:path";
|
|
113265
113852
|
function leanTurboEvidenceDir(directory, phase) {
|
|
113266
|
-
return
|
|
113853
|
+
return path125.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
113267
113854
|
}
|
|
113268
113855
|
function validateLaneId(laneId) {
|
|
113269
113856
|
if (laneId.length === 0) {
|
|
@@ -113285,21 +113872,21 @@ function validateLaneId(laneId) {
|
|
|
113285
113872
|
function laneEvidencePath(directory, phase, laneId) {
|
|
113286
113873
|
validateLaneId(laneId);
|
|
113287
113874
|
const expectedDir = leanTurboEvidenceDir(directory, phase);
|
|
113288
|
-
const resolvedPath =
|
|
113289
|
-
const resolvedDir =
|
|
113290
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
113875
|
+
const resolvedPath = path125.resolve(path125.join(expectedDir, `${laneId}.json`));
|
|
113876
|
+
const resolvedDir = path125.resolve(expectedDir);
|
|
113877
|
+
if (!resolvedPath.startsWith(resolvedDir + path125.sep) && resolvedPath !== resolvedDir) {
|
|
113291
113878
|
throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
|
|
113292
113879
|
}
|
|
113293
113880
|
return resolvedPath;
|
|
113294
113881
|
}
|
|
113295
113882
|
async function atomicWriteJson(filePath, data) {
|
|
113296
113883
|
const content = JSON.stringify(data, null, 2);
|
|
113297
|
-
const dir =
|
|
113298
|
-
await
|
|
113884
|
+
const dir = path125.dirname(filePath);
|
|
113885
|
+
await fs87.mkdir(dir, { recursive: true });
|
|
113299
113886
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
113300
113887
|
try {
|
|
113301
113888
|
await bunWrite(tempPath, content);
|
|
113302
|
-
await
|
|
113889
|
+
await fs87.rename(tempPath, filePath);
|
|
113303
113890
|
} catch (error93) {
|
|
113304
113891
|
try {
|
|
113305
113892
|
rmSync6(tempPath, { force: true });
|
|
@@ -113308,7 +113895,7 @@ async function atomicWriteJson(filePath, data) {
|
|
|
113308
113895
|
}
|
|
113309
113896
|
}
|
|
113310
113897
|
function phaseEvidencePath(directory, phase) {
|
|
113311
|
-
return
|
|
113898
|
+
return path125.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
|
|
113312
113899
|
}
|
|
113313
113900
|
async function writeLaneEvidence(directory, phase, evidence) {
|
|
113314
113901
|
const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
|
|
@@ -113318,7 +113905,7 @@ async function readPhaseEvidence(directory, phase) {
|
|
|
113318
113905
|
const targetPath = phaseEvidencePath(directory, phase);
|
|
113319
113906
|
let content;
|
|
113320
113907
|
try {
|
|
113321
|
-
content = await
|
|
113908
|
+
content = await fs87.readFile(targetPath, "utf-8");
|
|
113322
113909
|
} catch (error93) {
|
|
113323
113910
|
const code = error93.code;
|
|
113324
113911
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -113336,7 +113923,7 @@ async function listLaneEvidence(directory, phase) {
|
|
|
113336
113923
|
const evidenceDir = leanTurboEvidenceDir(directory, phase);
|
|
113337
113924
|
let entries;
|
|
113338
113925
|
try {
|
|
113339
|
-
entries = await
|
|
113926
|
+
entries = await fs87.readdir(evidenceDir);
|
|
113340
113927
|
} catch (error93) {
|
|
113341
113928
|
const code = error93.code;
|
|
113342
113929
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -113352,10 +113939,10 @@ async function listLaneEvidence(directory, phase) {
|
|
|
113352
113939
|
if (entry === "lean-turbo-phase.json") {
|
|
113353
113940
|
continue;
|
|
113354
113941
|
}
|
|
113355
|
-
const filePath =
|
|
113942
|
+
const filePath = path125.join(evidenceDir, entry);
|
|
113356
113943
|
let content;
|
|
113357
113944
|
try {
|
|
113358
|
-
content = await
|
|
113945
|
+
content = await fs87.readFile(filePath, "utf-8");
|
|
113359
113946
|
} catch {
|
|
113360
113947
|
continue;
|
|
113361
113948
|
}
|
|
@@ -113483,9 +114070,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
113483
114070
|
return { verdict, reason };
|
|
113484
114071
|
}
|
|
113485
114072
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
113486
|
-
const evidenceDir =
|
|
113487
|
-
await
|
|
113488
|
-
const evidencePath =
|
|
114073
|
+
const evidenceDir = path126.join(directory, ".swarm", "evidence", String(phase));
|
|
114074
|
+
await fs88.mkdir(evidenceDir, { recursive: true });
|
|
114075
|
+
const evidencePath = path126.join(evidenceDir, "lean-turbo-reviewer.json");
|
|
113489
114076
|
const content = JSON.stringify({
|
|
113490
114077
|
phase,
|
|
113491
114078
|
verdict,
|
|
@@ -113494,11 +114081,11 @@ async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
|
113494
114081
|
}, null, 2);
|
|
113495
114082
|
const tempPath = `${evidencePath}.tmp.${process.pid}.${Date.now()}`;
|
|
113496
114083
|
try {
|
|
113497
|
-
await
|
|
113498
|
-
await
|
|
114084
|
+
await fs88.writeFile(tempPath, content, "utf-8");
|
|
114085
|
+
await fs88.rename(tempPath, evidencePath);
|
|
113499
114086
|
} catch (error93) {
|
|
113500
114087
|
try {
|
|
113501
|
-
await
|
|
114088
|
+
await fs88.unlink(tempPath);
|
|
113502
114089
|
} catch {}
|
|
113503
114090
|
throw error93;
|
|
113504
114091
|
}
|
|
@@ -114296,8 +114883,8 @@ init_lint();
|
|
|
114296
114883
|
// src/tools/lint-spec.ts
|
|
114297
114884
|
init_spec_schema();
|
|
114298
114885
|
init_create_tool();
|
|
114299
|
-
import * as
|
|
114300
|
-
import * as
|
|
114886
|
+
import * as fs89 from "node:fs";
|
|
114887
|
+
import * as path127 from "node:path";
|
|
114301
114888
|
var SPEC_FILE_NAME = "spec.md";
|
|
114302
114889
|
var SWARM_DIR2 = ".swarm";
|
|
114303
114890
|
var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -114350,8 +114937,8 @@ var lint_spec = createSwarmTool({
|
|
|
114350
114937
|
async execute(_args, directory) {
|
|
114351
114938
|
const errors5 = [];
|
|
114352
114939
|
const warnings = [];
|
|
114353
|
-
const specPath =
|
|
114354
|
-
if (!
|
|
114940
|
+
const specPath = path127.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
114941
|
+
if (!fs89.existsSync(specPath)) {
|
|
114355
114942
|
const result2 = {
|
|
114356
114943
|
valid: false,
|
|
114357
114944
|
specMtime: null,
|
|
@@ -114370,12 +114957,12 @@ var lint_spec = createSwarmTool({
|
|
|
114370
114957
|
}
|
|
114371
114958
|
let specMtime = null;
|
|
114372
114959
|
try {
|
|
114373
|
-
const stats =
|
|
114960
|
+
const stats = fs89.statSync(specPath);
|
|
114374
114961
|
specMtime = stats.mtime.toISOString();
|
|
114375
114962
|
} catch {}
|
|
114376
114963
|
let content;
|
|
114377
114964
|
try {
|
|
114378
|
-
content =
|
|
114965
|
+
content = fs89.readFileSync(specPath, "utf-8");
|
|
114379
114966
|
} catch (e) {
|
|
114380
114967
|
const result2 = {
|
|
114381
114968
|
valid: false,
|
|
@@ -114421,13 +115008,13 @@ var lint_spec = createSwarmTool({
|
|
|
114421
115008
|
|
|
114422
115009
|
// src/tools/mutation-test.ts
|
|
114423
115010
|
init_zod();
|
|
114424
|
-
import * as
|
|
114425
|
-
import * as
|
|
115011
|
+
import * as fs90 from "node:fs";
|
|
115012
|
+
import * as path129 from "node:path";
|
|
114426
115013
|
|
|
114427
115014
|
// src/mutation/engine.ts
|
|
114428
|
-
import { spawnSync as
|
|
115015
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
114429
115016
|
import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync24 } from "node:fs";
|
|
114430
|
-
import * as
|
|
115017
|
+
import * as path128 from "node:path";
|
|
114431
115018
|
|
|
114432
115019
|
// src/mutation/equivalence.ts
|
|
114433
115020
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -114562,7 +115149,7 @@ var _internals57 = {
|
|
|
114562
115149
|
executeMutation,
|
|
114563
115150
|
computeReport,
|
|
114564
115151
|
executeMutationSuite,
|
|
114565
|
-
spawnSync:
|
|
115152
|
+
spawnSync: spawnSync9
|
|
114566
115153
|
};
|
|
114567
115154
|
async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
114568
115155
|
const startTime = Date.now();
|
|
@@ -114573,7 +115160,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
114573
115160
|
let patchFile;
|
|
114574
115161
|
try {
|
|
114575
115162
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
114576
|
-
patchFile =
|
|
115163
|
+
patchFile = path128.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
114577
115164
|
try {
|
|
114578
115165
|
writeFileSync24(patchFile, patch.patch);
|
|
114579
115166
|
} catch (writeErr) {
|
|
@@ -114977,8 +115564,8 @@ var mutation_test = createSwarmTool({
|
|
|
114977
115564
|
];
|
|
114978
115565
|
for (const filePath of uniquePaths) {
|
|
114979
115566
|
try {
|
|
114980
|
-
const resolvedPath =
|
|
114981
|
-
sourceFiles.set(filePath,
|
|
115567
|
+
const resolvedPath = path129.resolve(cwd, filePath);
|
|
115568
|
+
sourceFiles.set(filePath, fs90.readFileSync(resolvedPath, "utf-8"));
|
|
114982
115569
|
} catch {}
|
|
114983
115570
|
}
|
|
114984
115571
|
const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
|
|
@@ -114998,30 +115585,30 @@ init_zod();
|
|
|
114998
115585
|
init_config();
|
|
114999
115586
|
init_schema();
|
|
115000
115587
|
init_manager2();
|
|
115001
|
-
import * as
|
|
115002
|
-
import * as
|
|
115588
|
+
import * as fs100 from "node:fs";
|
|
115589
|
+
import * as path139 from "node:path";
|
|
115003
115590
|
|
|
115004
115591
|
// src/full-auto/phase-approval.ts
|
|
115005
115592
|
init_utils2();
|
|
115006
115593
|
init_logger();
|
|
115007
115594
|
init_state2();
|
|
115008
|
-
import * as
|
|
115009
|
-
import * as
|
|
115595
|
+
import * as fs91 from "node:fs";
|
|
115596
|
+
import * as path130 from "node:path";
|
|
115010
115597
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
115011
115598
|
function readEvidenceDir(directory, phase) {
|
|
115012
115599
|
try {
|
|
115013
|
-
const dirPath = validateSwarmPath(directory,
|
|
115014
|
-
if (!
|
|
115600
|
+
const dirPath = validateSwarmPath(directory, path130.posix.join("evidence", String(phase)));
|
|
115601
|
+
if (!fs91.existsSync(dirPath))
|
|
115015
115602
|
return [];
|
|
115016
|
-
const entries =
|
|
115017
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
115603
|
+
const entries = fs91.readdirSync(dirPath);
|
|
115604
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path130.join(dirPath, e));
|
|
115018
115605
|
} catch {
|
|
115019
115606
|
return [];
|
|
115020
115607
|
}
|
|
115021
115608
|
}
|
|
115022
115609
|
function parseEvidence(filePath) {
|
|
115023
115610
|
try {
|
|
115024
|
-
const raw =
|
|
115611
|
+
const raw = fs91.readFileSync(filePath, "utf-8");
|
|
115025
115612
|
const parsed = JSON.parse(raw);
|
|
115026
115613
|
return parsed;
|
|
115027
115614
|
} catch (error93) {
|
|
@@ -115110,9 +115697,9 @@ function verifyFullAutoPhaseApproval(directory, sessionID, phase, config3) {
|
|
|
115110
115697
|
function phaseIsExplicitlyNonCode(directory, phase) {
|
|
115111
115698
|
try {
|
|
115112
115699
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
115113
|
-
if (!
|
|
115700
|
+
if (!fs91.existsSync(planPath))
|
|
115114
115701
|
return false;
|
|
115115
|
-
const raw =
|
|
115702
|
+
const raw = fs91.readFileSync(planPath, "utf-8");
|
|
115116
115703
|
const plan = JSON.parse(raw);
|
|
115117
115704
|
const phases = Array.isArray(plan.phases) ? plan.phases : [];
|
|
115118
115705
|
const entry = phases.find((p) => p.id === phase || p.phase === phase);
|
|
@@ -115154,20 +115741,20 @@ init_file_locks();
|
|
|
115154
115741
|
init_plan_schema();
|
|
115155
115742
|
init_ledger();
|
|
115156
115743
|
init_manager();
|
|
115157
|
-
import * as
|
|
115158
|
-
import * as
|
|
115744
|
+
import * as fs92 from "node:fs";
|
|
115745
|
+
import * as path131 from "node:path";
|
|
115159
115746
|
async function writeCheckpoint(directory) {
|
|
115160
115747
|
try {
|
|
115161
115748
|
const plan = await loadPlan(directory);
|
|
115162
115749
|
if (!plan)
|
|
115163
115750
|
return;
|
|
115164
|
-
const swarmDir =
|
|
115165
|
-
|
|
115166
|
-
const jsonPath =
|
|
115167
|
-
const mdPath =
|
|
115168
|
-
|
|
115751
|
+
const swarmDir = path131.join(directory, ".swarm");
|
|
115752
|
+
fs92.mkdirSync(swarmDir, { recursive: true });
|
|
115753
|
+
const jsonPath = path131.join(swarmDir, "SWARM_PLAN.json");
|
|
115754
|
+
const mdPath = path131.join(swarmDir, "SWARM_PLAN.md");
|
|
115755
|
+
fs92.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
115169
115756
|
const md = derivePlanMarkdown(plan);
|
|
115170
|
-
|
|
115757
|
+
fs92.writeFileSync(mdPath, md, "utf8");
|
|
115171
115758
|
} catch (error93) {
|
|
115172
115759
|
console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
115173
115760
|
}
|
|
@@ -115182,8 +115769,8 @@ init_telemetry();
|
|
|
115182
115769
|
|
|
115183
115770
|
// src/turbo/lean/phase-ready.ts
|
|
115184
115771
|
init_file_locks();
|
|
115185
|
-
import * as
|
|
115186
|
-
import * as
|
|
115772
|
+
import * as fs93 from "node:fs";
|
|
115773
|
+
import * as path132 from "node:path";
|
|
115187
115774
|
init_state3();
|
|
115188
115775
|
var DEFAULT_CONFIG3 = {
|
|
115189
115776
|
phase_reviewer: true,
|
|
@@ -115192,10 +115779,10 @@ var DEFAULT_CONFIG3 = {
|
|
|
115192
115779
|
};
|
|
115193
115780
|
function defaultReadPlanJson(dir) {
|
|
115194
115781
|
try {
|
|
115195
|
-
const planPath =
|
|
115196
|
-
if (!
|
|
115782
|
+
const planPath = path132.join(dir, ".swarm", "plan.json");
|
|
115783
|
+
if (!fs93.existsSync(planPath))
|
|
115197
115784
|
return null;
|
|
115198
|
-
const raw =
|
|
115785
|
+
const raw = fs93.readFileSync(planPath, "utf-8");
|
|
115199
115786
|
const plan = JSON.parse(raw);
|
|
115200
115787
|
if (typeof plan !== "object" || plan === null || !Array.isArray(plan.phases)) {
|
|
115201
115788
|
return null;
|
|
@@ -115207,11 +115794,11 @@ function defaultReadPlanJson(dir) {
|
|
|
115207
115794
|
}
|
|
115208
115795
|
function readReviewerEvidenceFromFile(directory, phase) {
|
|
115209
115796
|
try {
|
|
115210
|
-
const evidencePath =
|
|
115211
|
-
if (!
|
|
115797
|
+
const evidencePath = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
|
|
115798
|
+
if (!fs93.existsSync(evidencePath)) {
|
|
115212
115799
|
return null;
|
|
115213
115800
|
}
|
|
115214
|
-
const raw =
|
|
115801
|
+
const raw = fs93.readFileSync(evidencePath, "utf-8");
|
|
115215
115802
|
const parsed = JSON.parse(raw);
|
|
115216
115803
|
if (typeof parsed !== "object" || parsed === null || typeof parsed.verdict !== "string") {
|
|
115217
115804
|
return null;
|
|
@@ -115227,11 +115814,11 @@ function readReviewerEvidenceFromFile(directory, phase) {
|
|
|
115227
115814
|
}
|
|
115228
115815
|
function readCriticEvidenceFromFile(directory, phase) {
|
|
115229
115816
|
try {
|
|
115230
|
-
const evidencePath =
|
|
115231
|
-
if (!
|
|
115817
|
+
const evidencePath = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
|
|
115818
|
+
if (!fs93.existsSync(evidencePath)) {
|
|
115232
115819
|
return null;
|
|
115233
115820
|
}
|
|
115234
|
-
const raw =
|
|
115821
|
+
const raw = fs93.readFileSync(evidencePath, "utf-8");
|
|
115235
115822
|
const parsed = JSON.parse(raw);
|
|
115236
115823
|
if (typeof parsed !== "object" || parsed === null || typeof parsed.verdict !== "string") {
|
|
115237
115824
|
return null;
|
|
@@ -115246,10 +115833,10 @@ function readCriticEvidenceFromFile(directory, phase) {
|
|
|
115246
115833
|
}
|
|
115247
115834
|
}
|
|
115248
115835
|
function listLaneEvidenceSync(directory, phase) {
|
|
115249
|
-
const evidenceDir =
|
|
115836
|
+
const evidenceDir = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
115250
115837
|
let entries;
|
|
115251
115838
|
try {
|
|
115252
|
-
entries =
|
|
115839
|
+
entries = fs93.readdirSync(evidenceDir);
|
|
115253
115840
|
} catch {
|
|
115254
115841
|
return [];
|
|
115255
115842
|
}
|
|
@@ -115316,8 +115903,8 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
115316
115903
|
...DEFAULT_CONFIG3,
|
|
115317
115904
|
...actualConfig
|
|
115318
115905
|
};
|
|
115319
|
-
const statePath =
|
|
115320
|
-
if (!
|
|
115906
|
+
const statePath = path132.join(directory, ".swarm", "turbo-state.json");
|
|
115907
|
+
if (!fs93.existsSync(statePath)) {
|
|
115321
115908
|
return {
|
|
115322
115909
|
ok: false,
|
|
115323
115910
|
reason: "Lean Turbo state unreadable or missing"
|
|
@@ -115504,10 +116091,10 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
115504
116091
|
}
|
|
115505
116092
|
}
|
|
115506
116093
|
if (mergedConfig.integrated_diff_required) {
|
|
115507
|
-
const evidencePath =
|
|
116094
|
+
const evidencePath = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
|
|
115508
116095
|
let hasDiff = false;
|
|
115509
116096
|
try {
|
|
115510
|
-
const content =
|
|
116097
|
+
const content = fs93.readFileSync(evidencePath, "utf-8");
|
|
115511
116098
|
const evidence = JSON.parse(content);
|
|
115512
116099
|
hasDiff = !!evidence.integratedDiffSummary;
|
|
115513
116100
|
} catch {}
|
|
@@ -115655,15 +116242,15 @@ async function runCompletionVerifyGate(ctx) {
|
|
|
115655
116242
|
init_qa_gate_profile();
|
|
115656
116243
|
init_manager();
|
|
115657
116244
|
init_state();
|
|
115658
|
-
import * as
|
|
115659
|
-
import * as
|
|
116245
|
+
import * as fs94 from "node:fs";
|
|
116246
|
+
import * as path133 from "node:path";
|
|
115660
116247
|
async function runDriftGate(ctx) {
|
|
115661
116248
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
115662
116249
|
let driftCheckEnabled = true;
|
|
115663
116250
|
let driftHasSpecMd = false;
|
|
115664
116251
|
try {
|
|
115665
|
-
const specMdPath =
|
|
115666
|
-
driftHasSpecMd =
|
|
116252
|
+
const specMdPath = path133.join(dir, ".swarm", "spec.md");
|
|
116253
|
+
driftHasSpecMd = fs94.existsSync(specMdPath);
|
|
115667
116254
|
const gatePlan = await loadPlan(dir);
|
|
115668
116255
|
if (gatePlan) {
|
|
115669
116256
|
const gatePlanId = derivePlanId(gatePlan);
|
|
@@ -115690,9 +116277,9 @@ async function runDriftGate(ctx) {
|
|
|
115690
116277
|
}
|
|
115691
116278
|
let phaseType;
|
|
115692
116279
|
try {
|
|
115693
|
-
const planPath =
|
|
115694
|
-
if (
|
|
115695
|
-
const planRaw =
|
|
116280
|
+
const planPath = path133.join(dir, ".swarm", "plan.json");
|
|
116281
|
+
if (fs94.existsSync(planPath)) {
|
|
116282
|
+
const planRaw = fs94.readFileSync(planPath, "utf-8");
|
|
115696
116283
|
const plan = JSON.parse(planRaw);
|
|
115697
116284
|
const targetPhase = plan.phases?.find((p) => p.id === phase);
|
|
115698
116285
|
phaseType = targetPhase?.type;
|
|
@@ -115709,11 +116296,11 @@ async function runDriftGate(ctx) {
|
|
|
115709
116296
|
};
|
|
115710
116297
|
}
|
|
115711
116298
|
try {
|
|
115712
|
-
const driftEvidencePath =
|
|
116299
|
+
const driftEvidencePath = path133.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
115713
116300
|
let driftVerdictFound = false;
|
|
115714
116301
|
let driftVerdictApproved = false;
|
|
115715
116302
|
try {
|
|
115716
|
-
const driftEvidenceContent =
|
|
116303
|
+
const driftEvidenceContent = fs94.readFileSync(driftEvidencePath, "utf-8");
|
|
115717
116304
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
115718
116305
|
const entries = driftEvidence.entries ?? [];
|
|
115719
116306
|
for (const entry of entries) {
|
|
@@ -115745,9 +116332,9 @@ async function runDriftGate(ctx) {
|
|
|
115745
116332
|
let incompleteTaskCount = 0;
|
|
115746
116333
|
let planParseable = false;
|
|
115747
116334
|
try {
|
|
115748
|
-
const planPath =
|
|
115749
|
-
if (
|
|
115750
|
-
const planRaw =
|
|
116335
|
+
const planPath = path133.join(dir, ".swarm", "plan.json");
|
|
116336
|
+
if (fs94.existsSync(planPath)) {
|
|
116337
|
+
const planRaw = fs94.readFileSync(planPath, "utf-8");
|
|
115751
116338
|
const plan = JSON.parse(planRaw);
|
|
115752
116339
|
planParseable = true;
|
|
115753
116340
|
const planPhase = plan.phases?.find((p) => p.id === phase);
|
|
@@ -115826,8 +116413,8 @@ async function runDriftGate(ctx) {
|
|
|
115826
116413
|
init_qa_gate_profile();
|
|
115827
116414
|
init_manager();
|
|
115828
116415
|
init_state();
|
|
115829
|
-
import * as
|
|
115830
|
-
import * as
|
|
116416
|
+
import * as fs95 from "node:fs";
|
|
116417
|
+
import * as path134 from "node:path";
|
|
115831
116418
|
async function runFinalCouncilGate(ctx) {
|
|
115832
116419
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
115833
116420
|
let finalCouncilEnabled = false;
|
|
@@ -115844,11 +116431,11 @@ async function runFinalCouncilGate(ctx) {
|
|
|
115844
116431
|
const effective = getEffectiveGates(profile, overrides);
|
|
115845
116432
|
if (effective.final_council === true) {
|
|
115846
116433
|
finalCouncilEnabled = true;
|
|
115847
|
-
const fcPath =
|
|
116434
|
+
const fcPath = path134.join(dir, ".swarm", "evidence", "final-council.json");
|
|
115848
116435
|
let fcVerdictFound = false;
|
|
115849
116436
|
let _fcVerdict;
|
|
115850
116437
|
try {
|
|
115851
|
-
const fcContent =
|
|
116438
|
+
const fcContent = fs95.readFileSync(fcPath, "utf-8");
|
|
115852
116439
|
const fcBundle = JSON.parse(fcContent);
|
|
115853
116440
|
for (const entry of fcBundle.entries ?? []) {
|
|
115854
116441
|
if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
|
|
@@ -115973,8 +116560,8 @@ async function runFinalCouncilGate(ctx) {
|
|
|
115973
116560
|
init_qa_gate_profile();
|
|
115974
116561
|
init_manager();
|
|
115975
116562
|
init_state();
|
|
115976
|
-
import * as
|
|
115977
|
-
import * as
|
|
116563
|
+
import * as fs96 from "node:fs";
|
|
116564
|
+
import * as path135 from "node:path";
|
|
115978
116565
|
async function runHallucinationGate(ctx) {
|
|
115979
116566
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
115980
116567
|
try {
|
|
@@ -115987,11 +116574,11 @@ async function runHallucinationGate(ctx) {
|
|
|
115987
116574
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
115988
116575
|
const effective = getEffectiveGates(profile, overrides);
|
|
115989
116576
|
if (effective.hallucination_guard === true) {
|
|
115990
|
-
const hgPath =
|
|
116577
|
+
const hgPath = path135.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
115991
116578
|
let hgVerdictFound = false;
|
|
115992
116579
|
let hgVerdictApproved = false;
|
|
115993
116580
|
try {
|
|
115994
|
-
const hgContent =
|
|
116581
|
+
const hgContent = fs96.readFileSync(hgPath, "utf-8");
|
|
115995
116582
|
const hgBundle = JSON.parse(hgContent);
|
|
115996
116583
|
for (const entry of hgBundle.entries ?? []) {
|
|
115997
116584
|
if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
|
|
@@ -116049,8 +116636,8 @@ async function runHallucinationGate(ctx) {
|
|
|
116049
116636
|
init_qa_gate_profile();
|
|
116050
116637
|
init_manager();
|
|
116051
116638
|
init_state();
|
|
116052
|
-
import * as
|
|
116053
|
-
import * as
|
|
116639
|
+
import * as fs97 from "node:fs";
|
|
116640
|
+
import * as path136 from "node:path";
|
|
116054
116641
|
async function runMutationGate(ctx) {
|
|
116055
116642
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
116056
116643
|
try {
|
|
@@ -116063,11 +116650,11 @@ async function runMutationGate(ctx) {
|
|
|
116063
116650
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
116064
116651
|
const effective = getEffectiveGates(profile, overrides);
|
|
116065
116652
|
if (effective.mutation_test === true) {
|
|
116066
|
-
const mgPath =
|
|
116653
|
+
const mgPath = path136.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
116067
116654
|
let mgVerdictFound = false;
|
|
116068
116655
|
let mgVerdict;
|
|
116069
116656
|
try {
|
|
116070
|
-
const mgContent =
|
|
116657
|
+
const mgContent = fs97.readFileSync(mgPath, "utf-8");
|
|
116071
116658
|
const mgBundle = JSON.parse(mgContent);
|
|
116072
116659
|
for (const entry of mgBundle.entries ?? []) {
|
|
116073
116660
|
if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
|
|
@@ -116125,8 +116712,8 @@ async function runMutationGate(ctx) {
|
|
|
116125
116712
|
init_qa_gate_profile();
|
|
116126
116713
|
init_manager();
|
|
116127
116714
|
init_state();
|
|
116128
|
-
import * as
|
|
116129
|
-
import * as
|
|
116715
|
+
import * as fs98 from "node:fs";
|
|
116716
|
+
import * as path137 from "node:path";
|
|
116130
116717
|
async function runPhaseCouncilGate(ctx) {
|
|
116131
116718
|
const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
|
|
116132
116719
|
let councilModeEnabled = false;
|
|
@@ -116141,14 +116728,14 @@ async function runPhaseCouncilGate(ctx) {
|
|
|
116141
116728
|
const effective = getEffectiveGates(profile, overrides);
|
|
116142
116729
|
if (effective.council_mode === true) {
|
|
116143
116730
|
councilModeEnabled = true;
|
|
116144
|
-
const pcPath =
|
|
116731
|
+
const pcPath = path137.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
116145
116732
|
let pcVerdictFound = false;
|
|
116146
116733
|
let _pcVerdict;
|
|
116147
116734
|
let pcQuorumSize;
|
|
116148
116735
|
let pcTimestamp;
|
|
116149
116736
|
let pcPhaseNumber;
|
|
116150
116737
|
try {
|
|
116151
|
-
const pcContent =
|
|
116738
|
+
const pcContent = fs98.readFileSync(pcPath, "utf-8");
|
|
116152
116739
|
const pcBundle = JSON.parse(pcContent);
|
|
116153
116740
|
for (const entry of pcBundle.entries ?? []) {
|
|
116154
116741
|
if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
|
|
@@ -116656,7 +117243,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
116656
117243
|
}
|
|
116657
117244
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
116658
117245
|
try {
|
|
116659
|
-
const projectName =
|
|
117246
|
+
const projectName = path139.basename(dir);
|
|
116660
117247
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
116661
117248
|
if (curationResult) {
|
|
116662
117249
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -116756,14 +117343,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
116756
117343
|
const markerPath = validateSwarmPath(dir, "skill-usage-last-processed.json");
|
|
116757
117344
|
let sinceTimestamp;
|
|
116758
117345
|
try {
|
|
116759
|
-
const markerData = JSON.parse(
|
|
117346
|
+
const markerData = JSON.parse(fs100.readFileSync(markerPath, "utf-8"));
|
|
116760
117347
|
sinceTimestamp = markerData.lastProcessedTimestamp;
|
|
116761
117348
|
} catch {}
|
|
116762
117349
|
const feedbackResult = await applySkillUsageFeedback(dir, {
|
|
116763
117350
|
sinceTimestamp
|
|
116764
117351
|
});
|
|
116765
117352
|
try {
|
|
116766
|
-
|
|
117353
|
+
fs100.writeFileSync(markerPath, JSON.stringify({ lastProcessedTimestamp: new Date().toISOString() }), "utf-8");
|
|
116767
117354
|
} catch {}
|
|
116768
117355
|
if (feedbackResult.processed > 0) {
|
|
116769
117356
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -116783,7 +117370,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
116783
117370
|
let phaseRequiredAgents;
|
|
116784
117371
|
try {
|
|
116785
117372
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
116786
|
-
const planRaw =
|
|
117373
|
+
const planRaw = fs100.readFileSync(planPath, "utf-8");
|
|
116787
117374
|
const plan = JSON.parse(planRaw);
|
|
116788
117375
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
116789
117376
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -116798,7 +117385,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
116798
117385
|
if (agentsMissing.length > 0) {
|
|
116799
117386
|
try {
|
|
116800
117387
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
116801
|
-
const planRaw =
|
|
117388
|
+
const planRaw = fs100.readFileSync(planPath, "utf-8");
|
|
116802
117389
|
const plan = JSON.parse(planRaw);
|
|
116803
117390
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
116804
117391
|
if (targetPhase && targetPhase.tasks.length > 0 && canInferMissingAgentsFromTaskGates(agentsMissing) && await allCompletedTasksHavePassedGateEvidence(dir, targetPhase.tasks)) {
|
|
@@ -116838,7 +117425,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
116838
117425
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
116839
117426
|
try {
|
|
116840
117427
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
116841
|
-
const planRaw =
|
|
117428
|
+
const planRaw = fs100.readFileSync(planPath, "utf-8");
|
|
116842
117429
|
const plan = JSON.parse(planRaw);
|
|
116843
117430
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
116844
117431
|
if (targetPhase) {
|
|
@@ -116892,7 +117479,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
116892
117479
|
}
|
|
116893
117480
|
try {
|
|
116894
117481
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
116895
|
-
|
|
117482
|
+
fs100.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
116896
117483
|
`, "utf-8");
|
|
116897
117484
|
} catch (writeError) {
|
|
116898
117485
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -116967,12 +117554,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
116967
117554
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
116968
117555
|
try {
|
|
116969
117556
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
116970
|
-
const planRaw =
|
|
117557
|
+
const planRaw = fs100.readFileSync(planPath, "utf-8");
|
|
116971
117558
|
const plan2 = JSON.parse(planRaw);
|
|
116972
117559
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
116973
117560
|
if (phaseObj) {
|
|
116974
117561
|
phaseObj.status = "complete";
|
|
116975
|
-
|
|
117562
|
+
fs100.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
116976
117563
|
}
|
|
116977
117564
|
} catch {}
|
|
116978
117565
|
} else if (plan) {
|
|
@@ -117009,12 +117596,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
117009
117596
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
117010
117597
|
try {
|
|
117011
117598
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
117012
|
-
const planRaw =
|
|
117599
|
+
const planRaw = fs100.readFileSync(planPath, "utf-8");
|
|
117013
117600
|
const plan = JSON.parse(planRaw);
|
|
117014
117601
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
117015
117602
|
if (phaseObj) {
|
|
117016
117603
|
phaseObj.status = "complete";
|
|
117017
|
-
|
|
117604
|
+
fs100.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
117018
117605
|
}
|
|
117019
117606
|
} catch {}
|
|
117020
117607
|
}
|
|
@@ -117098,8 +117685,8 @@ init_discovery();
|
|
|
117098
117685
|
init_utils();
|
|
117099
117686
|
init_bun_compat();
|
|
117100
117687
|
init_create_tool();
|
|
117101
|
-
import * as
|
|
117102
|
-
import * as
|
|
117688
|
+
import * as fs101 from "node:fs";
|
|
117689
|
+
import * as path140 from "node:path";
|
|
117103
117690
|
var MAX_OUTPUT_BYTES6 = 52428800;
|
|
117104
117691
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
117105
117692
|
function isValidEcosystem(value) {
|
|
@@ -117127,31 +117714,31 @@ function validateArgs3(args2) {
|
|
|
117127
117714
|
function detectEcosystems(directory) {
|
|
117128
117715
|
const ecosystems = [];
|
|
117129
117716
|
const cwd = directory;
|
|
117130
|
-
if (
|
|
117717
|
+
if (fs101.existsSync(path140.join(cwd, "package.json"))) {
|
|
117131
117718
|
ecosystems.push("npm");
|
|
117132
117719
|
}
|
|
117133
|
-
if (
|
|
117720
|
+
if (fs101.existsSync(path140.join(cwd, "pyproject.toml")) || fs101.existsSync(path140.join(cwd, "requirements.txt"))) {
|
|
117134
117721
|
ecosystems.push("pip");
|
|
117135
117722
|
}
|
|
117136
|
-
if (
|
|
117723
|
+
if (fs101.existsSync(path140.join(cwd, "Cargo.toml"))) {
|
|
117137
117724
|
ecosystems.push("cargo");
|
|
117138
117725
|
}
|
|
117139
|
-
if (
|
|
117726
|
+
if (fs101.existsSync(path140.join(cwd, "go.mod"))) {
|
|
117140
117727
|
ecosystems.push("go");
|
|
117141
117728
|
}
|
|
117142
117729
|
try {
|
|
117143
|
-
const files =
|
|
117730
|
+
const files = fs101.readdirSync(cwd);
|
|
117144
117731
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
117145
117732
|
ecosystems.push("dotnet");
|
|
117146
117733
|
}
|
|
117147
117734
|
} catch {}
|
|
117148
|
-
if (
|
|
117735
|
+
if (fs101.existsSync(path140.join(cwd, "Gemfile")) || fs101.existsSync(path140.join(cwd, "Gemfile.lock"))) {
|
|
117149
117736
|
ecosystems.push("ruby");
|
|
117150
117737
|
}
|
|
117151
|
-
if (
|
|
117738
|
+
if (fs101.existsSync(path140.join(cwd, "pubspec.yaml"))) {
|
|
117152
117739
|
ecosystems.push("dart");
|
|
117153
117740
|
}
|
|
117154
|
-
if (
|
|
117741
|
+
if (fs101.existsSync(path140.join(cwd, "composer.lock"))) {
|
|
117155
117742
|
ecosystems.push("composer");
|
|
117156
117743
|
}
|
|
117157
117744
|
return ecosystems;
|
|
@@ -117164,7 +117751,7 @@ async function runNpmAudit(directory) {
|
|
|
117164
117751
|
stderr: "pipe",
|
|
117165
117752
|
cwd: directory
|
|
117166
117753
|
});
|
|
117167
|
-
const timeoutPromise = new Promise((
|
|
117754
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
117168
117755
|
const result = await Promise.race([
|
|
117169
117756
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
117170
117757
|
timeoutPromise
|
|
@@ -117284,7 +117871,7 @@ async function runPipAudit(directory) {
|
|
|
117284
117871
|
stderr: "pipe",
|
|
117285
117872
|
cwd: directory
|
|
117286
117873
|
});
|
|
117287
|
-
const timeoutPromise = new Promise((
|
|
117874
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
117288
117875
|
const result = await Promise.race([
|
|
117289
117876
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
117290
117877
|
timeoutPromise
|
|
@@ -117412,7 +117999,7 @@ async function runCargoAudit(directory) {
|
|
|
117412
117999
|
stderr: "pipe",
|
|
117413
118000
|
cwd: directory
|
|
117414
118001
|
});
|
|
117415
|
-
const timeoutPromise = new Promise((
|
|
118002
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
117416
118003
|
const result = await Promise.race([
|
|
117417
118004
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
117418
118005
|
timeoutPromise
|
|
@@ -117536,7 +118123,7 @@ async function runGoAudit(directory) {
|
|
|
117536
118123
|
stderr: "pipe",
|
|
117537
118124
|
cwd: directory
|
|
117538
118125
|
});
|
|
117539
|
-
const timeoutPromise = new Promise((
|
|
118126
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
117540
118127
|
const result = await Promise.race([
|
|
117541
118128
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
117542
118129
|
timeoutPromise
|
|
@@ -117669,7 +118256,7 @@ async function runDotnetAudit(directory) {
|
|
|
117669
118256
|
stderr: "pipe",
|
|
117670
118257
|
cwd: directory
|
|
117671
118258
|
});
|
|
117672
|
-
const timeoutPromise = new Promise((
|
|
118259
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
117673
118260
|
const result = await Promise.race([
|
|
117674
118261
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
117675
118262
|
timeoutPromise
|
|
@@ -117785,7 +118372,7 @@ async function runBundleAudit(directory) {
|
|
|
117785
118372
|
stderr: "pipe",
|
|
117786
118373
|
cwd: directory
|
|
117787
118374
|
});
|
|
117788
|
-
const timeoutPromise = new Promise((
|
|
118375
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
117789
118376
|
const result = await Promise.race([
|
|
117790
118377
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
117791
118378
|
timeoutPromise
|
|
@@ -117930,7 +118517,7 @@ async function runDartAudit(directory) {
|
|
|
117930
118517
|
stderr: "pipe",
|
|
117931
118518
|
cwd: directory
|
|
117932
118519
|
});
|
|
117933
|
-
const timeoutPromise = new Promise((
|
|
118520
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
117934
118521
|
const result = await Promise.race([
|
|
117935
118522
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
117936
118523
|
timeoutPromise
|
|
@@ -118045,7 +118632,7 @@ async function runComposerAudit(directory) {
|
|
|
118045
118632
|
stderr: "pipe",
|
|
118046
118633
|
cwd: directory
|
|
118047
118634
|
});
|
|
118048
|
-
const timeoutPromise = new Promise((
|
|
118635
|
+
const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
|
|
118049
118636
|
const result = await Promise.race([
|
|
118050
118637
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
118051
118638
|
timeoutPromise
|
|
@@ -118287,8 +118874,8 @@ var pkg_audit = createSwarmTool({
|
|
|
118287
118874
|
// src/tools/placeholder-scan.ts
|
|
118288
118875
|
init_zod();
|
|
118289
118876
|
init_manager2();
|
|
118290
|
-
import * as
|
|
118291
|
-
import * as
|
|
118877
|
+
import * as fs102 from "node:fs";
|
|
118878
|
+
import * as path141 from "node:path";
|
|
118292
118879
|
init_utils();
|
|
118293
118880
|
init_create_tool();
|
|
118294
118881
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -118411,7 +118998,7 @@ function isScaffoldFile(filePath) {
|
|
|
118411
118998
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
118412
118999
|
return true;
|
|
118413
119000
|
}
|
|
118414
|
-
const filename =
|
|
119001
|
+
const filename = path141.basename(filePath);
|
|
118415
119002
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
118416
119003
|
return true;
|
|
118417
119004
|
}
|
|
@@ -118428,7 +119015,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
118428
119015
|
if (regex.test(normalizedPath)) {
|
|
118429
119016
|
return true;
|
|
118430
119017
|
}
|
|
118431
|
-
const filename =
|
|
119018
|
+
const filename = path141.basename(filePath);
|
|
118432
119019
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
118433
119020
|
if (filenameRegex.test(filename)) {
|
|
118434
119021
|
return true;
|
|
@@ -118437,7 +119024,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
118437
119024
|
return false;
|
|
118438
119025
|
}
|
|
118439
119026
|
function isParserSupported(filePath) {
|
|
118440
|
-
const ext =
|
|
119027
|
+
const ext = path141.extname(filePath).toLowerCase();
|
|
118441
119028
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
118442
119029
|
}
|
|
118443
119030
|
function isPlanFile(filePath) {
|
|
@@ -118684,28 +119271,28 @@ async function placeholderScan(input, directory) {
|
|
|
118684
119271
|
let filesScanned = 0;
|
|
118685
119272
|
const filesWithFindings = new Set;
|
|
118686
119273
|
for (const filePath of changed_files) {
|
|
118687
|
-
const fullPath =
|
|
118688
|
-
const resolvedDirectory =
|
|
118689
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
119274
|
+
const fullPath = path141.isAbsolute(filePath) ? filePath : path141.resolve(directory, filePath);
|
|
119275
|
+
const resolvedDirectory = path141.resolve(directory);
|
|
119276
|
+
if (!fullPath.startsWith(resolvedDirectory + path141.sep) && fullPath !== resolvedDirectory) {
|
|
118690
119277
|
continue;
|
|
118691
119278
|
}
|
|
118692
|
-
if (!
|
|
119279
|
+
if (!fs102.existsSync(fullPath)) {
|
|
118693
119280
|
continue;
|
|
118694
119281
|
}
|
|
118695
119282
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
118696
119283
|
continue;
|
|
118697
119284
|
}
|
|
118698
|
-
const relativeFilePath =
|
|
119285
|
+
const relativeFilePath = path141.relative(directory, fullPath).replace(/\\/g, "/");
|
|
118699
119286
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
118700
119287
|
continue;
|
|
118701
119288
|
}
|
|
118702
119289
|
let content;
|
|
118703
119290
|
try {
|
|
118704
|
-
const stat9 =
|
|
119291
|
+
const stat9 = fs102.statSync(fullPath);
|
|
118705
119292
|
if (stat9.size > MAX_FILE_SIZE) {
|
|
118706
119293
|
continue;
|
|
118707
119294
|
}
|
|
118708
|
-
content =
|
|
119295
|
+
content = fs102.readFileSync(fullPath, "utf-8");
|
|
118709
119296
|
} catch {
|
|
118710
119297
|
continue;
|
|
118711
119298
|
}
|
|
@@ -118767,8 +119354,8 @@ var placeholder_scan = createSwarmTool({
|
|
|
118767
119354
|
});
|
|
118768
119355
|
|
|
118769
119356
|
// src/tools/pre-check-batch.ts
|
|
118770
|
-
import * as
|
|
118771
|
-
import * as
|
|
119357
|
+
import * as fs106 from "node:fs";
|
|
119358
|
+
import * as path145 from "node:path";
|
|
118772
119359
|
init_zod();
|
|
118773
119360
|
init_manager2();
|
|
118774
119361
|
init_utils();
|
|
@@ -118908,9 +119495,9 @@ var _internals61 = {
|
|
|
118908
119495
|
init_zod();
|
|
118909
119496
|
init_manager2();
|
|
118910
119497
|
init_detector();
|
|
118911
|
-
import * as
|
|
118912
|
-
import * as
|
|
118913
|
-
import { extname as
|
|
119498
|
+
import * as fs105 from "node:fs";
|
|
119499
|
+
import * as path144 from "node:path";
|
|
119500
|
+
import { extname as extname21 } from "node:path";
|
|
118914
119501
|
|
|
118915
119502
|
// src/sast/rules/c.ts
|
|
118916
119503
|
var cRules = [
|
|
@@ -119623,9 +120210,9 @@ function executeRulesSync(filePath, content, language) {
|
|
|
119623
120210
|
}
|
|
119624
120211
|
|
|
119625
120212
|
// src/sast/semgrep.ts
|
|
119626
|
-
import * as
|
|
119627
|
-
import * as
|
|
119628
|
-
import * as
|
|
120213
|
+
import * as child_process10 from "node:child_process";
|
|
120214
|
+
import * as fs103 from "node:fs";
|
|
120215
|
+
import * as path142 from "node:path";
|
|
119629
120216
|
var semgrepAvailableCache = null;
|
|
119630
120217
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
119631
120218
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
@@ -119642,7 +120229,7 @@ function isSemgrepAvailable() {
|
|
|
119642
120229
|
return semgrepAvailableCache;
|
|
119643
120230
|
}
|
|
119644
120231
|
try {
|
|
119645
|
-
|
|
120232
|
+
child_process10.execFileSync("semgrep", ["--version"], {
|
|
119646
120233
|
encoding: "utf-8",
|
|
119647
120234
|
stdio: "pipe"
|
|
119648
120235
|
});
|
|
@@ -119706,8 +120293,8 @@ function mapSemgrepSeverity(severity) {
|
|
|
119706
120293
|
}
|
|
119707
120294
|
}
|
|
119708
120295
|
async function executeWithTimeout(command, args2, options) {
|
|
119709
|
-
return new Promise((
|
|
119710
|
-
const child =
|
|
120296
|
+
return new Promise((resolve50) => {
|
|
120297
|
+
const child = child_process10.spawn(command, args2, {
|
|
119711
120298
|
shell: false,
|
|
119712
120299
|
cwd: options.cwd
|
|
119713
120300
|
});
|
|
@@ -119715,7 +120302,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
119715
120302
|
let stderr = "";
|
|
119716
120303
|
const timeout = setTimeout(() => {
|
|
119717
120304
|
child.kill("SIGTERM");
|
|
119718
|
-
|
|
120305
|
+
resolve50({
|
|
119719
120306
|
stdout,
|
|
119720
120307
|
stderr: "Process timed out",
|
|
119721
120308
|
exitCode: 124
|
|
@@ -119729,7 +120316,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
119729
120316
|
});
|
|
119730
120317
|
child.on("close", (code) => {
|
|
119731
120318
|
clearTimeout(timeout);
|
|
119732
|
-
|
|
120319
|
+
resolve50({
|
|
119733
120320
|
stdout,
|
|
119734
120321
|
stderr,
|
|
119735
120322
|
exitCode: code ?? 0
|
|
@@ -119737,7 +120324,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
119737
120324
|
});
|
|
119738
120325
|
child.on("error", (err2) => {
|
|
119739
120326
|
clearTimeout(timeout);
|
|
119740
|
-
|
|
120327
|
+
resolve50({
|
|
119741
120328
|
stdout,
|
|
119742
120329
|
stderr: err2.message,
|
|
119743
120330
|
exitCode: 1
|
|
@@ -119812,14 +120399,14 @@ async function runSemgrep(options) {
|
|
|
119812
120399
|
}
|
|
119813
120400
|
function getRulesDirectory(projectRoot) {
|
|
119814
120401
|
if (projectRoot) {
|
|
119815
|
-
return
|
|
120402
|
+
return path142.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
119816
120403
|
}
|
|
119817
120404
|
return DEFAULT_RULES_DIR;
|
|
119818
120405
|
}
|
|
119819
120406
|
function hasBundledRules(projectRoot) {
|
|
119820
120407
|
const rulesDir = getRulesDirectory(projectRoot);
|
|
119821
120408
|
try {
|
|
119822
|
-
return
|
|
120409
|
+
return fs103.existsSync(rulesDir);
|
|
119823
120410
|
} catch {
|
|
119824
120411
|
return false;
|
|
119825
120412
|
}
|
|
@@ -119832,25 +120419,25 @@ init_create_tool();
|
|
|
119832
120419
|
// src/tools/sast-baseline.ts
|
|
119833
120420
|
init_utils2();
|
|
119834
120421
|
import * as crypto11 from "node:crypto";
|
|
119835
|
-
import * as
|
|
119836
|
-
import * as
|
|
120422
|
+
import * as fs104 from "node:fs";
|
|
120423
|
+
import * as path143 from "node:path";
|
|
119837
120424
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
119838
120425
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
119839
120426
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
119840
120427
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
119841
120428
|
function normalizeFindingPath(directory, file3) {
|
|
119842
|
-
const resolved =
|
|
119843
|
-
const rel =
|
|
120429
|
+
const resolved = path143.isAbsolute(file3) ? file3 : path143.resolve(directory, file3);
|
|
120430
|
+
const rel = path143.relative(path143.resolve(directory), resolved);
|
|
119844
120431
|
return rel.replace(/\\/g, "/");
|
|
119845
120432
|
}
|
|
119846
120433
|
function baselineRelPath(phase) {
|
|
119847
|
-
return
|
|
120434
|
+
return path143.join("evidence", String(phase), "sast-baseline.json");
|
|
119848
120435
|
}
|
|
119849
120436
|
function tempRelPath(phase) {
|
|
119850
|
-
return
|
|
120437
|
+
return path143.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
119851
120438
|
}
|
|
119852
120439
|
function lockRelPath(phase) {
|
|
119853
|
-
return
|
|
120440
|
+
return path143.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
119854
120441
|
}
|
|
119855
120442
|
function getLine(lines, idx) {
|
|
119856
120443
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -119867,7 +120454,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
|
|
|
119867
120454
|
}
|
|
119868
120455
|
const lineNum = finding.location.line;
|
|
119869
120456
|
try {
|
|
119870
|
-
const content =
|
|
120457
|
+
const content = fs104.readFileSync(finding.location.file, "utf-8");
|
|
119871
120458
|
const lines = content.split(`
|
|
119872
120459
|
`);
|
|
119873
120460
|
const idx = lineNum - 1;
|
|
@@ -119898,7 +120485,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
119898
120485
|
try {
|
|
119899
120486
|
if (relFile.startsWith(".."))
|
|
119900
120487
|
throw new Error("escapes workspace");
|
|
119901
|
-
const content =
|
|
120488
|
+
const content = fs104.readFileSync(finding.location.file, "utf-8");
|
|
119902
120489
|
const lines = content.split(`
|
|
119903
120490
|
`);
|
|
119904
120491
|
const idx = lineNum - 1;
|
|
@@ -119927,16 +120514,16 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
119927
120514
|
async function acquireLock2(lockPath) {
|
|
119928
120515
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
119929
120516
|
try {
|
|
119930
|
-
const fd =
|
|
119931
|
-
|
|
120517
|
+
const fd = fs104.openSync(lockPath, "wx");
|
|
120518
|
+
fs104.closeSync(fd);
|
|
119932
120519
|
return () => {
|
|
119933
120520
|
try {
|
|
119934
|
-
|
|
120521
|
+
fs104.unlinkSync(lockPath);
|
|
119935
120522
|
} catch {}
|
|
119936
120523
|
};
|
|
119937
120524
|
} catch {
|
|
119938
120525
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
119939
|
-
await new Promise((
|
|
120526
|
+
await new Promise((resolve51) => setTimeout(resolve51, LOCK_RETRY_DELAYS_MS[attempt]));
|
|
119940
120527
|
}
|
|
119941
120528
|
}
|
|
119942
120529
|
}
|
|
@@ -119971,13 +120558,13 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
119971
120558
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
119972
120559
|
};
|
|
119973
120560
|
}
|
|
119974
|
-
|
|
119975
|
-
|
|
120561
|
+
fs104.mkdirSync(path143.dirname(baselinePath), { recursive: true });
|
|
120562
|
+
fs104.mkdirSync(path143.dirname(tempPath), { recursive: true });
|
|
119976
120563
|
const releaseLock = await acquireLock2(lockPath);
|
|
119977
120564
|
try {
|
|
119978
120565
|
let existing = null;
|
|
119979
120566
|
try {
|
|
119980
|
-
const raw =
|
|
120567
|
+
const raw = fs104.readFileSync(baselinePath, "utf-8");
|
|
119981
120568
|
const parsed = JSON.parse(raw);
|
|
119982
120569
|
if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
|
|
119983
120570
|
existing = parsed;
|
|
@@ -120037,8 +120624,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
120037
120624
|
message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
120038
120625
|
};
|
|
120039
120626
|
}
|
|
120040
|
-
|
|
120041
|
-
|
|
120627
|
+
fs104.writeFileSync(tempPath, json4, "utf-8");
|
|
120628
|
+
fs104.renameSync(tempPath, baselinePath);
|
|
120042
120629
|
return {
|
|
120043
120630
|
status: "merged",
|
|
120044
120631
|
path: baselinePath,
|
|
@@ -120069,8 +120656,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
120069
120656
|
message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
120070
120657
|
};
|
|
120071
120658
|
}
|
|
120072
|
-
|
|
120073
|
-
|
|
120659
|
+
fs104.writeFileSync(tempPath, json3, "utf-8");
|
|
120660
|
+
fs104.renameSync(tempPath, baselinePath);
|
|
120074
120661
|
return {
|
|
120075
120662
|
status: "written",
|
|
120076
120663
|
path: baselinePath,
|
|
@@ -120095,7 +120682,7 @@ function loadBaseline(directory, phase) {
|
|
|
120095
120682
|
};
|
|
120096
120683
|
}
|
|
120097
120684
|
try {
|
|
120098
|
-
const raw =
|
|
120685
|
+
const raw = fs104.readFileSync(baselinePath, "utf-8");
|
|
120099
120686
|
const parsed = JSON.parse(raw);
|
|
120100
120687
|
if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
|
|
120101
120688
|
return {
|
|
@@ -120143,17 +120730,17 @@ var SEVERITY_ORDER = {
|
|
|
120143
120730
|
};
|
|
120144
120731
|
function shouldSkipFile(filePath) {
|
|
120145
120732
|
try {
|
|
120146
|
-
const stats =
|
|
120733
|
+
const stats = fs105.statSync(filePath);
|
|
120147
120734
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
120148
120735
|
return { skip: true, reason: "file too large" };
|
|
120149
120736
|
}
|
|
120150
120737
|
if (stats.size === 0) {
|
|
120151
120738
|
return { skip: true, reason: "empty file" };
|
|
120152
120739
|
}
|
|
120153
|
-
const fd =
|
|
120740
|
+
const fd = fs105.openSync(filePath, "r");
|
|
120154
120741
|
const buffer = Buffer.alloc(8192);
|
|
120155
|
-
const bytesRead =
|
|
120156
|
-
|
|
120742
|
+
const bytesRead = fs105.readSync(fd, buffer, 0, 8192, 0);
|
|
120743
|
+
fs105.closeSync(fd);
|
|
120157
120744
|
if (bytesRead > 0) {
|
|
120158
120745
|
let nullCount = 0;
|
|
120159
120746
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -120192,7 +120779,7 @@ function countBySeverity(findings) {
|
|
|
120192
120779
|
}
|
|
120193
120780
|
function scanFileWithTierA(filePath, language) {
|
|
120194
120781
|
try {
|
|
120195
|
-
const content =
|
|
120782
|
+
const content = fs105.readFileSync(filePath, "utf-8");
|
|
120196
120783
|
const findings = executeRulesSync(filePath, content, language);
|
|
120197
120784
|
return findings.map((f) => ({
|
|
120198
120785
|
rule_id: f.rule_id,
|
|
@@ -120245,13 +120832,13 @@ async function sastScan(input, directory, config3) {
|
|
|
120245
120832
|
_filesSkipped++;
|
|
120246
120833
|
continue;
|
|
120247
120834
|
}
|
|
120248
|
-
const resolvedPath =
|
|
120249
|
-
const resolvedDirectory =
|
|
120250
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
120835
|
+
const resolvedPath = path144.isAbsolute(filePath) ? filePath : path144.resolve(directory, filePath);
|
|
120836
|
+
const resolvedDirectory = path144.resolve(directory);
|
|
120837
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path144.sep) && resolvedPath !== resolvedDirectory) {
|
|
120251
120838
|
_filesSkipped++;
|
|
120252
120839
|
continue;
|
|
120253
120840
|
}
|
|
120254
|
-
if (!
|
|
120841
|
+
if (!fs105.existsSync(resolvedPath)) {
|
|
120255
120842
|
_filesSkipped++;
|
|
120256
120843
|
continue;
|
|
120257
120844
|
}
|
|
@@ -120260,7 +120847,7 @@ async function sastScan(input, directory, config3) {
|
|
|
120260
120847
|
_filesSkipped++;
|
|
120261
120848
|
continue;
|
|
120262
120849
|
}
|
|
120263
|
-
const ext =
|
|
120850
|
+
const ext = extname21(resolvedPath).toLowerCase();
|
|
120264
120851
|
const profile = getProfileForFile(resolvedPath);
|
|
120265
120852
|
const langDef = getLanguageForExtension(ext);
|
|
120266
120853
|
if (!profile && !langDef) {
|
|
@@ -120562,20 +121149,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
120562
121149
|
let resolved;
|
|
120563
121150
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
120564
121151
|
if (isWinAbs) {
|
|
120565
|
-
resolved =
|
|
120566
|
-
} else if (
|
|
120567
|
-
resolved =
|
|
121152
|
+
resolved = path145.win32.resolve(inputPath);
|
|
121153
|
+
} else if (path145.isAbsolute(inputPath)) {
|
|
121154
|
+
resolved = path145.resolve(inputPath);
|
|
120568
121155
|
} else {
|
|
120569
|
-
resolved =
|
|
121156
|
+
resolved = path145.resolve(baseDir, inputPath);
|
|
120570
121157
|
}
|
|
120571
|
-
const workspaceResolved =
|
|
120572
|
-
let
|
|
121158
|
+
const workspaceResolved = path145.resolve(workspaceDir);
|
|
121159
|
+
let relative29;
|
|
120573
121160
|
if (isWinAbs) {
|
|
120574
|
-
|
|
121161
|
+
relative29 = path145.win32.relative(workspaceResolved, resolved);
|
|
120575
121162
|
} else {
|
|
120576
|
-
|
|
121163
|
+
relative29 = path145.relative(workspaceResolved, resolved);
|
|
120577
121164
|
}
|
|
120578
|
-
if (
|
|
121165
|
+
if (relative29.startsWith("..")) {
|
|
120579
121166
|
return "path traversal detected";
|
|
120580
121167
|
}
|
|
120581
121168
|
return null;
|
|
@@ -120638,7 +121225,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
120638
121225
|
if (typeof file3 !== "string") {
|
|
120639
121226
|
continue;
|
|
120640
121227
|
}
|
|
120641
|
-
const resolvedPath =
|
|
121228
|
+
const resolvedPath = path145.resolve(file3);
|
|
120642
121229
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
120643
121230
|
if (validationError) {
|
|
120644
121231
|
continue;
|
|
@@ -120795,7 +121382,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
120795
121382
|
skippedFiles++;
|
|
120796
121383
|
continue;
|
|
120797
121384
|
}
|
|
120798
|
-
const resolvedPath =
|
|
121385
|
+
const resolvedPath = path145.resolve(file3);
|
|
120799
121386
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
120800
121387
|
if (validationError) {
|
|
120801
121388
|
skippedFiles++;
|
|
@@ -120813,14 +121400,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
120813
121400
|
};
|
|
120814
121401
|
}
|
|
120815
121402
|
for (const file3 of validatedFiles) {
|
|
120816
|
-
const ext =
|
|
121403
|
+
const ext = path145.extname(file3).toLowerCase();
|
|
120817
121404
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
120818
121405
|
skippedFiles++;
|
|
120819
121406
|
continue;
|
|
120820
121407
|
}
|
|
120821
121408
|
let stat9;
|
|
120822
121409
|
try {
|
|
120823
|
-
stat9 =
|
|
121410
|
+
stat9 = fs106.statSync(file3);
|
|
120824
121411
|
} catch {
|
|
120825
121412
|
skippedFiles++;
|
|
120826
121413
|
continue;
|
|
@@ -120831,7 +121418,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
120831
121418
|
}
|
|
120832
121419
|
let content;
|
|
120833
121420
|
try {
|
|
120834
|
-
const buffer =
|
|
121421
|
+
const buffer = fs106.readFileSync(file3);
|
|
120835
121422
|
if (buffer.includes(0)) {
|
|
120836
121423
|
skippedFiles++;
|
|
120837
121424
|
continue;
|
|
@@ -121032,7 +121619,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
121032
121619
|
const preexistingFindings = [];
|
|
121033
121620
|
for (const finding of findings) {
|
|
121034
121621
|
const filePath = finding.location.file;
|
|
121035
|
-
const normalised =
|
|
121622
|
+
const normalised = path145.relative(directory, filePath).replace(/\\/g, "/");
|
|
121036
121623
|
const changedLines = changedLineRanges.get(normalised);
|
|
121037
121624
|
if (changedLines?.has(finding.location.line)) {
|
|
121038
121625
|
newFindings.push(finding);
|
|
@@ -121083,7 +121670,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
121083
121670
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
121084
121671
|
continue;
|
|
121085
121672
|
}
|
|
121086
|
-
changedFiles.push(
|
|
121673
|
+
changedFiles.push(path145.resolve(directory, file3));
|
|
121087
121674
|
}
|
|
121088
121675
|
if (changedFiles.length === 0) {
|
|
121089
121676
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -121284,9 +121871,9 @@ var pre_check_batch = createSwarmTool({
|
|
|
121284
121871
|
};
|
|
121285
121872
|
return JSON.stringify(errorResult, null, 2);
|
|
121286
121873
|
}
|
|
121287
|
-
const resolvedDirectory =
|
|
121288
|
-
const workspaceAnchor =
|
|
121289
|
-
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor +
|
|
121874
|
+
const resolvedDirectory = path145.resolve(typedArgs.directory);
|
|
121875
|
+
const workspaceAnchor = path145.resolve(directory);
|
|
121876
|
+
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path145.sep)) {
|
|
121290
121877
|
const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
|
|
121291
121878
|
const subDirResult = {
|
|
121292
121879
|
gates_passed: false,
|
|
@@ -121338,7 +121925,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
121338
121925
|
|
|
121339
121926
|
// src/tools/repo-map.ts
|
|
121340
121927
|
init_zod();
|
|
121341
|
-
import * as
|
|
121928
|
+
import * as path146 from "node:path";
|
|
121342
121929
|
init_path_security();
|
|
121343
121930
|
init_create_tool();
|
|
121344
121931
|
var VALID_ACTIONS = [
|
|
@@ -121363,7 +121950,7 @@ function validateFile(p) {
|
|
|
121363
121950
|
return "file contains control characters";
|
|
121364
121951
|
if (containsPathTraversal(p))
|
|
121365
121952
|
return "file contains path traversal";
|
|
121366
|
-
if (
|
|
121953
|
+
if (path146.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
121367
121954
|
return "file must be a workspace-relative path, not absolute";
|
|
121368
121955
|
}
|
|
121369
121956
|
return null;
|
|
@@ -121386,8 +121973,8 @@ function ok(action, payload) {
|
|
|
121386
121973
|
}
|
|
121387
121974
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
121388
121975
|
const normalized = input.replace(/\\/g, "/");
|
|
121389
|
-
if (
|
|
121390
|
-
const rel =
|
|
121976
|
+
if (path146.isAbsolute(normalized)) {
|
|
121977
|
+
const rel = path146.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
121391
121978
|
return normalizeGraphPath2(rel);
|
|
121392
121979
|
}
|
|
121393
121980
|
return normalizeGraphPath2(normalized);
|
|
@@ -121532,8 +122119,8 @@ var repo_map = createSwarmTool({
|
|
|
121532
122119
|
// src/tools/req-coverage.ts
|
|
121533
122120
|
init_zod();
|
|
121534
122121
|
init_create_tool();
|
|
121535
|
-
import * as
|
|
121536
|
-
import * as
|
|
122122
|
+
import * as fs107 from "node:fs";
|
|
122123
|
+
import * as path147 from "node:path";
|
|
121537
122124
|
var SPEC_FILE = ".swarm/spec.md";
|
|
121538
122125
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
121539
122126
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -121592,19 +122179,19 @@ function extractObligationAndText(id, lineText) {
|
|
|
121592
122179
|
var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
121593
122180
|
function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
121594
122181
|
const touchedFiles = new Set;
|
|
121595
|
-
if (!
|
|
122182
|
+
if (!fs107.existsSync(evidenceDir) || !fs107.statSync(evidenceDir).isDirectory()) {
|
|
121596
122183
|
return [];
|
|
121597
122184
|
}
|
|
121598
122185
|
let entries;
|
|
121599
122186
|
try {
|
|
121600
|
-
entries =
|
|
122187
|
+
entries = fs107.readdirSync(evidenceDir);
|
|
121601
122188
|
} catch {
|
|
121602
122189
|
return [];
|
|
121603
122190
|
}
|
|
121604
122191
|
for (const entry of entries) {
|
|
121605
|
-
const entryPath =
|
|
122192
|
+
const entryPath = path147.join(evidenceDir, entry);
|
|
121606
122193
|
try {
|
|
121607
|
-
const stat9 =
|
|
122194
|
+
const stat9 = fs107.statSync(entryPath);
|
|
121608
122195
|
if (!stat9.isDirectory()) {
|
|
121609
122196
|
continue;
|
|
121610
122197
|
}
|
|
@@ -121618,14 +122205,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
121618
122205
|
if (entryPhase !== String(phase)) {
|
|
121619
122206
|
continue;
|
|
121620
122207
|
}
|
|
121621
|
-
const evidenceFilePath =
|
|
122208
|
+
const evidenceFilePath = path147.join(entryPath, "evidence.json");
|
|
121622
122209
|
try {
|
|
121623
|
-
const resolvedPath =
|
|
121624
|
-
const evidenceDirResolved =
|
|
121625
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
122210
|
+
const resolvedPath = path147.resolve(evidenceFilePath);
|
|
122211
|
+
const evidenceDirResolved = path147.resolve(evidenceDir);
|
|
122212
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path147.sep)) {
|
|
121626
122213
|
continue;
|
|
121627
122214
|
}
|
|
121628
|
-
const stat9 =
|
|
122215
|
+
const stat9 = fs107.lstatSync(evidenceFilePath);
|
|
121629
122216
|
if (!stat9.isFile()) {
|
|
121630
122217
|
continue;
|
|
121631
122218
|
}
|
|
@@ -121637,7 +122224,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
121637
122224
|
}
|
|
121638
122225
|
let content;
|
|
121639
122226
|
try {
|
|
121640
|
-
content =
|
|
122227
|
+
content = fs107.readFileSync(evidenceFilePath, "utf-8");
|
|
121641
122228
|
} catch {
|
|
121642
122229
|
continue;
|
|
121643
122230
|
}
|
|
@@ -121656,7 +122243,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
121656
122243
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
121657
122244
|
for (const file3 of diffEntry.files_changed) {
|
|
121658
122245
|
if (typeof file3 === "string") {
|
|
121659
|
-
touchedFiles.add(
|
|
122246
|
+
touchedFiles.add(path147.resolve(cwd, file3));
|
|
121660
122247
|
}
|
|
121661
122248
|
}
|
|
121662
122249
|
}
|
|
@@ -121669,12 +122256,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
121669
122256
|
}
|
|
121670
122257
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
121671
122258
|
try {
|
|
121672
|
-
const resolvedPath =
|
|
121673
|
-
const cwdResolved =
|
|
122259
|
+
const resolvedPath = path147.resolve(filePath);
|
|
122260
|
+
const cwdResolved = path147.resolve(cwd);
|
|
121674
122261
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
121675
122262
|
return false;
|
|
121676
122263
|
}
|
|
121677
|
-
const content =
|
|
122264
|
+
const content = fs107.readFileSync(resolvedPath, "utf-8");
|
|
121678
122265
|
for (const keyword of keywords) {
|
|
121679
122266
|
const regex = new RegExp(`\\b${keyword}\\b`, "i");
|
|
121680
122267
|
if (regex.test(content)) {
|
|
@@ -121804,10 +122391,10 @@ var req_coverage = createSwarmTool({
|
|
|
121804
122391
|
}, null, 2);
|
|
121805
122392
|
}
|
|
121806
122393
|
const cwd = inputDirectory || directory;
|
|
121807
|
-
const specPath =
|
|
122394
|
+
const specPath = path147.join(cwd, SPEC_FILE);
|
|
121808
122395
|
let specContent;
|
|
121809
122396
|
try {
|
|
121810
|
-
specContent =
|
|
122397
|
+
specContent = fs107.readFileSync(specPath, "utf-8");
|
|
121811
122398
|
} catch (readError) {
|
|
121812
122399
|
return JSON.stringify({
|
|
121813
122400
|
success: false,
|
|
@@ -121831,7 +122418,7 @@ var req_coverage = createSwarmTool({
|
|
|
121831
122418
|
message: "No FR requirements found in spec.md"
|
|
121832
122419
|
}, null, 2);
|
|
121833
122420
|
}
|
|
121834
|
-
const evidenceDir =
|
|
122421
|
+
const evidenceDir = path147.join(cwd, EVIDENCE_DIR4);
|
|
121835
122422
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
121836
122423
|
const analyzedRequirements = [];
|
|
121837
122424
|
let coveredCount = 0;
|
|
@@ -121857,12 +122444,12 @@ var req_coverage = createSwarmTool({
|
|
|
121857
122444
|
requirements: analyzedRequirements
|
|
121858
122445
|
};
|
|
121859
122446
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
121860
|
-
const reportPath =
|
|
122447
|
+
const reportPath = path147.join(evidenceDir, reportFilename);
|
|
121861
122448
|
try {
|
|
121862
|
-
if (!
|
|
121863
|
-
|
|
122449
|
+
if (!fs107.existsSync(evidenceDir)) {
|
|
122450
|
+
fs107.mkdirSync(evidenceDir, { recursive: true });
|
|
121864
122451
|
}
|
|
121865
|
-
|
|
122452
|
+
fs107.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
|
|
121866
122453
|
} catch (writeError) {
|
|
121867
122454
|
console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
121868
122455
|
}
|
|
@@ -121946,8 +122533,8 @@ init_plan_schema();
|
|
|
121946
122533
|
init_qa_gate_profile();
|
|
121947
122534
|
init_file_locks();
|
|
121948
122535
|
import * as crypto12 from "node:crypto";
|
|
121949
|
-
import * as
|
|
121950
|
-
import * as
|
|
122536
|
+
import * as fs108 from "node:fs";
|
|
122537
|
+
import * as path148 from "node:path";
|
|
121951
122538
|
init_ledger();
|
|
121952
122539
|
init_manager();
|
|
121953
122540
|
init_state();
|
|
@@ -122028,17 +122615,17 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
122028
122615
|
};
|
|
122029
122616
|
}
|
|
122030
122617
|
if (args2.working_directory && fallbackDir) {
|
|
122031
|
-
const resolvedTarget =
|
|
122032
|
-
const resolvedRoot =
|
|
122618
|
+
const resolvedTarget = path148.resolve(args2.working_directory);
|
|
122619
|
+
const resolvedRoot = path148.resolve(fallbackDir);
|
|
122033
122620
|
let fallbackExists = false;
|
|
122034
122621
|
try {
|
|
122035
|
-
|
|
122622
|
+
fs108.accessSync(resolvedRoot, fs108.constants.F_OK);
|
|
122036
122623
|
fallbackExists = true;
|
|
122037
122624
|
} catch {
|
|
122038
122625
|
fallbackExists = false;
|
|
122039
122626
|
}
|
|
122040
122627
|
if (fallbackExists) {
|
|
122041
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
122628
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path148.sep);
|
|
122042
122629
|
if (isSubdirectory) {
|
|
122043
122630
|
return {
|
|
122044
122631
|
success: false,
|
|
@@ -122054,11 +122641,11 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
122054
122641
|
let specMtime;
|
|
122055
122642
|
let specHash;
|
|
122056
122643
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
122057
|
-
const specPath =
|
|
122644
|
+
const specPath = path148.join(targetWorkspace, ".swarm", "spec.md");
|
|
122058
122645
|
try {
|
|
122059
|
-
const stat9 = await
|
|
122646
|
+
const stat9 = await fs108.promises.stat(specPath);
|
|
122060
122647
|
specMtime = stat9.mtime.toISOString();
|
|
122061
|
-
const content = await
|
|
122648
|
+
const content = await fs108.promises.readFile(specPath, "utf8");
|
|
122062
122649
|
specHash = crypto12.createHash("sha256").update(content).digest("hex");
|
|
122063
122650
|
} catch {
|
|
122064
122651
|
return {
|
|
@@ -122070,10 +122657,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
122070
122657
|
}
|
|
122071
122658
|
}
|
|
122072
122659
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
122073
|
-
const contextPath =
|
|
122660
|
+
const contextPath = path148.join(targetWorkspace, ".swarm", "context.md");
|
|
122074
122661
|
let contextContent = "";
|
|
122075
122662
|
try {
|
|
122076
|
-
contextContent = await
|
|
122663
|
+
contextContent = await fs108.promises.readFile(contextPath, "utf8");
|
|
122077
122664
|
} catch {}
|
|
122078
122665
|
const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
|
|
122079
122666
|
if (!hasPendingSection) {
|
|
@@ -122360,14 +122947,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
122360
122947
|
}
|
|
122361
122948
|
await writeCheckpoint(dir).catch(() => {});
|
|
122362
122949
|
try {
|
|
122363
|
-
const markerPath =
|
|
122950
|
+
const markerPath = path148.join(dir, ".swarm", ".plan-write-marker");
|
|
122364
122951
|
const marker = JSON.stringify({
|
|
122365
122952
|
source: "save_plan",
|
|
122366
122953
|
timestamp: new Date().toISOString(),
|
|
122367
122954
|
phases_count: plan.phases.length,
|
|
122368
122955
|
tasks_count: tasksCount
|
|
122369
122956
|
});
|
|
122370
|
-
await
|
|
122957
|
+
await fs108.promises.writeFile(markerPath, marker, "utf8");
|
|
122371
122958
|
} catch {}
|
|
122372
122959
|
const warnings = [];
|
|
122373
122960
|
let criticReviewFound = false;
|
|
@@ -122383,7 +122970,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
122383
122970
|
return {
|
|
122384
122971
|
success: true,
|
|
122385
122972
|
message: "Plan saved successfully",
|
|
122386
|
-
plan_path:
|
|
122973
|
+
plan_path: path148.join(dir, ".swarm", "plan.json"),
|
|
122387
122974
|
phases_count: plan.phases.length,
|
|
122388
122975
|
tasks_count: tasksCount,
|
|
122389
122976
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -122449,8 +123036,8 @@ var save_plan = createSwarmTool({
|
|
|
122449
123036
|
// src/tools/sbom-generate.ts
|
|
122450
123037
|
init_zod();
|
|
122451
123038
|
init_manager2();
|
|
122452
|
-
import * as
|
|
122453
|
-
import * as
|
|
123039
|
+
import * as fs109 from "node:fs";
|
|
123040
|
+
import * as path149 from "node:path";
|
|
122454
123041
|
|
|
122455
123042
|
// src/sbom/detectors/index.ts
|
|
122456
123043
|
init_utils();
|
|
@@ -123298,9 +123885,9 @@ function findManifestFiles(rootDir) {
|
|
|
123298
123885
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
123299
123886
|
function searchDir(dir) {
|
|
123300
123887
|
try {
|
|
123301
|
-
const entries =
|
|
123888
|
+
const entries = fs109.readdirSync(dir, { withFileTypes: true });
|
|
123302
123889
|
for (const entry of entries) {
|
|
123303
|
-
const fullPath =
|
|
123890
|
+
const fullPath = path149.join(dir, entry.name);
|
|
123304
123891
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
123305
123892
|
continue;
|
|
123306
123893
|
}
|
|
@@ -123309,7 +123896,7 @@ function findManifestFiles(rootDir) {
|
|
|
123309
123896
|
} else if (entry.isFile()) {
|
|
123310
123897
|
for (const pattern of patterns) {
|
|
123311
123898
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
123312
|
-
manifestFiles.push(
|
|
123899
|
+
manifestFiles.push(path149.relative(rootDir, fullPath));
|
|
123313
123900
|
break;
|
|
123314
123901
|
}
|
|
123315
123902
|
}
|
|
@@ -123325,13 +123912,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
123325
123912
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
123326
123913
|
for (const dir of directories) {
|
|
123327
123914
|
try {
|
|
123328
|
-
const entries =
|
|
123915
|
+
const entries = fs109.readdirSync(dir, { withFileTypes: true });
|
|
123329
123916
|
for (const entry of entries) {
|
|
123330
|
-
const fullPath =
|
|
123917
|
+
const fullPath = path149.join(dir, entry.name);
|
|
123331
123918
|
if (entry.isFile()) {
|
|
123332
123919
|
for (const pattern of patterns) {
|
|
123333
123920
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
123334
|
-
found.push(
|
|
123921
|
+
found.push(path149.relative(workingDir, fullPath));
|
|
123335
123922
|
break;
|
|
123336
123923
|
}
|
|
123337
123924
|
}
|
|
@@ -123344,11 +123931,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
123344
123931
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
123345
123932
|
const dirs = new Set;
|
|
123346
123933
|
for (const file3 of changedFiles) {
|
|
123347
|
-
let currentDir =
|
|
123934
|
+
let currentDir = path149.dirname(file3);
|
|
123348
123935
|
while (true) {
|
|
123349
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
123350
|
-
dirs.add(
|
|
123351
|
-
const parent =
|
|
123936
|
+
if (currentDir && currentDir !== "." && currentDir !== path149.sep) {
|
|
123937
|
+
dirs.add(path149.join(workingDir, currentDir));
|
|
123938
|
+
const parent = path149.dirname(currentDir);
|
|
123352
123939
|
if (parent === currentDir)
|
|
123353
123940
|
break;
|
|
123354
123941
|
currentDir = parent;
|
|
@@ -123362,7 +123949,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
123362
123949
|
}
|
|
123363
123950
|
function ensureOutputDir(outputDir) {
|
|
123364
123951
|
try {
|
|
123365
|
-
|
|
123952
|
+
fs109.mkdirSync(outputDir, { recursive: true });
|
|
123366
123953
|
} catch (error93) {
|
|
123367
123954
|
if (!error93 || error93.code !== "EEXIST") {
|
|
123368
123955
|
throw error93;
|
|
@@ -123432,7 +124019,7 @@ var sbom_generate = createSwarmTool({
|
|
|
123432
124019
|
const changedFiles = obj.changed_files;
|
|
123433
124020
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
123434
124021
|
const workingDir = directory;
|
|
123435
|
-
const outputDir =
|
|
124022
|
+
const outputDir = path149.isAbsolute(relativeOutputDir) ? relativeOutputDir : path149.join(workingDir, relativeOutputDir);
|
|
123436
124023
|
let manifestFiles = [];
|
|
123437
124024
|
if (scope === "all") {
|
|
123438
124025
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -123455,11 +124042,11 @@ var sbom_generate = createSwarmTool({
|
|
|
123455
124042
|
const processedFiles = [];
|
|
123456
124043
|
for (const manifestFile of manifestFiles) {
|
|
123457
124044
|
try {
|
|
123458
|
-
const fullPath =
|
|
123459
|
-
if (!
|
|
124045
|
+
const fullPath = path149.isAbsolute(manifestFile) ? manifestFile : path149.join(workingDir, manifestFile);
|
|
124046
|
+
if (!fs109.existsSync(fullPath)) {
|
|
123460
124047
|
continue;
|
|
123461
124048
|
}
|
|
123462
|
-
const content =
|
|
124049
|
+
const content = fs109.readFileSync(fullPath, "utf-8");
|
|
123463
124050
|
const components = detectComponents(manifestFile, content);
|
|
123464
124051
|
processedFiles.push(manifestFile);
|
|
123465
124052
|
if (components.length > 0) {
|
|
@@ -123472,8 +124059,8 @@ var sbom_generate = createSwarmTool({
|
|
|
123472
124059
|
const bom = generateCycloneDX(allComponents);
|
|
123473
124060
|
const bomJson = serializeCycloneDX(bom);
|
|
123474
124061
|
const filename = generateSbomFilename();
|
|
123475
|
-
const outputPath =
|
|
123476
|
-
|
|
124062
|
+
const outputPath = path149.join(outputDir, filename);
|
|
124063
|
+
fs109.writeFileSync(outputPath, bomJson, "utf-8");
|
|
123477
124064
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
123478
124065
|
try {
|
|
123479
124066
|
const timestamp = new Date().toISOString();
|
|
@@ -123516,8 +124103,8 @@ var sbom_generate = createSwarmTool({
|
|
|
123516
124103
|
// src/tools/schema-drift.ts
|
|
123517
124104
|
init_zod();
|
|
123518
124105
|
init_create_tool();
|
|
123519
|
-
import * as
|
|
123520
|
-
import * as
|
|
124106
|
+
import * as fs110 from "node:fs";
|
|
124107
|
+
import * as path150 from "node:path";
|
|
123521
124108
|
var SPEC_CANDIDATES = [
|
|
123522
124109
|
"openapi.json",
|
|
123523
124110
|
"openapi.yaml",
|
|
@@ -123549,28 +124136,28 @@ function normalizePath5(p) {
|
|
|
123549
124136
|
}
|
|
123550
124137
|
function discoverSpecFile(cwd, specFileArg) {
|
|
123551
124138
|
if (specFileArg) {
|
|
123552
|
-
const resolvedPath =
|
|
123553
|
-
const normalizedCwd = cwd.endsWith(
|
|
124139
|
+
const resolvedPath = path150.resolve(cwd, specFileArg);
|
|
124140
|
+
const normalizedCwd = cwd.endsWith(path150.sep) ? cwd : cwd + path150.sep;
|
|
123554
124141
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
123555
124142
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
123556
124143
|
}
|
|
123557
|
-
const ext =
|
|
124144
|
+
const ext = path150.extname(resolvedPath).toLowerCase();
|
|
123558
124145
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
123559
124146
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
123560
124147
|
}
|
|
123561
|
-
const stats =
|
|
124148
|
+
const stats = fs110.statSync(resolvedPath);
|
|
123562
124149
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
123563
124150
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
123564
124151
|
}
|
|
123565
|
-
if (!
|
|
124152
|
+
if (!fs110.existsSync(resolvedPath)) {
|
|
123566
124153
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
123567
124154
|
}
|
|
123568
124155
|
return resolvedPath;
|
|
123569
124156
|
}
|
|
123570
124157
|
for (const candidate of SPEC_CANDIDATES) {
|
|
123571
|
-
const candidatePath =
|
|
123572
|
-
if (
|
|
123573
|
-
const stats =
|
|
124158
|
+
const candidatePath = path150.resolve(cwd, candidate);
|
|
124159
|
+
if (fs110.existsSync(candidatePath)) {
|
|
124160
|
+
const stats = fs110.statSync(candidatePath);
|
|
123574
124161
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
123575
124162
|
return candidatePath;
|
|
123576
124163
|
}
|
|
@@ -123579,8 +124166,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
123579
124166
|
return null;
|
|
123580
124167
|
}
|
|
123581
124168
|
function parseSpec(specFile) {
|
|
123582
|
-
const content =
|
|
123583
|
-
const ext =
|
|
124169
|
+
const content = fs110.readFileSync(specFile, "utf-8");
|
|
124170
|
+
const ext = path150.extname(specFile).toLowerCase();
|
|
123584
124171
|
if (ext === ".json") {
|
|
123585
124172
|
return parseJsonSpec(content);
|
|
123586
124173
|
}
|
|
@@ -123648,15 +124235,15 @@ function parseYamlSpec(content) {
|
|
|
123648
124235
|
}
|
|
123649
124236
|
function extractRoutes(cwd) {
|
|
123650
124237
|
const routes = [];
|
|
123651
|
-
function
|
|
124238
|
+
function walkDir2(dir) {
|
|
123652
124239
|
let entries;
|
|
123653
124240
|
try {
|
|
123654
|
-
entries =
|
|
124241
|
+
entries = fs110.readdirSync(dir, { withFileTypes: true });
|
|
123655
124242
|
} catch {
|
|
123656
124243
|
return;
|
|
123657
124244
|
}
|
|
123658
124245
|
for (const entry of entries) {
|
|
123659
|
-
const fullPath =
|
|
124246
|
+
const fullPath = path150.join(dir, entry.name);
|
|
123660
124247
|
if (entry.isSymbolicLink()) {
|
|
123661
124248
|
continue;
|
|
123662
124249
|
}
|
|
@@ -123664,9 +124251,9 @@ function extractRoutes(cwd) {
|
|
|
123664
124251
|
if (SKIP_DIRS.includes(entry.name)) {
|
|
123665
124252
|
continue;
|
|
123666
124253
|
}
|
|
123667
|
-
|
|
124254
|
+
walkDir2(fullPath);
|
|
123668
124255
|
} else if (entry.isFile()) {
|
|
123669
|
-
const ext =
|
|
124256
|
+
const ext = path150.extname(entry.name).toLowerCase();
|
|
123670
124257
|
const baseName = entry.name.toLowerCase();
|
|
123671
124258
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
123672
124259
|
continue;
|
|
@@ -123679,12 +124266,12 @@ function extractRoutes(cwd) {
|
|
|
123679
124266
|
}
|
|
123680
124267
|
}
|
|
123681
124268
|
}
|
|
123682
|
-
|
|
124269
|
+
walkDir2(cwd);
|
|
123683
124270
|
return routes;
|
|
123684
124271
|
}
|
|
123685
124272
|
function extractRoutesFromFile(filePath) {
|
|
123686
124273
|
const routes = [];
|
|
123687
|
-
const content =
|
|
124274
|
+
const content = fs110.readFileSync(filePath, "utf-8");
|
|
123688
124275
|
const lines = content.split(/\r?\n/);
|
|
123689
124276
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
123690
124277
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -123834,8 +124421,8 @@ init_zod();
|
|
|
123834
124421
|
init_bun_compat();
|
|
123835
124422
|
init_path_security();
|
|
123836
124423
|
init_create_tool();
|
|
123837
|
-
import * as
|
|
123838
|
-
import * as
|
|
124424
|
+
import * as fs111 from "node:fs";
|
|
124425
|
+
import * as path151 from "node:path";
|
|
123839
124426
|
var DEFAULT_MAX_RESULTS = 100;
|
|
123840
124427
|
var DEFAULT_MAX_LINES = 200;
|
|
123841
124428
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -123871,11 +124458,11 @@ function containsWindowsAttacks4(str) {
|
|
|
123871
124458
|
}
|
|
123872
124459
|
function isPathInWorkspace3(filePath, workspace) {
|
|
123873
124460
|
try {
|
|
123874
|
-
const resolvedPath =
|
|
123875
|
-
const realWorkspace =
|
|
123876
|
-
const realResolvedPath =
|
|
123877
|
-
const relativePath =
|
|
123878
|
-
if (relativePath.startsWith("..") ||
|
|
124461
|
+
const resolvedPath = path151.resolve(workspace, filePath);
|
|
124462
|
+
const realWorkspace = fs111.realpathSync(workspace);
|
|
124463
|
+
const realResolvedPath = fs111.realpathSync(resolvedPath);
|
|
124464
|
+
const relativePath = path151.relative(realWorkspace, realResolvedPath);
|
|
124465
|
+
if (relativePath.startsWith("..") || path151.isAbsolute(relativePath)) {
|
|
123879
124466
|
return false;
|
|
123880
124467
|
}
|
|
123881
124468
|
return true;
|
|
@@ -123888,12 +124475,12 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
123888
124475
|
}
|
|
123889
124476
|
function findRgInEnvPath() {
|
|
123890
124477
|
const searchPath = process.env.PATH ?? "";
|
|
123891
|
-
for (const dir of searchPath.split(
|
|
124478
|
+
for (const dir of searchPath.split(path151.delimiter)) {
|
|
123892
124479
|
if (!dir)
|
|
123893
124480
|
continue;
|
|
123894
124481
|
const isWindows = process.platform === "win32";
|
|
123895
|
-
const candidate =
|
|
123896
|
-
if (
|
|
124482
|
+
const candidate = path151.join(dir, isWindows ? "rg.exe" : "rg");
|
|
124483
|
+
if (fs111.existsSync(candidate))
|
|
123897
124484
|
return candidate;
|
|
123898
124485
|
}
|
|
123899
124486
|
return null;
|
|
@@ -123947,7 +124534,7 @@ async function ripgrepSearch(opts) {
|
|
|
123947
124534
|
stderr: "pipe",
|
|
123948
124535
|
cwd: opts.workspace
|
|
123949
124536
|
});
|
|
123950
|
-
const timeout = new Promise((
|
|
124537
|
+
const timeout = new Promise((resolve57) => setTimeout(() => resolve57("timeout"), REGEX_TIMEOUT_MS));
|
|
123951
124538
|
const exitPromise = proc.exited;
|
|
123952
124539
|
const result = await Promise.race([exitPromise, timeout]);
|
|
123953
124540
|
if (result === "timeout") {
|
|
@@ -124020,10 +124607,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
124020
124607
|
return files;
|
|
124021
124608
|
}
|
|
124022
124609
|
try {
|
|
124023
|
-
const entries =
|
|
124610
|
+
const entries = fs111.readdirSync(dir, { withFileTypes: true });
|
|
124024
124611
|
for (const entry of entries) {
|
|
124025
|
-
const fullPath =
|
|
124026
|
-
const relativePath =
|
|
124612
|
+
const fullPath = path151.join(dir, entry.name);
|
|
124613
|
+
const relativePath = path151.relative(workspace, fullPath);
|
|
124027
124614
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
124028
124615
|
continue;
|
|
124029
124616
|
}
|
|
@@ -124064,13 +124651,13 @@ async function fallbackSearch(opts) {
|
|
|
124064
124651
|
const matches = [];
|
|
124065
124652
|
let total = 0;
|
|
124066
124653
|
for (const file3 of files) {
|
|
124067
|
-
const fullPath =
|
|
124654
|
+
const fullPath = path151.join(opts.workspace, file3);
|
|
124068
124655
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
124069
124656
|
continue;
|
|
124070
124657
|
}
|
|
124071
124658
|
let stats;
|
|
124072
124659
|
try {
|
|
124073
|
-
stats =
|
|
124660
|
+
stats = fs111.statSync(fullPath);
|
|
124074
124661
|
if (stats.size > MAX_FILE_SIZE_BYTES10) {
|
|
124075
124662
|
continue;
|
|
124076
124663
|
}
|
|
@@ -124079,7 +124666,7 @@ async function fallbackSearch(opts) {
|
|
|
124079
124666
|
}
|
|
124080
124667
|
let content;
|
|
124081
124668
|
try {
|
|
124082
|
-
content =
|
|
124669
|
+
content = fs111.readFileSync(fullPath, "utf-8");
|
|
124083
124670
|
} catch {
|
|
124084
124671
|
continue;
|
|
124085
124672
|
}
|
|
@@ -124191,7 +124778,7 @@ var search = createSwarmTool({
|
|
|
124191
124778
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
124192
124779
|
}, null, 2);
|
|
124193
124780
|
}
|
|
124194
|
-
if (!
|
|
124781
|
+
if (!fs111.existsSync(directory)) {
|
|
124195
124782
|
return JSON.stringify({
|
|
124196
124783
|
error: true,
|
|
124197
124784
|
type: "unknown",
|
|
@@ -124477,7 +125064,7 @@ init_config();
|
|
|
124477
125064
|
init_schema();
|
|
124478
125065
|
init_create_tool();
|
|
124479
125066
|
import { mkdir as mkdir24, rename as rename10, writeFile as writeFile19 } from "node:fs/promises";
|
|
124480
|
-
import * as
|
|
125067
|
+
import * as path152 from "node:path";
|
|
124481
125068
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
124482
125069
|
var spec_write = createSwarmTool({
|
|
124483
125070
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -124518,14 +125105,14 @@ var spec_write = createSwarmTool({
|
|
|
124518
125105
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
124519
125106
|
}, null, 2);
|
|
124520
125107
|
}
|
|
124521
|
-
const target =
|
|
124522
|
-
await mkdir24(
|
|
125108
|
+
const target = path152.join(directory, ".swarm", "spec.md");
|
|
125109
|
+
await mkdir24(path152.dirname(target), { recursive: true });
|
|
124523
125110
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
124524
125111
|
let finalContent = content;
|
|
124525
125112
|
if (mode === "append") {
|
|
124526
125113
|
try {
|
|
124527
|
-
const
|
|
124528
|
-
const prior = await
|
|
125114
|
+
const fs112 = await import("node:fs/promises");
|
|
125115
|
+
const prior = await fs112.readFile(target, "utf-8");
|
|
124529
125116
|
finalContent = `${prior.replace(/\s+$/, "")}
|
|
124530
125117
|
|
|
124531
125118
|
${content}
|
|
@@ -124548,14 +125135,14 @@ ${content}
|
|
|
124548
125135
|
init_zod();
|
|
124549
125136
|
init_loader();
|
|
124550
125137
|
import {
|
|
124551
|
-
existsSync as
|
|
125138
|
+
existsSync as existsSync86,
|
|
124552
125139
|
mkdirSync as mkdirSync36,
|
|
124553
125140
|
readFileSync as readFileSync72,
|
|
124554
125141
|
renameSync as renameSync22,
|
|
124555
125142
|
unlinkSync as unlinkSync20,
|
|
124556
125143
|
writeFileSync as writeFileSync30
|
|
124557
125144
|
} from "node:fs";
|
|
124558
|
-
import
|
|
125145
|
+
import path153 from "node:path";
|
|
124559
125146
|
init_create_tool();
|
|
124560
125147
|
init_resolve_working_directory();
|
|
124561
125148
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -124685,7 +125272,7 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
124685
125272
|
}
|
|
124686
125273
|
});
|
|
124687
125274
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
124688
|
-
const mutationGatePath =
|
|
125275
|
+
const mutationGatePath = path153.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
124689
125276
|
try {
|
|
124690
125277
|
const raw = readFileSync72(mutationGatePath, "utf-8");
|
|
124691
125278
|
const parsed = JSON.parse(raw);
|
|
@@ -124747,9 +125334,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
124747
125334
|
}
|
|
124748
125335
|
}
|
|
124749
125336
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
124750
|
-
const evidenceDir =
|
|
125337
|
+
const evidenceDir = path153.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
124751
125338
|
mkdirSync36(evidenceDir, { recursive: true });
|
|
124752
|
-
const evidenceFile =
|
|
125339
|
+
const evidenceFile = path153.join(evidenceDir, "phase-council.json");
|
|
124753
125340
|
const evidenceBundle = {
|
|
124754
125341
|
entries: [
|
|
124755
125342
|
{
|
|
@@ -124785,7 +125372,7 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
|
124785
125372
|
writeFileSync30(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
124786
125373
|
renameSync22(tempFile, evidenceFile);
|
|
124787
125374
|
} finally {
|
|
124788
|
-
if (
|
|
125375
|
+
if (existsSync86(tempFile)) {
|
|
124789
125376
|
unlinkSync20(tempFile);
|
|
124790
125377
|
}
|
|
124791
125378
|
}
|
|
@@ -124810,8 +125397,30 @@ function formatMutationGapFeedback(finding) {
|
|
|
124810
125397
|
init_zod();
|
|
124811
125398
|
init_path_security();
|
|
124812
125399
|
init_create_tool();
|
|
124813
|
-
import * as
|
|
124814
|
-
import * as
|
|
125400
|
+
import * as fs112 from "node:fs";
|
|
125401
|
+
import * as path154 from "node:path";
|
|
125402
|
+
var BINARY_EXTENSIONS2 = new Set([
|
|
125403
|
+
".png",
|
|
125404
|
+
".jpg",
|
|
125405
|
+
".jpeg",
|
|
125406
|
+
".gif",
|
|
125407
|
+
".bmp",
|
|
125408
|
+
".ico",
|
|
125409
|
+
".svg",
|
|
125410
|
+
".woff",
|
|
125411
|
+
".woff2",
|
|
125412
|
+
".ttf",
|
|
125413
|
+
".eot",
|
|
125414
|
+
".mp3",
|
|
125415
|
+
".mp4",
|
|
125416
|
+
".avi",
|
|
125417
|
+
".mov",
|
|
125418
|
+
".pdf",
|
|
125419
|
+
".zip",
|
|
125420
|
+
".tar",
|
|
125421
|
+
".gz",
|
|
125422
|
+
".rar"
|
|
125423
|
+
]);
|
|
124815
125424
|
var WINDOWS_RESERVED_NAMES5 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
124816
125425
|
function containsWindowsAttacks5(str) {
|
|
124817
125426
|
if (/:[^\\/]/.test(str))
|
|
@@ -124825,14 +125434,14 @@ function containsWindowsAttacks5(str) {
|
|
|
124825
125434
|
}
|
|
124826
125435
|
function isPathInWorkspace4(filePath, workspace) {
|
|
124827
125436
|
try {
|
|
124828
|
-
const resolvedPath =
|
|
124829
|
-
if (!
|
|
125437
|
+
const resolvedPath = path154.resolve(workspace, filePath);
|
|
125438
|
+
if (!fs112.existsSync(resolvedPath)) {
|
|
124830
125439
|
return true;
|
|
124831
125440
|
}
|
|
124832
|
-
const realWorkspace =
|
|
124833
|
-
const realResolvedPath =
|
|
124834
|
-
const relativePath =
|
|
124835
|
-
if (relativePath.startsWith("..") ||
|
|
125441
|
+
const realWorkspace = fs112.realpathSync(workspace);
|
|
125442
|
+
const realResolvedPath = fs112.realpathSync(resolvedPath);
|
|
125443
|
+
const relativePath = path154.relative(realWorkspace, realResolvedPath);
|
|
125444
|
+
if (relativePath.startsWith("..") || path154.isAbsolute(relativePath)) {
|
|
124836
125445
|
return false;
|
|
124837
125446
|
}
|
|
124838
125447
|
return true;
|
|
@@ -124840,7 +125449,7 @@ function isPathInWorkspace4(filePath, workspace) {
|
|
|
124840
125449
|
return false;
|
|
124841
125450
|
}
|
|
124842
125451
|
}
|
|
124843
|
-
function
|
|
125452
|
+
function validateFilePath2(filePath, workspace) {
|
|
124844
125453
|
if (!filePath || filePath.trim() === "")
|
|
124845
125454
|
return false;
|
|
124846
125455
|
if (containsPathTraversal(filePath))
|
|
@@ -124852,8 +125461,7 @@ function validateFilePath(filePath, workspace) {
|
|
|
124852
125461
|
return isPathInWorkspace4(filePath, workspace);
|
|
124853
125462
|
}
|
|
124854
125463
|
function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
124855
|
-
const lines = content
|
|
124856
|
-
`);
|
|
125464
|
+
const lines = splitDiffLines(content);
|
|
124857
125465
|
if ((!contextBefore || contextBefore.length === 0) && (!contextAfter || contextAfter.length === 0)) {
|
|
124858
125466
|
return null;
|
|
124859
125467
|
}
|
|
@@ -124875,8 +125483,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
124875
125483
|
};
|
|
124876
125484
|
} else {
|
|
124877
125485
|
if (oldContent && oldContent.length > 0) {
|
|
124878
|
-
const oldContentLines = oldContent
|
|
124879
|
-
`);
|
|
125486
|
+
const oldContentLines = splitDiffLines(oldContent);
|
|
124880
125487
|
const betweenLines = lines.slice(afterStart, j);
|
|
124881
125488
|
if (arraysEqual2(betweenLines, oldContentLines)) {
|
|
124882
125489
|
return {
|
|
@@ -124900,8 +125507,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
|
|
|
124900
125507
|
return null;
|
|
124901
125508
|
} else {
|
|
124902
125509
|
if (oldContent && oldContent.length > 0) {
|
|
124903
|
-
const oldContentLines = oldContent
|
|
124904
|
-
`);
|
|
125510
|
+
const oldContentLines = splitDiffLines(oldContent);
|
|
124905
125511
|
for (let k = afterStart;k <= lines.length - oldContentLines.length; k++) {
|
|
124906
125512
|
const candidate = lines.slice(k, k + oldContentLines.length);
|
|
124907
125513
|
if (arraysEqual2(candidate, oldContentLines)) {
|
|
@@ -124949,23 +125555,117 @@ function arraysEqual2(a, b) {
|
|
|
124949
125555
|
}
|
|
124950
125556
|
return true;
|
|
124951
125557
|
}
|
|
124952
|
-
function
|
|
125558
|
+
function isBinaryFile4(filePath) {
|
|
125559
|
+
const ext = path154.extname(filePath).toLowerCase();
|
|
125560
|
+
return BINARY_EXTENSIONS2.has(ext);
|
|
125561
|
+
}
|
|
125562
|
+
function splitDiffLines(content) {
|
|
125563
|
+
if (content === "")
|
|
125564
|
+
return [];
|
|
125565
|
+
return content.endsWith(`
|
|
125566
|
+
`) ? content.slice(0, -1).split(`
|
|
125567
|
+
`) : content.split(`
|
|
125568
|
+
`);
|
|
125569
|
+
}
|
|
125570
|
+
function generateFileHeader(file3) {
|
|
125571
|
+
return `diff --git a/${file3} b/${file3}
|
|
125572
|
+
` + `--- a/${file3}
|
|
125573
|
+
` + `+++ b/${file3}
|
|
125574
|
+
`;
|
|
125575
|
+
}
|
|
125576
|
+
function generateHunk(content, contextMatch, oldContent, newContent) {
|
|
125577
|
+
const lines = splitDiffLines(content);
|
|
125578
|
+
const originalEndsWithNewline = content.endsWith(`
|
|
125579
|
+
`);
|
|
125580
|
+
const newContentEndsWithNewline = newContent.endsWith(`
|
|
125581
|
+
`);
|
|
125582
|
+
const removalStartIdx = contextMatch.startLineIndex + contextMatch.matchedBefore.length;
|
|
125583
|
+
const removalLines = oldContent ? splitDiffLines(oldContent) : [];
|
|
125584
|
+
const removalEndIdx = removalLines.length > 0 ? removalStartIdx + removalLines.length - 1 : removalStartIdx - 1;
|
|
125585
|
+
const additionLines = splitDiffLines(newContent);
|
|
125586
|
+
const isAdjacentCase = contextMatch.matchedAfter.length > 0 && contextMatch.endLineIndex >= 0 && contextMatch.endLineIndex < lines.length && lines[contextMatch.endLineIndex] === contextMatch.matchedAfter[contextMatch.matchedAfter.length - 1];
|
|
125587
|
+
const contextAfterStartInFile = isAdjacentCase ? contextMatch.endLineIndex - contextMatch.matchedAfter.length + 1 : contextMatch.endLineIndex + 1;
|
|
125588
|
+
const overlapSkipCount = Math.max(0, removalLines.length > 0 ? removalEndIdx + 1 - contextAfterStartInFile : 0);
|
|
125589
|
+
const effectiveContextAfterCount = Math.max(0, contextMatch.matchedAfter.length - overlapSkipCount);
|
|
125590
|
+
const oldStart = contextMatch.matchedBefore.length > 0 ? contextMatch.startLineIndex + 1 : removalStartIdx + 1;
|
|
125591
|
+
const newStart = oldStart;
|
|
125592
|
+
const oldCount = contextMatch.matchedBefore.length + removalLines.length + effectiveContextAfterCount;
|
|
125593
|
+
const newCount = contextMatch.matchedBefore.length + additionLines.length + effectiveContextAfterCount;
|
|
125594
|
+
const hunkLines = [];
|
|
125595
|
+
let lastOldSidePos = -1;
|
|
125596
|
+
let lastNewSidePos = -1;
|
|
125597
|
+
for (const line of contextMatch.matchedBefore) {
|
|
125598
|
+
const idx = hunkLines.length;
|
|
125599
|
+
hunkLines.push(` ${line}`);
|
|
125600
|
+
lastOldSidePos = idx;
|
|
125601
|
+
lastNewSidePos = idx;
|
|
125602
|
+
}
|
|
125603
|
+
for (const line of removalLines) {
|
|
125604
|
+
const idx = hunkLines.length;
|
|
125605
|
+
hunkLines.push(`-${line}`);
|
|
125606
|
+
lastOldSidePos = idx;
|
|
125607
|
+
}
|
|
125608
|
+
for (const line of additionLines) {
|
|
125609
|
+
const idx = hunkLines.length;
|
|
125610
|
+
hunkLines.push(`+${line}`);
|
|
125611
|
+
lastNewSidePos = idx;
|
|
125612
|
+
}
|
|
125613
|
+
for (let k = overlapSkipCount;k < contextMatch.matchedAfter.length; k++) {
|
|
125614
|
+
const idx = hunkLines.length;
|
|
125615
|
+
hunkLines.push(` ${contextMatch.matchedAfter[k]}`);
|
|
125616
|
+
lastOldSidePos = idx;
|
|
125617
|
+
lastNewSidePos = idx;
|
|
125618
|
+
}
|
|
125619
|
+
const lastOldSideFileIdx = effectiveContextAfterCount > 0 ? contextAfterStartInFile + contextMatch.matchedAfter.length - 1 : removalLines.length > 0 ? removalEndIdx : contextMatch.matchedBefore.length > 0 ? contextMatch.startLineIndex + contextMatch.matchedBefore.length - 1 : -1;
|
|
125620
|
+
const isAtEof = lastOldSideFileIdx === lines.length - 1;
|
|
125621
|
+
const needsOldMarker = isAtEof && !originalEndsWithNewline && lastOldSidePos >= 0;
|
|
125622
|
+
const newSideEndsWithNewline = effectiveContextAfterCount > 0 ? originalEndsWithNewline : additionLines.length > 0 ? newContentEndsWithNewline : true;
|
|
125623
|
+
const needsNewMarker = isAtEof && !newSideEndsWithNewline && lastNewSidePos >= 0;
|
|
125624
|
+
const finalLines = [];
|
|
125625
|
+
let pendingOldMarker = needsOldMarker;
|
|
125626
|
+
let pendingNewMarker = needsNewMarker;
|
|
125627
|
+
for (let i2 = 0;i2 < hunkLines.length; i2++) {
|
|
125628
|
+
finalLines.push(hunkLines[i2]);
|
|
125629
|
+
if (pendingOldMarker && i2 === lastOldSidePos) {
|
|
125630
|
+
finalLines.push("\");
|
|
125631
|
+
pendingOldMarker = false;
|
|
125632
|
+
}
|
|
125633
|
+
if (pendingNewMarker && i2 === lastNewSidePos) {
|
|
125634
|
+
finalLines.push("\");
|
|
125635
|
+
pendingNewMarker = false;
|
|
125636
|
+
}
|
|
125637
|
+
}
|
|
125638
|
+
const oldCountStr = oldCount === 0 ? "0" : String(oldCount);
|
|
125639
|
+
const newCountStr = newCount === 0 ? "0" : String(newCount);
|
|
125640
|
+
let diff2 = "";
|
|
125641
|
+
diff2 += `@@ -${oldStart},${oldCountStr} +${newStart},${newCountStr} @@
|
|
125642
|
+
`;
|
|
125643
|
+
diff2 += finalLines.join(`
|
|
125644
|
+
`);
|
|
125645
|
+
diff2 += `
|
|
125646
|
+
`;
|
|
125647
|
+
return diff2;
|
|
125648
|
+
}
|
|
125649
|
+
function validateOldContent(lines, contextMatch, oldContent) {
|
|
124953
125650
|
if (!oldContent) {
|
|
124954
125651
|
return { valid: true };
|
|
124955
125652
|
}
|
|
124956
|
-
const
|
|
124957
|
-
|
|
124958
|
-
|
|
125653
|
+
const expectedLines = splitDiffLines(oldContent);
|
|
125654
|
+
const removalStartIdx = contextMatch.startLineIndex + contextMatch.matchedBefore.length;
|
|
125655
|
+
const actualLines = lines.slice(removalStartIdx, removalStartIdx + expectedLines.length);
|
|
125656
|
+
if (!arraysEqual2(actualLines, expectedLines)) {
|
|
124959
125657
|
return {
|
|
124960
125658
|
valid: false,
|
|
124961
|
-
expected:
|
|
124962
|
-
|
|
125659
|
+
expected: expectedLines.join(`
|
|
125660
|
+
`),
|
|
125661
|
+
actual: actualLines.join(`
|
|
125662
|
+
`)
|
|
124963
125663
|
};
|
|
124964
125664
|
}
|
|
124965
125665
|
return { valid: true };
|
|
124966
125666
|
}
|
|
124967
125667
|
var suggestPatch = createSwarmTool({
|
|
124968
|
-
description: "Suggest a structured patch for specified files without modifying them. " + "Returns context-based patch proposals with anchors for reviewer use. " + "This is a read-only tool — it does not modify any files.",
|
|
125668
|
+
description: "Suggest a structured patch for specified files without modifying them. " + "Returns context-based patch proposals with anchors for reviewer use. " + 'When format="unified", also produces a unified diff string consumable by apply_patch. ' + "This is a read-only tool — it does not modify any files.",
|
|
124969
125669
|
args: {
|
|
124970
125670
|
targetFiles: exports_external.array(exports_external.string()).describe("Array of file paths to patch").min(1),
|
|
124971
125671
|
changes: exports_external.array(exports_external.object({
|
|
@@ -124974,7 +125674,8 @@ var suggestPatch = createSwarmTool({
|
|
|
124974
125674
|
contextAfter: exports_external.array(exports_external.string()).optional().describe("Lines after the change region (anchor)"),
|
|
124975
125675
|
oldContent: exports_external.string().optional().describe("Current content to be replaced"),
|
|
124976
125676
|
newContent: exports_external.string().describe("New content to replace with")
|
|
124977
|
-
})).describe("Array of change descriptions with context anchors").min(1)
|
|
125677
|
+
})).describe("Array of change descriptions with context anchors").min(1),
|
|
125678
|
+
format: exports_external.enum(["json", "unified"]).optional().default("json").describe('Output format: "json" (default, existing structured output) or "unified" (unified diff string for apply_patch)')
|
|
124978
125679
|
},
|
|
124979
125680
|
execute: async (args2, directory) => {
|
|
124980
125681
|
if (!args2 || typeof args2 !== "object") {
|
|
@@ -124988,6 +125689,7 @@ var suggestPatch = createSwarmTool({
|
|
|
124988
125689
|
const obj = args2;
|
|
124989
125690
|
const targetFiles = obj.targetFiles ?? [];
|
|
124990
125691
|
const changes = obj.changes ?? [];
|
|
125692
|
+
const format = obj.format ?? "json";
|
|
124991
125693
|
if (!targetFiles || targetFiles.length === 0) {
|
|
124992
125694
|
return JSON.stringify({
|
|
124993
125695
|
success: false,
|
|
@@ -125004,7 +125706,7 @@ var suggestPatch = createSwarmTool({
|
|
|
125004
125706
|
message: "changes cannot be empty"
|
|
125005
125707
|
}, null, 2);
|
|
125006
125708
|
}
|
|
125007
|
-
if (!
|
|
125709
|
+
if (!fs112.existsSync(directory)) {
|
|
125008
125710
|
return JSON.stringify({
|
|
125009
125711
|
success: false,
|
|
125010
125712
|
error: true,
|
|
@@ -125015,9 +125717,28 @@ var suggestPatch = createSwarmTool({
|
|
|
125015
125717
|
const patches = [];
|
|
125016
125718
|
const filesModifiedSet = new Set;
|
|
125017
125719
|
const errors5 = [];
|
|
125720
|
+
const unifiedDiffEntries = [];
|
|
125018
125721
|
const targetFileSet = new Set(targetFiles);
|
|
125722
|
+
const skippedBinaryFiles = new Set;
|
|
125723
|
+
if (format === "unified") {
|
|
125724
|
+
for (const change of changes) {
|
|
125725
|
+
if (isBinaryFile4(change.file)) {
|
|
125726
|
+
errors5.push({
|
|
125727
|
+
success: false,
|
|
125728
|
+
error: true,
|
|
125729
|
+
type: "parse-error",
|
|
125730
|
+
message: `Binary files are not supported in unified diff mode: ${change.file}`,
|
|
125731
|
+
details: { location: change.file }
|
|
125732
|
+
});
|
|
125733
|
+
skippedBinaryFiles.add(change.file);
|
|
125734
|
+
}
|
|
125735
|
+
}
|
|
125736
|
+
}
|
|
125019
125737
|
for (let changeIndex = 0;changeIndex < changes.length; changeIndex++) {
|
|
125020
125738
|
const change = changes[changeIndex];
|
|
125739
|
+
if (format === "unified" && skippedBinaryFiles.has(change.file)) {
|
|
125740
|
+
continue;
|
|
125741
|
+
}
|
|
125021
125742
|
if (!targetFileSet.has(change.file)) {
|
|
125022
125743
|
errors5.push({
|
|
125023
125744
|
success: false,
|
|
@@ -125028,7 +125749,7 @@ var suggestPatch = createSwarmTool({
|
|
|
125028
125749
|
});
|
|
125029
125750
|
continue;
|
|
125030
125751
|
}
|
|
125031
|
-
if (!
|
|
125752
|
+
if (!validateFilePath2(change.file, directory)) {
|
|
125032
125753
|
errors5.push({
|
|
125033
125754
|
success: false,
|
|
125034
125755
|
error: true,
|
|
@@ -125040,8 +125761,8 @@ var suggestPatch = createSwarmTool({
|
|
|
125040
125761
|
});
|
|
125041
125762
|
continue;
|
|
125042
125763
|
}
|
|
125043
|
-
const fullPath =
|
|
125044
|
-
if (!
|
|
125764
|
+
const fullPath = path154.resolve(directory, change.file);
|
|
125765
|
+
if (!fs112.existsSync(fullPath)) {
|
|
125045
125766
|
errors5.push({
|
|
125046
125767
|
success: false,
|
|
125047
125768
|
error: true,
|
|
@@ -125055,7 +125776,7 @@ var suggestPatch = createSwarmTool({
|
|
|
125055
125776
|
}
|
|
125056
125777
|
let content;
|
|
125057
125778
|
try {
|
|
125058
|
-
content =
|
|
125779
|
+
content = fs112.readFileSync(fullPath, "utf-8");
|
|
125059
125780
|
} catch (err3) {
|
|
125060
125781
|
errors5.push({
|
|
125061
125782
|
success: false,
|
|
@@ -125081,9 +125802,8 @@ var suggestPatch = createSwarmTool({
|
|
|
125081
125802
|
});
|
|
125082
125803
|
continue;
|
|
125083
125804
|
}
|
|
125084
|
-
const lines = content
|
|
125085
|
-
|
|
125086
|
-
const oldContentValidation = validateOldContent(lines, contextMatch.startLineIndex + contextMatch.matchedBefore.length, contextMatch.endLineIndex - contextMatch.matchedAfter.length + 1, change.oldContent);
|
|
125805
|
+
const lines = splitDiffLines(content);
|
|
125806
|
+
const oldContentValidation = validateOldContent(lines, contextMatch, change.oldContent);
|
|
125087
125807
|
if (!oldContentValidation.valid) {
|
|
125088
125808
|
errors5.push({
|
|
125089
125809
|
success: false,
|
|
@@ -125110,14 +125830,51 @@ var suggestPatch = createSwarmTool({
|
|
|
125110
125830
|
hunkIndex: changeIndex
|
|
125111
125831
|
});
|
|
125112
125832
|
filesModifiedSet.add(change.file);
|
|
125833
|
+
if (format === "unified") {
|
|
125834
|
+
unifiedDiffEntries.push({
|
|
125835
|
+
file: change.file,
|
|
125836
|
+
contextMatch,
|
|
125837
|
+
oldContent: change.oldContent,
|
|
125838
|
+
newContent: change.newContent
|
|
125839
|
+
});
|
|
125840
|
+
}
|
|
125113
125841
|
}
|
|
125114
125842
|
if (patches.length > 0) {
|
|
125115
|
-
|
|
125843
|
+
const baseResult = {
|
|
125116
125844
|
success: true,
|
|
125117
125845
|
patches,
|
|
125118
125846
|
filesModified: Array.from(filesModifiedSet),
|
|
125119
125847
|
...errors5.length > 0 && { errors: errors5 }
|
|
125120
|
-
}
|
|
125848
|
+
};
|
|
125849
|
+
if (format === "unified") {
|
|
125850
|
+
const fileGroups = new Map;
|
|
125851
|
+
for (const entry of unifiedDiffEntries) {
|
|
125852
|
+
const group = fileGroups.get(entry.file) ?? [];
|
|
125853
|
+
group.push(entry);
|
|
125854
|
+
fileGroups.set(entry.file, group);
|
|
125855
|
+
}
|
|
125856
|
+
const unifiedParts = [];
|
|
125857
|
+
for (const [file3, entries] of fileGroups) {
|
|
125858
|
+
entries.sort((a, b) => a.contextMatch.startLineIndex - b.contextMatch.startLineIndex);
|
|
125859
|
+
const entryFullPath = path154.resolve(directory, file3);
|
|
125860
|
+
let entryContent;
|
|
125861
|
+
try {
|
|
125862
|
+
entryContent = fs112.readFileSync(entryFullPath, "utf-8");
|
|
125863
|
+
} catch {
|
|
125864
|
+
continue;
|
|
125865
|
+
}
|
|
125866
|
+
unifiedParts.push(generateFileHeader(file3));
|
|
125867
|
+
for (const entry of entries) {
|
|
125868
|
+
unifiedParts.push(generateHunk(entryContent, entry.contextMatch, entry.oldContent, entry.newContent));
|
|
125869
|
+
}
|
|
125870
|
+
}
|
|
125871
|
+
const unifiedPatch = unifiedParts.join("");
|
|
125872
|
+
return JSON.stringify({
|
|
125873
|
+
...baseResult,
|
|
125874
|
+
unifiedPatch
|
|
125875
|
+
}, null, 2);
|
|
125876
|
+
}
|
|
125877
|
+
return JSON.stringify(baseResult, null, 2);
|
|
125121
125878
|
}
|
|
125122
125879
|
if (errors5.length === 1) {
|
|
125123
125880
|
return JSON.stringify(errors5[0], null, 2);
|
|
@@ -125443,8 +126200,8 @@ function getContextAgent3(ctx) {
|
|
|
125443
126200
|
init_zod();
|
|
125444
126201
|
init_manager2();
|
|
125445
126202
|
init_detector();
|
|
125446
|
-
import * as
|
|
125447
|
-
import * as
|
|
126203
|
+
import * as fs113 from "node:fs";
|
|
126204
|
+
import * as path155 from "node:path";
|
|
125448
126205
|
init_create_tool();
|
|
125449
126206
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
125450
126207
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -125510,7 +126267,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
125510
126267
|
if (languages?.length) {
|
|
125511
126268
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
125512
126269
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
125513
|
-
const ext =
|
|
126270
|
+
const ext = path155.extname(file3.path).toLowerCase();
|
|
125514
126271
|
const langDef = getLanguageForExtension(ext);
|
|
125515
126272
|
const fileProfile = getProfileForFile(file3.path);
|
|
125516
126273
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -125523,7 +126280,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
125523
126280
|
let skippedCount = 0;
|
|
125524
126281
|
for (const fileInfo of filesToCheck) {
|
|
125525
126282
|
const { path: filePath } = fileInfo;
|
|
125526
|
-
const fullPath =
|
|
126283
|
+
const fullPath = path155.isAbsolute(filePath) ? filePath : path155.join(directory, filePath);
|
|
125527
126284
|
const result = {
|
|
125528
126285
|
path: filePath,
|
|
125529
126286
|
language: "",
|
|
@@ -125553,7 +126310,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
125553
126310
|
}
|
|
125554
126311
|
let content;
|
|
125555
126312
|
try {
|
|
125556
|
-
content =
|
|
126313
|
+
content = fs113.readFileSync(fullPath, "utf8");
|
|
125557
126314
|
} catch {
|
|
125558
126315
|
result.skipped_reason = "file_read_error";
|
|
125559
126316
|
skippedCount++;
|
|
@@ -125572,7 +126329,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
125572
126329
|
results.push(result);
|
|
125573
126330
|
continue;
|
|
125574
126331
|
}
|
|
125575
|
-
const ext =
|
|
126332
|
+
const ext = path155.extname(filePath).toLowerCase();
|
|
125576
126333
|
const langDef = getLanguageForExtension(ext);
|
|
125577
126334
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
125578
126335
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -125670,8 +126427,8 @@ init_zod();
|
|
|
125670
126427
|
init_utils();
|
|
125671
126428
|
init_create_tool();
|
|
125672
126429
|
init_path_security();
|
|
125673
|
-
import * as
|
|
125674
|
-
import * as
|
|
126430
|
+
import * as fs114 from "node:fs";
|
|
126431
|
+
import * as path156 from "node:path";
|
|
125675
126432
|
var MAX_TEXT_LENGTH = 200;
|
|
125676
126433
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
125677
126434
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -125694,7 +126451,7 @@ var SUPPORTED_EXTENSIONS4 = new Set([
|
|
|
125694
126451
|
".swift",
|
|
125695
126452
|
".kt"
|
|
125696
126453
|
]);
|
|
125697
|
-
var
|
|
126454
|
+
var SKIP_DIRECTORIES6 = new Set([
|
|
125698
126455
|
"node_modules",
|
|
125699
126456
|
"dist",
|
|
125700
126457
|
"build",
|
|
@@ -125737,9 +126494,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
125737
126494
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
125738
126495
|
}
|
|
125739
126496
|
try {
|
|
125740
|
-
const resolvedPath =
|
|
125741
|
-
const normalizedCwd =
|
|
125742
|
-
const normalizedResolved =
|
|
126497
|
+
const resolvedPath = path156.resolve(paths);
|
|
126498
|
+
const normalizedCwd = path156.resolve(cwd);
|
|
126499
|
+
const normalizedResolved = path156.resolve(resolvedPath);
|
|
125743
126500
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
125744
126501
|
return {
|
|
125745
126502
|
error: "paths must be within the current working directory",
|
|
@@ -125755,30 +126512,30 @@ function validatePathsInput(paths, cwd) {
|
|
|
125755
126512
|
}
|
|
125756
126513
|
}
|
|
125757
126514
|
function isSupportedExtension(filePath) {
|
|
125758
|
-
const ext =
|
|
126515
|
+
const ext = path156.extname(filePath).toLowerCase();
|
|
125759
126516
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
125760
126517
|
}
|
|
125761
|
-
function
|
|
126518
|
+
function findSourceFiles4(dir, files = []) {
|
|
125762
126519
|
let entries;
|
|
125763
126520
|
try {
|
|
125764
|
-
entries =
|
|
126521
|
+
entries = fs114.readdirSync(dir);
|
|
125765
126522
|
} catch {
|
|
125766
126523
|
return files;
|
|
125767
126524
|
}
|
|
125768
126525
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
125769
126526
|
for (const entry of entries) {
|
|
125770
|
-
if (
|
|
126527
|
+
if (SKIP_DIRECTORIES6.has(entry)) {
|
|
125771
126528
|
continue;
|
|
125772
126529
|
}
|
|
125773
|
-
const fullPath =
|
|
126530
|
+
const fullPath = path156.join(dir, entry);
|
|
125774
126531
|
let stat9;
|
|
125775
126532
|
try {
|
|
125776
|
-
stat9 =
|
|
126533
|
+
stat9 = fs114.statSync(fullPath);
|
|
125777
126534
|
} catch {
|
|
125778
126535
|
continue;
|
|
125779
126536
|
}
|
|
125780
126537
|
if (stat9.isDirectory()) {
|
|
125781
|
-
|
|
126538
|
+
findSourceFiles4(fullPath, files);
|
|
125782
126539
|
} else if (stat9.isFile()) {
|
|
125783
126540
|
if (isSupportedExtension(fullPath)) {
|
|
125784
126541
|
files.push(fullPath);
|
|
@@ -125866,7 +126623,7 @@ var todo_extract = createSwarmTool({
|
|
|
125866
126623
|
return JSON.stringify(errorResult, null, 2);
|
|
125867
126624
|
}
|
|
125868
126625
|
const scanPath = resolvedPath;
|
|
125869
|
-
if (!
|
|
126626
|
+
if (!fs114.existsSync(scanPath)) {
|
|
125870
126627
|
const errorResult = {
|
|
125871
126628
|
error: `path not found: ${pathsInput}`,
|
|
125872
126629
|
total: 0,
|
|
@@ -125876,13 +126633,13 @@ var todo_extract = createSwarmTool({
|
|
|
125876
126633
|
return JSON.stringify(errorResult, null, 2);
|
|
125877
126634
|
}
|
|
125878
126635
|
const filesToScan = [];
|
|
125879
|
-
const stat9 =
|
|
126636
|
+
const stat9 = fs114.statSync(scanPath);
|
|
125880
126637
|
if (stat9.isFile()) {
|
|
125881
126638
|
if (isSupportedExtension(scanPath)) {
|
|
125882
126639
|
filesToScan.push(scanPath);
|
|
125883
126640
|
} else {
|
|
125884
126641
|
const errorResult = {
|
|
125885
|
-
error: `unsupported file extension: ${
|
|
126642
|
+
error: `unsupported file extension: ${path156.extname(scanPath)}`,
|
|
125886
126643
|
total: 0,
|
|
125887
126644
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
125888
126645
|
entries: []
|
|
@@ -125890,16 +126647,16 @@ var todo_extract = createSwarmTool({
|
|
|
125890
126647
|
return JSON.stringify(errorResult, null, 2);
|
|
125891
126648
|
}
|
|
125892
126649
|
} else {
|
|
125893
|
-
|
|
126650
|
+
findSourceFiles4(scanPath, filesToScan);
|
|
125894
126651
|
}
|
|
125895
126652
|
const allEntries = [];
|
|
125896
126653
|
for (const filePath of filesToScan) {
|
|
125897
126654
|
try {
|
|
125898
|
-
const fileStat =
|
|
126655
|
+
const fileStat = fs114.statSync(filePath);
|
|
125899
126656
|
if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
|
|
125900
126657
|
continue;
|
|
125901
126658
|
}
|
|
125902
|
-
const content =
|
|
126659
|
+
const content = fs114.readFileSync(filePath, "utf-8");
|
|
125903
126660
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
125904
126661
|
allEntries.push(...entries);
|
|
125905
126662
|
} catch {}
|
|
@@ -125931,18 +126688,18 @@ init_loader();
|
|
|
125931
126688
|
init_schema();
|
|
125932
126689
|
init_qa_gate_profile();
|
|
125933
126690
|
init_gate_evidence();
|
|
125934
|
-
import * as
|
|
125935
|
-
import * as
|
|
126691
|
+
import * as fs118 from "node:fs";
|
|
126692
|
+
import * as path160 from "node:path";
|
|
125936
126693
|
|
|
125937
126694
|
// src/hooks/diff-scope.ts
|
|
125938
126695
|
init_bun_compat();
|
|
125939
|
-
import * as
|
|
125940
|
-
import * as
|
|
126696
|
+
import * as fs116 from "node:fs";
|
|
126697
|
+
import * as path158 from "node:path";
|
|
125941
126698
|
|
|
125942
126699
|
// src/utils/gitignore-warning.ts
|
|
125943
126700
|
init_bun_compat();
|
|
125944
|
-
import * as
|
|
125945
|
-
import * as
|
|
126701
|
+
import * as fs115 from "node:fs";
|
|
126702
|
+
import * as path157 from "node:path";
|
|
125946
126703
|
var _internals67 = { bunSpawn };
|
|
125947
126704
|
var _swarmGitExcludedChecked = false;
|
|
125948
126705
|
function fileCoversSwarm(content) {
|
|
@@ -126016,16 +126773,16 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
126016
126773
|
const excludeRelPath = excludePathRaw.trim();
|
|
126017
126774
|
if (!excludeRelPath)
|
|
126018
126775
|
return;
|
|
126019
|
-
const excludePath =
|
|
126776
|
+
const excludePath = path157.isAbsolute(excludeRelPath) ? excludeRelPath : path157.join(directory, excludeRelPath);
|
|
126020
126777
|
if (checkIgnoreExitCode !== 0) {
|
|
126021
126778
|
try {
|
|
126022
|
-
|
|
126779
|
+
fs115.mkdirSync(path157.dirname(excludePath), { recursive: true });
|
|
126023
126780
|
let existing = "";
|
|
126024
126781
|
try {
|
|
126025
|
-
existing =
|
|
126782
|
+
existing = fs115.readFileSync(excludePath, "utf8");
|
|
126026
126783
|
} catch {}
|
|
126027
126784
|
if (!fileCoversSwarm(existing)) {
|
|
126028
|
-
|
|
126785
|
+
fs115.appendFileSync(excludePath, `
|
|
126029
126786
|
# opencode-swarm local runtime state
|
|
126030
126787
|
.swarm/
|
|
126031
126788
|
`, "utf8");
|
|
@@ -126063,10 +126820,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
126063
126820
|
var _internals68 = { bunSpawn };
|
|
126064
126821
|
function getDeclaredScope(taskId, directory) {
|
|
126065
126822
|
try {
|
|
126066
|
-
const planPath =
|
|
126067
|
-
if (!
|
|
126823
|
+
const planPath = path158.join(directory, ".swarm", "plan.json");
|
|
126824
|
+
if (!fs116.existsSync(planPath))
|
|
126068
126825
|
return null;
|
|
126069
|
-
const raw =
|
|
126826
|
+
const raw = fs116.readFileSync(planPath, "utf-8");
|
|
126070
126827
|
const plan = JSON.parse(raw);
|
|
126071
126828
|
for (const phase of plan.phases ?? []) {
|
|
126072
126829
|
for (const task of phase.tasks ?? []) {
|
|
@@ -126168,8 +126925,8 @@ init_telemetry();
|
|
|
126168
126925
|
|
|
126169
126926
|
// src/turbo/lean/task-completion.ts
|
|
126170
126927
|
init_file_locks();
|
|
126171
|
-
import * as
|
|
126172
|
-
import * as
|
|
126928
|
+
import * as fs117 from "node:fs";
|
|
126929
|
+
import * as path159 from "node:path";
|
|
126173
126930
|
var _internals69 = {
|
|
126174
126931
|
listActiveLocks,
|
|
126175
126932
|
verifyLeanTurboTaskCompletion
|
|
@@ -126188,7 +126945,7 @@ var TIER_3_PATTERNS = [
|
|
|
126188
126945
|
];
|
|
126189
126946
|
function matchesTier3Pattern(files) {
|
|
126190
126947
|
for (const file3 of files) {
|
|
126191
|
-
const fileName =
|
|
126948
|
+
const fileName = path159.basename(file3);
|
|
126192
126949
|
for (const pattern of TIER_3_PATTERNS) {
|
|
126193
126950
|
if (pattern.test(fileName)) {
|
|
126194
126951
|
return true;
|
|
@@ -126200,14 +126957,14 @@ function matchesTier3Pattern(files) {
|
|
|
126200
126957
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
126201
126958
|
let persisted = null;
|
|
126202
126959
|
try {
|
|
126203
|
-
const statePath =
|
|
126204
|
-
if (!
|
|
126960
|
+
const statePath = path159.join(directory, ".swarm", "turbo-state.json");
|
|
126961
|
+
if (!fs117.existsSync(statePath)) {
|
|
126205
126962
|
return {
|
|
126206
126963
|
ok: false,
|
|
126207
126964
|
reason: "Lean Turbo state file not found"
|
|
126208
126965
|
};
|
|
126209
126966
|
}
|
|
126210
|
-
const raw =
|
|
126967
|
+
const raw = fs117.readFileSync(statePath, "utf-8");
|
|
126211
126968
|
persisted = JSON.parse(raw);
|
|
126212
126969
|
} catch {
|
|
126213
126970
|
return {
|
|
@@ -126284,11 +127041,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
126284
127041
|
};
|
|
126285
127042
|
}
|
|
126286
127043
|
const phase = runState.phase ?? 0;
|
|
126287
|
-
const evidencePath =
|
|
126288
|
-
const expectedDir =
|
|
126289
|
-
const resolvedPath =
|
|
126290
|
-
const resolvedDir =
|
|
126291
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
127044
|
+
const evidencePath = path159.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
127045
|
+
const expectedDir = path159.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
127046
|
+
const resolvedPath = path159.resolve(evidencePath);
|
|
127047
|
+
const resolvedDir = path159.resolve(expectedDir);
|
|
127048
|
+
if (!resolvedPath.startsWith(resolvedDir + path159.sep) && resolvedPath !== resolvedDir) {
|
|
126292
127049
|
return {
|
|
126293
127050
|
ok: false,
|
|
126294
127051
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -126300,7 +127057,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
126300
127057
|
}
|
|
126301
127058
|
};
|
|
126302
127059
|
}
|
|
126303
|
-
if (!
|
|
127060
|
+
if (!fs117.existsSync(evidencePath)) {
|
|
126304
127061
|
return {
|
|
126305
127062
|
ok: false,
|
|
126306
127063
|
reason: `Lane ${lane.laneId} evidence file not found: ${evidencePath}`,
|
|
@@ -126328,8 +127085,8 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
126328
127085
|
}
|
|
126329
127086
|
let filesTouched = [];
|
|
126330
127087
|
try {
|
|
126331
|
-
const planPath =
|
|
126332
|
-
const planRaw =
|
|
127088
|
+
const planPath = path159.join(directory, ".swarm", "plan.json");
|
|
127089
|
+
const planRaw = fs117.readFileSync(planPath, "utf-8");
|
|
126333
127090
|
const plan = JSON.parse(planRaw);
|
|
126334
127091
|
for (const planPhase of plan.phases ?? []) {
|
|
126335
127092
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -126412,7 +127169,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
126412
127169
|
];
|
|
126413
127170
|
function matchesTier3Pattern2(files) {
|
|
126414
127171
|
for (const file3 of files) {
|
|
126415
|
-
const fileName =
|
|
127172
|
+
const fileName = path160.basename(file3);
|
|
126416
127173
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
126417
127174
|
if (pattern.test(fileName)) {
|
|
126418
127175
|
return true;
|
|
@@ -126451,8 +127208,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
126451
127208
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
126452
127209
|
const resolvedDir2 = workingDirectory;
|
|
126453
127210
|
try {
|
|
126454
|
-
const planPath =
|
|
126455
|
-
const planRaw =
|
|
127211
|
+
const planPath = path160.join(resolvedDir2, ".swarm", "plan.json");
|
|
127212
|
+
const planRaw = fs118.readFileSync(planPath, "utf-8");
|
|
126456
127213
|
const plan = JSON.parse(planRaw);
|
|
126457
127214
|
for (const planPhase of plan.phases ?? []) {
|
|
126458
127215
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -126529,8 +127286,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
126529
127286
|
}
|
|
126530
127287
|
if (resolvedDir) {
|
|
126531
127288
|
try {
|
|
126532
|
-
const planPath =
|
|
126533
|
-
const planRaw =
|
|
127289
|
+
const planPath = path160.join(resolvedDir, ".swarm", "plan.json");
|
|
127290
|
+
const planRaw = fs118.readFileSync(planPath, "utf-8");
|
|
126534
127291
|
const plan = JSON.parse(planRaw);
|
|
126535
127292
|
for (const planPhase of plan.phases ?? []) {
|
|
126536
127293
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -126765,8 +127522,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
126765
127522
|
};
|
|
126766
127523
|
}
|
|
126767
127524
|
directory = resolveResult.directory;
|
|
126768
|
-
const planPath =
|
|
126769
|
-
if (!
|
|
127525
|
+
const planPath = path160.join(directory, ".swarm", "plan.json");
|
|
127526
|
+
if (!fs118.existsSync(planPath)) {
|
|
126770
127527
|
return {
|
|
126771
127528
|
success: false,
|
|
126772
127529
|
message: `Invalid working_directory: plan not found in "${directory}"`,
|
|
@@ -126774,9 +127531,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
126774
127531
|
};
|
|
126775
127532
|
}
|
|
126776
127533
|
if (fallbackDir && directory !== fallbackDir) {
|
|
126777
|
-
const canonicalDir =
|
|
126778
|
-
const canonicalRoot =
|
|
126779
|
-
if (canonicalDir.startsWith(canonicalRoot +
|
|
127534
|
+
const canonicalDir = fs118.realpathSync(path160.resolve(directory));
|
|
127535
|
+
const canonicalRoot = fs118.realpathSync(path160.resolve(fallbackDir));
|
|
127536
|
+
if (canonicalDir.startsWith(canonicalRoot + path160.sep)) {
|
|
126780
127537
|
return {
|
|
126781
127538
|
success: false,
|
|
126782
127539
|
message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
|
|
@@ -126788,22 +127545,22 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
126788
127545
|
}
|
|
126789
127546
|
if (args2.status === "in_progress") {
|
|
126790
127547
|
try {
|
|
126791
|
-
const evidencePath =
|
|
126792
|
-
|
|
126793
|
-
const fd =
|
|
127548
|
+
const evidencePath = path160.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
127549
|
+
fs118.mkdirSync(path160.dirname(evidencePath), { recursive: true });
|
|
127550
|
+
const fd = fs118.openSync(evidencePath, "wx");
|
|
126794
127551
|
let writeOk = false;
|
|
126795
127552
|
try {
|
|
126796
|
-
|
|
127553
|
+
fs118.writeSync(fd, JSON.stringify({
|
|
126797
127554
|
taskId: args2.task_id,
|
|
126798
127555
|
required_gates: [],
|
|
126799
127556
|
gates: {}
|
|
126800
127557
|
}, null, 2));
|
|
126801
127558
|
writeOk = true;
|
|
126802
127559
|
} finally {
|
|
126803
|
-
|
|
127560
|
+
fs118.closeSync(fd);
|
|
126804
127561
|
if (!writeOk) {
|
|
126805
127562
|
try {
|
|
126806
|
-
|
|
127563
|
+
fs118.unlinkSync(evidencePath);
|
|
126807
127564
|
} catch {}
|
|
126808
127565
|
}
|
|
126809
127566
|
}
|
|
@@ -126813,8 +127570,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
126813
127570
|
recoverTaskStateFromDelegations(args2.task_id, directory);
|
|
126814
127571
|
let phaseRequiresReviewer = true;
|
|
126815
127572
|
try {
|
|
126816
|
-
const planPath2 =
|
|
126817
|
-
const planRaw =
|
|
127573
|
+
const planPath2 = path160.join(directory, ".swarm", "plan.json");
|
|
127574
|
+
const planRaw = fs118.readFileSync(planPath2, "utf-8");
|
|
126818
127575
|
const plan = JSON.parse(planRaw);
|
|
126819
127576
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
126820
127577
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -127042,7 +127799,7 @@ init_utils2();
|
|
|
127042
127799
|
init_redaction();
|
|
127043
127800
|
import { createHash as createHash12 } from "node:crypto";
|
|
127044
127801
|
import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
|
|
127045
|
-
import * as
|
|
127802
|
+
import * as path161 from "node:path";
|
|
127046
127803
|
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
127047
127804
|
var MAX_EVIDENCE_TEXT_LENGTH = 4000;
|
|
127048
127805
|
async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
@@ -127050,7 +127807,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
|
127050
127807
|
const capturedAt = now().toISOString();
|
|
127051
127808
|
const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
|
|
127052
127809
|
if (records.length > 0) {
|
|
127053
|
-
await mkdir25(
|
|
127810
|
+
await mkdir25(path161.dirname(filePath), { recursive: true });
|
|
127054
127811
|
await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
|
|
127055
127812
|
`)}
|
|
127056
127813
|
`, "utf-8");
|
|
@@ -127247,7 +128004,7 @@ init_schema3();
|
|
|
127247
128004
|
init_store();
|
|
127248
128005
|
init_create_tool();
|
|
127249
128006
|
init_resolve_working_directory();
|
|
127250
|
-
import * as
|
|
128007
|
+
import * as path162 from "node:path";
|
|
127251
128008
|
var FindingSchema2 = exports_external.object({
|
|
127252
128009
|
severity: exports_external.enum(["low", "medium", "high", "critical"]),
|
|
127253
128010
|
category: exports_external.string().min(1),
|
|
@@ -127311,7 +128068,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
127311
128068
|
if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
|
|
127312
128069
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
127313
128070
|
const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
|
|
127314
|
-
const result = await curateAndStoreSwarm(lessons,
|
|
128071
|
+
const result = await curateAndStoreSwarm(lessons, path162.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
|
|
127315
128072
|
knowledgeProposed = result.stored;
|
|
127316
128073
|
}
|
|
127317
128074
|
} catch {}
|
|
@@ -127346,8 +128103,8 @@ init_utils2();
|
|
|
127346
128103
|
init_ledger();
|
|
127347
128104
|
init_manager();
|
|
127348
128105
|
init_create_tool();
|
|
127349
|
-
import
|
|
127350
|
-
import
|
|
128106
|
+
import fs119 from "node:fs";
|
|
128107
|
+
import path163 from "node:path";
|
|
127351
128108
|
function normalizeVerdict(verdict) {
|
|
127352
128109
|
switch (verdict) {
|
|
127353
128110
|
case "APPROVED":
|
|
@@ -127395,7 +128152,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
127395
128152
|
entries: [evidenceEntry]
|
|
127396
128153
|
};
|
|
127397
128154
|
const filename = "drift-verifier.json";
|
|
127398
|
-
const relativePath =
|
|
128155
|
+
const relativePath = path163.join("evidence", String(phase), filename);
|
|
127399
128156
|
let validatedPath;
|
|
127400
128157
|
try {
|
|
127401
128158
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -127406,12 +128163,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
127406
128163
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
127407
128164
|
}, null, 2);
|
|
127408
128165
|
}
|
|
127409
|
-
const evidenceDir =
|
|
128166
|
+
const evidenceDir = path163.dirname(validatedPath);
|
|
127410
128167
|
try {
|
|
127411
|
-
await
|
|
127412
|
-
const tempPath =
|
|
127413
|
-
await
|
|
127414
|
-
await
|
|
128168
|
+
await fs119.promises.mkdir(evidenceDir, { recursive: true });
|
|
128169
|
+
const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
|
|
128170
|
+
await fs119.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
128171
|
+
await fs119.promises.rename(tempPath, validatedPath);
|
|
127415
128172
|
let snapshotInfo;
|
|
127416
128173
|
let snapshotError;
|
|
127417
128174
|
let qaProfileLocked;
|
|
@@ -127505,8 +128262,8 @@ var write_drift_evidence = createSwarmTool({
|
|
|
127505
128262
|
// src/tools/write-final-council-evidence.ts
|
|
127506
128263
|
init_zod();
|
|
127507
128264
|
init_loader();
|
|
127508
|
-
import
|
|
127509
|
-
import
|
|
128265
|
+
import fs120 from "node:fs";
|
|
128266
|
+
import path164 from "node:path";
|
|
127510
128267
|
init_utils2();
|
|
127511
128268
|
init_manager();
|
|
127512
128269
|
init_create_tool();
|
|
@@ -127594,7 +128351,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
127594
128351
|
timestamp: synthesis.timestamp
|
|
127595
128352
|
};
|
|
127596
128353
|
const filename = "final-council.json";
|
|
127597
|
-
const relativePath =
|
|
128354
|
+
const relativePath = path164.join("evidence", filename);
|
|
127598
128355
|
let validatedPath;
|
|
127599
128356
|
try {
|
|
127600
128357
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -127608,12 +128365,12 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
127608
128365
|
const evidenceContent = {
|
|
127609
128366
|
entries: [evidenceEntry]
|
|
127610
128367
|
};
|
|
127611
|
-
const evidenceDir =
|
|
128368
|
+
const evidenceDir = path164.dirname(validatedPath);
|
|
127612
128369
|
try {
|
|
127613
|
-
await
|
|
127614
|
-
const tempPath =
|
|
127615
|
-
await
|
|
127616
|
-
await
|
|
128370
|
+
await fs120.promises.mkdir(evidenceDir, { recursive: true });
|
|
128371
|
+
const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
|
|
128372
|
+
await fs120.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
128373
|
+
await fs120.promises.rename(tempPath, validatedPath);
|
|
127617
128374
|
return JSON.stringify({
|
|
127618
128375
|
success: true,
|
|
127619
128376
|
phase: input.phase,
|
|
@@ -127670,8 +128427,8 @@ var write_final_council_evidence = createSwarmTool({
|
|
|
127670
128427
|
init_zod();
|
|
127671
128428
|
init_utils2();
|
|
127672
128429
|
init_create_tool();
|
|
127673
|
-
import
|
|
127674
|
-
import
|
|
128430
|
+
import fs121 from "node:fs";
|
|
128431
|
+
import path165 from "node:path";
|
|
127675
128432
|
function normalizeVerdict2(verdict) {
|
|
127676
128433
|
switch (verdict) {
|
|
127677
128434
|
case "APPROVED":
|
|
@@ -127719,7 +128476,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
127719
128476
|
entries: [evidenceEntry]
|
|
127720
128477
|
};
|
|
127721
128478
|
const filename = "hallucination-guard.json";
|
|
127722
|
-
const relativePath =
|
|
128479
|
+
const relativePath = path165.join("evidence", String(phase), filename);
|
|
127723
128480
|
let validatedPath;
|
|
127724
128481
|
try {
|
|
127725
128482
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -127730,12 +128487,12 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
127730
128487
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
127731
128488
|
}, null, 2);
|
|
127732
128489
|
}
|
|
127733
|
-
const evidenceDir =
|
|
128490
|
+
const evidenceDir = path165.dirname(validatedPath);
|
|
127734
128491
|
try {
|
|
127735
|
-
await
|
|
127736
|
-
const tempPath =
|
|
127737
|
-
await
|
|
127738
|
-
await
|
|
128492
|
+
await fs121.promises.mkdir(evidenceDir, { recursive: true });
|
|
128493
|
+
const tempPath = path165.join(evidenceDir, `.${filename}.tmp`);
|
|
128494
|
+
await fs121.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
128495
|
+
await fs121.promises.rename(tempPath, validatedPath);
|
|
127739
128496
|
return JSON.stringify({
|
|
127740
128497
|
success: true,
|
|
127741
128498
|
phase,
|
|
@@ -127782,8 +128539,8 @@ var write_hallucination_evidence = createSwarmTool({
|
|
|
127782
128539
|
init_zod();
|
|
127783
128540
|
init_utils2();
|
|
127784
128541
|
init_create_tool();
|
|
127785
|
-
import
|
|
127786
|
-
import
|
|
128542
|
+
import fs122 from "node:fs";
|
|
128543
|
+
import path166 from "node:path";
|
|
127787
128544
|
function normalizeVerdict3(verdict) {
|
|
127788
128545
|
switch (verdict) {
|
|
127789
128546
|
case "PASS":
|
|
@@ -127857,7 +128614,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
127857
128614
|
entries: [evidenceEntry]
|
|
127858
128615
|
};
|
|
127859
128616
|
const filename = "mutation-gate.json";
|
|
127860
|
-
const relativePath =
|
|
128617
|
+
const relativePath = path166.join("evidence", String(phase), filename);
|
|
127861
128618
|
let validatedPath;
|
|
127862
128619
|
try {
|
|
127863
128620
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -127868,12 +128625,12 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
127868
128625
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
127869
128626
|
}, null, 2);
|
|
127870
128627
|
}
|
|
127871
|
-
const evidenceDir =
|
|
128628
|
+
const evidenceDir = path166.dirname(validatedPath);
|
|
127872
128629
|
try {
|
|
127873
|
-
await
|
|
127874
|
-
const tempPath =
|
|
127875
|
-
await
|
|
127876
|
-
await
|
|
128630
|
+
await fs122.promises.mkdir(evidenceDir, { recursive: true });
|
|
128631
|
+
const tempPath = path166.join(evidenceDir, `.${filename}.tmp`);
|
|
128632
|
+
await fs122.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
128633
|
+
await fs122.promises.rename(tempPath, validatedPath);
|
|
127877
128634
|
return JSON.stringify({
|
|
127878
128635
|
success: true,
|
|
127879
128636
|
phase,
|
|
@@ -127955,6 +128712,7 @@ var TOOL_MANIFEST = defineHandlers({
|
|
|
127955
128712
|
mutation_test: () => mutation_test,
|
|
127956
128713
|
generate_mutants: () => generate_mutants,
|
|
127957
128714
|
detect_domains: () => detect_domains,
|
|
128715
|
+
git_blame: () => git_blame,
|
|
127958
128716
|
gitingest: () => gitingest,
|
|
127959
128717
|
retrieve_summary: () => retrieve_summary,
|
|
127960
128718
|
extract_code_blocks: () => extract_code_blocks,
|
|
@@ -128319,7 +129077,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
128319
129077
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
128320
129078
|
preflightTriggerManager = new PTM(automationConfig);
|
|
128321
129079
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
128322
|
-
const swarmDir =
|
|
129080
|
+
const swarmDir = path168.resolve(ctx.directory, ".swarm");
|
|
128323
129081
|
statusArtifact = new ASA(swarmDir);
|
|
128324
129082
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
128325
129083
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -128833,7 +129591,7 @@ ${promptRaw}`;
|
|
|
128833
129591
|
const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
|
|
128834
129592
|
let desc = meta3.description || "";
|
|
128835
129593
|
if (!desc || desc === "No description provided") {
|
|
128836
|
-
desc =
|
|
129594
|
+
desc = path168.basename(path168.dirname(s.skillPath));
|
|
128837
129595
|
}
|
|
128838
129596
|
desc = desc.replace(/,/g, ";");
|
|
128839
129597
|
return `file:${s.skillPath} (-- ${desc})`;
|
|
@@ -128843,7 +129601,7 @@ ${promptRaw}`;
|
|
|
128843
129601
|
|
|
128844
129602
|
${promptRaw}`;
|
|
128845
129603
|
argsRecord.prompt = newPrompt;
|
|
128846
|
-
const skillNames = topSkills.map((s) => `${
|
|
129604
|
+
const skillNames = topSkills.map((s) => `${path168.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
128847
129605
|
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
128848
129606
|
for (const skill of topSkills) {
|
|
128849
129607
|
try {
|