opencode-swarm 6.29.1 → 6.29.2
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 +4 -1
- package/dist/cli/index.js +2 -2
- package/dist/config/schema.d.ts +2 -2
- package/dist/hooks/incremental-verify.d.ts +15 -0
- package/dist/hooks/spawn-helper.d.ts +5 -0
- package/dist/hooks/spawn-helper.test.d.ts +1 -0
- package/dist/index.js +461 -328
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14217,7 +14217,7 @@ var init_evidence_schema = __esm(() => {
|
|
|
14217
14217
|
});
|
|
14218
14218
|
RetrospectiveEvidenceSchema = BaseEvidenceSchema.extend({
|
|
14219
14219
|
type: exports_external.literal("retrospective"),
|
|
14220
|
-
phase_number: exports_external.number().int().min(
|
|
14220
|
+
phase_number: exports_external.number().int().min(1).max(99),
|
|
14221
14221
|
total_tool_calls: exports_external.number().int().min(0).max(9999),
|
|
14222
14222
|
coder_revisions: exports_external.number().int().min(0).max(999),
|
|
14223
14223
|
reviewer_rejections: exports_external.number().int().min(0).max(999),
|
|
@@ -14882,7 +14882,7 @@ var init_schema = __esm(() => {
|
|
|
14882
14882
|
});
|
|
14883
14883
|
IncrementalVerifyConfigSchema = exports_external.object({
|
|
14884
14884
|
enabled: exports_external.boolean().default(true),
|
|
14885
|
-
command: exports_external.string().nullable().default(null),
|
|
14885
|
+
command: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).nullable().default(null),
|
|
14886
14886
|
timeoutMs: exports_external.number().int().min(1000).max(300000).default(30000),
|
|
14887
14887
|
triggerAgents: exports_external.array(exports_external.string()).default(["coder"])
|
|
14888
14888
|
});
|
|
@@ -37601,11 +37601,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37601
37601
|
throw toThrow;
|
|
37602
37602
|
}, "quit_");
|
|
37603
37603
|
var scriptDirectory = "";
|
|
37604
|
-
function locateFile(
|
|
37604
|
+
function locateFile(path46) {
|
|
37605
37605
|
if (Module["locateFile"]) {
|
|
37606
|
-
return Module["locateFile"](
|
|
37606
|
+
return Module["locateFile"](path46, scriptDirectory);
|
|
37607
37607
|
}
|
|
37608
|
-
return scriptDirectory +
|
|
37608
|
+
return scriptDirectory + path46;
|
|
37609
37609
|
}
|
|
37610
37610
|
__name(locateFile, "locateFile");
|
|
37611
37611
|
var readAsync, readBinary;
|
|
@@ -39353,7 +39353,7 @@ var init_runtime = __esm(() => {
|
|
|
39353
39353
|
});
|
|
39354
39354
|
|
|
39355
39355
|
// src/index.ts
|
|
39356
|
-
import * as
|
|
39356
|
+
import * as path56 from "path";
|
|
39357
39357
|
|
|
39358
39358
|
// src/agents/index.ts
|
|
39359
39359
|
init_config();
|
|
@@ -40183,6 +40183,7 @@ Activates when: user asks to "specify", "define requirements", "write a spec", o
|
|
|
40183
40183
|
- Refine \u2192 delegate to MODE: CLARIFY-SPEC
|
|
40184
40184
|
- If NO: proceed to generation (step 2)
|
|
40185
40185
|
- If this is called from the stale spec archival path (MODE: PLAN option 1) \u2014 archival was already completed; skip this check and proceed directly to generation (step 2)
|
|
40186
|
+
1b. Run CODEBASE REALITY CHECK for any codebase references mentioned by the user or implied by the feature. Skip if work is purely greenfield (no existing codebase to check). Report discrepancies before proceeding to explorer.
|
|
40186
40187
|
2. Delegate to \`{{AGENT_PREFIX}}explorer\` to scan the codebase for relevant context (existing patterns, related code, affected areas).
|
|
40187
40188
|
3. Delegate to \`{{AGENT_PREFIX}}sme\` for domain research on the feature area to surface known constraints, best practices, and integration concerns.
|
|
40188
40189
|
4. Generate \`.swarm/spec.md\` capturing:
|
|
@@ -40209,22 +40210,23 @@ Each requirement must be independently testable.
|
|
|
40209
40210
|
Prefer informed defaults over asking the user \u2014 use \`[NEEDS CLARIFICATION]\` only when uncertainty could change scope, security, or core behavior.
|
|
40210
40211
|
|
|
40211
40212
|
EXTERNAL PLAN IMPORT PATH \u2014 when the user provides an existing implementation plan (markdown content, pasted text, or a reference to a file):
|
|
40212
|
-
1.
|
|
40213
|
-
2.
|
|
40213
|
+
1. Run CODEBASE REALITY CHECK scoped to every file, function, API, and behavioral assumption in the provided plan. Report discrepancies to user before proceeding.
|
|
40214
|
+
2. Read and parse the provided plan content.
|
|
40215
|
+
3. Reverse-engineer \`.swarm/spec.md\` from the plan:
|
|
40214
40216
|
- Derive FR-### functional requirements from task descriptions
|
|
40215
40217
|
- Derive SC-### success criteria from acceptance criteria in tasks
|
|
40216
40218
|
- Identify user scenarios from the plan's phase/feature groupings
|
|
40217
40219
|
- Surface implicit assumptions as \`[NEEDS CLARIFICATION]\` markers
|
|
40218
|
-
|
|
40220
|
+
4. Validate the provided plan against swarm task format requirements:
|
|
40219
40221
|
- Every task should have FILE, TASK, CONSTRAINT, and ACCEPTANCE fields
|
|
40220
40222
|
- No task should touch more than 2 files
|
|
40221
40223
|
- No compound verbs in TASK lines ("implement X and add Y" = 2 tasks)
|
|
40222
40224
|
- Dependencies should be declared explicitly
|
|
40223
40225
|
- Phase structure should match \`.swarm/plan.md\` format
|
|
40224
|
-
|
|
40225
|
-
|
|
40226
|
+
5. Report gaps, format issues, and improvement suggestions to the user.
|
|
40227
|
+
6. Ask: "Should I also flesh out any areas that seem underspecified?"
|
|
40226
40228
|
- If yes: delegate to \`{{AGENT_PREFIX}}sme\` for targeted research on weak areas, then propose specific improvements.
|
|
40227
|
-
|
|
40229
|
+
7. Output: both a \`.swarm/spec.md\` (extracted from the plan) and a validated version of the user's plan.
|
|
40228
40230
|
|
|
40229
40231
|
EXTERNAL PLAN RULES:
|
|
40230
40232
|
- Surface ALL changes as suggestions \u2014 do not silently rewrite the user's plan.
|
|
@@ -40327,6 +40329,34 @@ User directives carried forward: {list any persistent directives}
|
|
|
40327
40329
|
|
|
40328
40330
|
This briefing is a HARD REQUIREMENT for ALL phases. Skipping it is a process violation.
|
|
40329
40331
|
|
|
40332
|
+
### CODEBASE REALITY CHECK (Required Before Speccing or Planning)
|
|
40333
|
+
|
|
40334
|
+
Before any spec generation, plan creation, or plan ingestion begins, the Architect must dispatch the Explorer agent in targeted, scoped chunks \u2014 one per logical area of the codebase referenced by the work (e.g., per module, per hook, per config surface). Each chunk must be explored with full depth rather than a broad surface pass.
|
|
40335
|
+
|
|
40336
|
+
For each scoped chunk, Explorer must determine:
|
|
40337
|
+
- Does this file/module/function already exist?
|
|
40338
|
+
- If it exists, what is its current state? Does it already implement any part of what the plan or spec describes?
|
|
40339
|
+
- Is the plan's or user's assumption about the current state accurate? Flag any discrepancy between what is expected and what actually exists.
|
|
40340
|
+
- Has any portion of this work already been applied (partially or fully) in a prior session or commit?
|
|
40341
|
+
|
|
40342
|
+
Explorer outputs a CODEBASE REALITY REPORT before any other agent proceeds. The report must list every referenced item with one of:
|
|
40343
|
+
NOT STARTED | PARTIALLY DONE | ALREADY COMPLETE | ASSUMPTION INCORRECT
|
|
40344
|
+
|
|
40345
|
+
Format:
|
|
40346
|
+
REALITY CHECK: [N] references verified, [M] discrepancies found.
|
|
40347
|
+
\u2713 src/hooks/incremental-verify.ts \u2014 exists, line 69 confirmed Bun.spawn
|
|
40348
|
+
\u2717 src/services/status-service.ts \u2014 ASSUMPTION INCORRECT: compactionCount is no longer hardcoded (fixed in v6.29.1)
|
|
40349
|
+
\u2713 src/config/evidence-schema.ts:107 \u2014 confirmed phase_number min(0)
|
|
40350
|
+
|
|
40351
|
+
No implementation agent (coder, reviewer, test-engineer) may begin until this report is finalized.
|
|
40352
|
+
|
|
40353
|
+
This check fires automatically in:
|
|
40354
|
+
- MODE: SPECIFY \u2014 before explorer dispatch for context (step 2)
|
|
40355
|
+
- MODE: PLAN \u2014 before plan generation or validation
|
|
40356
|
+
- EXTERNAL PLAN IMPORT PATH \u2014 before parsing the provided plan
|
|
40357
|
+
|
|
40358
|
+
GREENFIELD EXEMPTION: If the work is purely greenfield (new project, no existing codebase references), skip this check.
|
|
40359
|
+
|
|
40330
40360
|
### MODE: PLAN
|
|
40331
40361
|
|
|
40332
40362
|
SPEC GATE (soft \u2014 check before planning):
|
|
@@ -40356,6 +40386,8 @@ SPEC GATE (soft \u2014 check before planning):
|
|
|
40356
40386
|
|
|
40357
40387
|
This is a SOFT gate. When the user chooses "Skip and plan directly", proceed to the steps below exactly as before \u2014 do NOT modify any planning behavior.
|
|
40358
40388
|
|
|
40389
|
+
Run CODEBASE REALITY CHECK scoped to codebase elements referenced in spec.md or user constraints. Discrepancies must be reflected in the generated plan.
|
|
40390
|
+
|
|
40359
40391
|
Use the \`save_plan\` tool to create the implementation plan. Required parameters:
|
|
40360
40392
|
- \`title\`: The real project name from the spec (NOT a placeholder like [Project])
|
|
40361
40393
|
- \`swarm_id\`: The swarm identifier (e.g. "mega", "local", "paid")
|
|
@@ -52432,53 +52464,110 @@ function createDarkMatterDetectorHook(directory) {
|
|
|
52432
52464
|
// src/hooks/incremental-verify.ts
|
|
52433
52465
|
import * as fs20 from "fs";
|
|
52434
52466
|
import * as path32 from "path";
|
|
52467
|
+
|
|
52468
|
+
// src/hooks/spawn-helper.ts
|
|
52469
|
+
import { spawn } from "child_process";
|
|
52470
|
+
function spawnAsync(command, cwd, timeoutMs) {
|
|
52471
|
+
return new Promise((resolve11) => {
|
|
52472
|
+
try {
|
|
52473
|
+
const [cmd, ...args2] = command;
|
|
52474
|
+
const proc = spawn(cmd, args2, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
52475
|
+
let stdout = "";
|
|
52476
|
+
let stderr = "";
|
|
52477
|
+
let done = false;
|
|
52478
|
+
proc.stdout.on("data", (d) => {
|
|
52479
|
+
stdout += d;
|
|
52480
|
+
});
|
|
52481
|
+
proc.stderr.on("data", (d) => {
|
|
52482
|
+
stderr += d;
|
|
52483
|
+
});
|
|
52484
|
+
const timer = setTimeout(() => {
|
|
52485
|
+
if (done)
|
|
52486
|
+
return;
|
|
52487
|
+
done = true;
|
|
52488
|
+
try {
|
|
52489
|
+
proc.stdout.destroy();
|
|
52490
|
+
} catch {}
|
|
52491
|
+
try {
|
|
52492
|
+
proc.stderr.destroy();
|
|
52493
|
+
} catch {}
|
|
52494
|
+
try {
|
|
52495
|
+
proc.kill();
|
|
52496
|
+
} catch {}
|
|
52497
|
+
resolve11(null);
|
|
52498
|
+
}, timeoutMs);
|
|
52499
|
+
proc.on("close", (code) => {
|
|
52500
|
+
if (done)
|
|
52501
|
+
return;
|
|
52502
|
+
done = true;
|
|
52503
|
+
clearTimeout(timer);
|
|
52504
|
+
resolve11({ exitCode: code ?? 1, stdout, stderr });
|
|
52505
|
+
});
|
|
52506
|
+
proc.on("error", () => {
|
|
52507
|
+
if (done)
|
|
52508
|
+
return;
|
|
52509
|
+
done = true;
|
|
52510
|
+
clearTimeout(timer);
|
|
52511
|
+
resolve11(null);
|
|
52512
|
+
});
|
|
52513
|
+
} catch {
|
|
52514
|
+
resolve11(null);
|
|
52515
|
+
}
|
|
52516
|
+
});
|
|
52517
|
+
}
|
|
52518
|
+
|
|
52519
|
+
// src/hooks/incremental-verify.ts
|
|
52520
|
+
var emittedSkipAdvisories = new Set;
|
|
52435
52521
|
function detectTypecheckCommand(projectDir) {
|
|
52436
52522
|
const pkgPath = path32.join(projectDir, "package.json");
|
|
52437
|
-
if (
|
|
52438
|
-
|
|
52439
|
-
|
|
52440
|
-
|
|
52441
|
-
|
|
52442
|
-
|
|
52443
|
-
|
|
52444
|
-
|
|
52445
|
-
|
|
52446
|
-
|
|
52447
|
-
|
|
52448
|
-
|
|
52449
|
-
|
|
52450
|
-
|
|
52523
|
+
if (fs20.existsSync(pkgPath)) {
|
|
52524
|
+
try {
|
|
52525
|
+
const pkg = JSON.parse(fs20.readFileSync(pkgPath, "utf8"));
|
|
52526
|
+
const scripts = pkg.scripts;
|
|
52527
|
+
if (scripts?.typecheck)
|
|
52528
|
+
return { command: ["bun", "run", "typecheck"], language: "typescript" };
|
|
52529
|
+
if (scripts?.["type-check"])
|
|
52530
|
+
return {
|
|
52531
|
+
command: ["bun", "run", "type-check"],
|
|
52532
|
+
language: "typescript"
|
|
52533
|
+
};
|
|
52534
|
+
const deps = {
|
|
52535
|
+
...pkg.dependencies,
|
|
52536
|
+
...pkg.devDependencies
|
|
52537
|
+
};
|
|
52538
|
+
if (!deps?.typescript && !fs20.existsSync(path32.join(projectDir, "tsconfig.json"))) {
|
|
52539
|
+
return null;
|
|
52540
|
+
}
|
|
52541
|
+
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
52542
|
+
} catch {
|
|
52451
52543
|
return null;
|
|
52452
52544
|
}
|
|
52453
|
-
return ["npx", "tsc", "--noEmit"];
|
|
52454
|
-
} catch {
|
|
52455
|
-
return null;
|
|
52456
52545
|
}
|
|
52457
|
-
|
|
52458
|
-
|
|
52546
|
+
if (fs20.existsSync(path32.join(projectDir, "go.mod"))) {
|
|
52547
|
+
return { command: ["go", "vet", "./..."], language: "go" };
|
|
52548
|
+
}
|
|
52549
|
+
if (fs20.existsSync(path32.join(projectDir, "Cargo.toml"))) {
|
|
52550
|
+
return { command: ["cargo", "check"], language: "rust" };
|
|
52551
|
+
}
|
|
52552
|
+
if (fs20.existsSync(path32.join(projectDir, "pyproject.toml")) || fs20.existsSync(path32.join(projectDir, "requirements.txt")) || fs20.existsSync(path32.join(projectDir, "setup.py"))) {
|
|
52553
|
+
return { command: null, language: "python" };
|
|
52554
|
+
}
|
|
52459
52555
|
try {
|
|
52460
|
-
const
|
|
52461
|
-
|
|
52462
|
-
|
|
52463
|
-
|
|
52464
|
-
|
|
52465
|
-
|
|
52466
|
-
try {
|
|
52467
|
-
proc.kill();
|
|
52468
|
-
} catch {}
|
|
52469
|
-
}, timeoutMs);
|
|
52470
|
-
try {
|
|
52471
|
-
const [exitCode, stderr] = await Promise.all([
|
|
52472
|
-
proc.exited,
|
|
52473
|
-
new Response(proc.stderr).text()
|
|
52474
|
-
]);
|
|
52475
|
-
return { exitCode, stderr };
|
|
52476
|
-
} finally {
|
|
52477
|
-
clearTimeout(timeoutHandle);
|
|
52556
|
+
const entries = fs20.readdirSync(projectDir);
|
|
52557
|
+
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
52558
|
+
return {
|
|
52559
|
+
command: ["dotnet", "build", "--no-restore"],
|
|
52560
|
+
language: "csharp"
|
|
52561
|
+
};
|
|
52478
52562
|
}
|
|
52479
|
-
} catch {
|
|
52563
|
+
} catch {}
|
|
52564
|
+
return null;
|
|
52565
|
+
}
|
|
52566
|
+
async function runWithTimeout(command, cwd, timeoutMs) {
|
|
52567
|
+
const result = await spawnAsync(command, cwd, timeoutMs);
|
|
52568
|
+
if (result === null)
|
|
52480
52569
|
return null;
|
|
52481
|
-
}
|
|
52570
|
+
return { exitCode: result.exitCode, stderr: result.stderr };
|
|
52482
52571
|
}
|
|
52483
52572
|
function createIncrementalVerifyHook(config3, projectDir, injectMessage) {
|
|
52484
52573
|
return {
|
|
@@ -52493,10 +52582,27 @@ function createIncrementalVerifyHook(config3, projectDir, injectMessage) {
|
|
|
52493
52582
|
if (!config3.triggerAgents.includes(agentName) && !config3.triggerAgents.includes(subagentType)) {
|
|
52494
52583
|
return;
|
|
52495
52584
|
}
|
|
52496
|
-
|
|
52497
|
-
if (
|
|
52585
|
+
let commandToRun = null;
|
|
52586
|
+
if (config3.command != null) {
|
|
52587
|
+
commandToRun = Array.isArray(config3.command) ? config3.command : config3.command.split(" ");
|
|
52588
|
+
} else {
|
|
52589
|
+
const detected = detectTypecheckCommand(projectDir);
|
|
52590
|
+
if (detected === null) {
|
|
52591
|
+
return;
|
|
52592
|
+
}
|
|
52593
|
+
if (detected.command === null) {
|
|
52594
|
+
const dedupKey = `${input.sessionID}:${detected.language}`;
|
|
52595
|
+
if (!emittedSkipAdvisories.has(dedupKey)) {
|
|
52596
|
+
emittedSkipAdvisories.add(dedupKey);
|
|
52597
|
+
injectMessage(input.sessionID, `POST-CODER CHECK SKIPPED: ${detected.language} project detected but no default checker available. Set incremental_verify.command in .swarm/config.json to enable.`);
|
|
52598
|
+
}
|
|
52599
|
+
return;
|
|
52600
|
+
}
|
|
52601
|
+
commandToRun = detected.command;
|
|
52602
|
+
}
|
|
52603
|
+
if (commandToRun === null)
|
|
52498
52604
|
return;
|
|
52499
|
-
const result = await runWithTimeout(
|
|
52605
|
+
const result = await runWithTimeout(commandToRun, projectDir, config3.timeoutMs);
|
|
52500
52606
|
if (result === null) {
|
|
52501
52607
|
return;
|
|
52502
52608
|
}
|
|
@@ -53422,6 +53528,8 @@ ${cachedInjectionText}`;
|
|
|
53422
53528
|
}
|
|
53423
53529
|
|
|
53424
53530
|
// src/hooks/slop-detector.ts
|
|
53531
|
+
import * as fs22 from "fs";
|
|
53532
|
+
import * as path35 from "path";
|
|
53425
53533
|
var WRITE_EDIT_TOOLS = new Set([
|
|
53426
53534
|
"write",
|
|
53427
53535
|
"edit",
|
|
@@ -53432,7 +53540,7 @@ function countMatches(text, pattern) {
|
|
|
53432
53540
|
return (text.match(pattern) ?? []).length;
|
|
53433
53541
|
}
|
|
53434
53542
|
function checkAbstractionBloat(content, threshold) {
|
|
53435
|
-
const newClasses = countMatches(content, /^\+.*\
|
|
53543
|
+
const newClasses = countMatches(content, /^\+.*\b(?:class|struct|impl)\s+\w+/gm);
|
|
53436
53544
|
if (newClasses >= threshold) {
|
|
53437
53545
|
return {
|
|
53438
53546
|
type: "abstraction_bloat",
|
|
@@ -53442,8 +53550,8 @@ function checkAbstractionBloat(content, threshold) {
|
|
|
53442
53550
|
return null;
|
|
53443
53551
|
}
|
|
53444
53552
|
function checkCommentStrip(content, threshold) {
|
|
53445
|
-
const removedComments = countMatches(content, /^-\s
|
|
53446
|
-
const addedComments = countMatches(content, /^\+\s
|
|
53553
|
+
const removedComments = countMatches(content, /^-\s*(?:\/[/*]|#|--)/gm);
|
|
53554
|
+
const addedComments = countMatches(content, /^\+\s*(?:\/[/*]|#|--)/gm);
|
|
53447
53555
|
if (removedComments >= threshold && addedComments === 0) {
|
|
53448
53556
|
return {
|
|
53449
53557
|
type: "comment_strip",
|
|
@@ -53463,8 +53571,33 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
53463
53571
|
}
|
|
53464
53572
|
return null;
|
|
53465
53573
|
}
|
|
53466
|
-
|
|
53467
|
-
const
|
|
53574
|
+
function walkFiles(dir, exts, deadline) {
|
|
53575
|
+
const results = [];
|
|
53576
|
+
try {
|
|
53577
|
+
for (const entry of fs22.readdirSync(dir, { withFileTypes: true })) {
|
|
53578
|
+
if (deadline !== undefined && Date.now() > deadline)
|
|
53579
|
+
break;
|
|
53580
|
+
if (entry.isSymbolicLink())
|
|
53581
|
+
continue;
|
|
53582
|
+
const full = path35.join(dir, entry.name);
|
|
53583
|
+
if (entry.isDirectory()) {
|
|
53584
|
+
if (entry.name === "node_modules" || entry.name === ".git")
|
|
53585
|
+
continue;
|
|
53586
|
+
results.push(...walkFiles(full, exts, deadline));
|
|
53587
|
+
} else if (entry.isFile()) {
|
|
53588
|
+
if (exts.some((ext) => entry.name.endsWith(ext))) {
|
|
53589
|
+
results.push(full);
|
|
53590
|
+
}
|
|
53591
|
+
}
|
|
53592
|
+
}
|
|
53593
|
+
} catch {}
|
|
53594
|
+
return results;
|
|
53595
|
+
}
|
|
53596
|
+
function checkDeadExports(content, projectDir, startTime) {
|
|
53597
|
+
const hasPackageJson = fs22.existsSync(path35.join(projectDir, "package.json"));
|
|
53598
|
+
if (!hasPackageJson)
|
|
53599
|
+
return null;
|
|
53600
|
+
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
53468
53601
|
const newExports = [];
|
|
53469
53602
|
for (const match of exportMatches) {
|
|
53470
53603
|
if (match[1])
|
|
@@ -53472,19 +53605,19 @@ async function checkDeadExports(content, projectDir, startTime) {
|
|
|
53472
53605
|
}
|
|
53473
53606
|
if (newExports.length === 0)
|
|
53474
53607
|
return null;
|
|
53608
|
+
const files = walkFiles(projectDir, [".ts", ".tsx", ".js", ".jsx"], startTime + 480);
|
|
53475
53609
|
const deadExports = [];
|
|
53476
53610
|
for (const name2 of newExports) {
|
|
53477
53611
|
if (Date.now() - startTime > 480)
|
|
53478
53612
|
break;
|
|
53479
53613
|
try {
|
|
53480
53614
|
const importPattern = new RegExp(`\\bimport\\b[^;]*\\b${name2}\\b`, "g");
|
|
53481
|
-
const glob = new Bun.Glob(`src/**/*.ts`);
|
|
53482
53615
|
let found = false;
|
|
53483
|
-
for
|
|
53616
|
+
for (const file3 of files) {
|
|
53484
53617
|
if (found || Date.now() - startTime > 480)
|
|
53485
53618
|
break;
|
|
53486
53619
|
try {
|
|
53487
|
-
const text =
|
|
53620
|
+
const text = fs22.readFileSync(file3, "utf-8");
|
|
53488
53621
|
if (importPattern.test(text))
|
|
53489
53622
|
found = true;
|
|
53490
53623
|
importPattern.lastIndex = 0;
|
|
@@ -53538,7 +53671,7 @@ function createSlopDetectorHook(config3, projectDir, injectSystemMessage) {
|
|
|
53538
53671
|
} catch {}
|
|
53539
53672
|
if (Date.now() - startTime < 400) {
|
|
53540
53673
|
try {
|
|
53541
|
-
const dead =
|
|
53674
|
+
const dead = checkDeadExports(content, projectDir, startTime);
|
|
53542
53675
|
if (dead)
|
|
53543
53676
|
findings.push(dead);
|
|
53544
53677
|
} catch {}
|
|
@@ -53557,7 +53690,7 @@ Review before proceeding.`;
|
|
|
53557
53690
|
|
|
53558
53691
|
// src/hooks/steering-consumed.ts
|
|
53559
53692
|
init_utils2();
|
|
53560
|
-
import * as
|
|
53693
|
+
import * as fs23 from "fs";
|
|
53561
53694
|
function recordSteeringConsumed(directory, directiveId) {
|
|
53562
53695
|
try {
|
|
53563
53696
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -53566,7 +53699,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
53566
53699
|
directiveId,
|
|
53567
53700
|
timestamp: new Date().toISOString()
|
|
53568
53701
|
};
|
|
53569
|
-
|
|
53702
|
+
fs23.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
53570
53703
|
`, "utf-8");
|
|
53571
53704
|
} catch {}
|
|
53572
53705
|
}
|
|
@@ -53611,7 +53744,7 @@ init_config_doctor();
|
|
|
53611
53744
|
|
|
53612
53745
|
// src/session/snapshot-reader.ts
|
|
53613
53746
|
init_utils2();
|
|
53614
|
-
import
|
|
53747
|
+
import path36 from "path";
|
|
53615
53748
|
var VALID_TASK_WORKFLOW_STATES = [
|
|
53616
53749
|
"idle",
|
|
53617
53750
|
"coder_delegated",
|
|
@@ -53736,7 +53869,7 @@ function rehydrateState(snapshot) {
|
|
|
53736
53869
|
async function reconcileTaskStatesFromPlan(directory) {
|
|
53737
53870
|
let raw;
|
|
53738
53871
|
try {
|
|
53739
|
-
raw = await Bun.file(
|
|
53872
|
+
raw = await Bun.file(path36.join(directory, ".swarm/plan.json")).text();
|
|
53740
53873
|
} catch {
|
|
53741
53874
|
return;
|
|
53742
53875
|
}
|
|
@@ -53958,8 +54091,8 @@ var build_check = createSwarmTool({
|
|
|
53958
54091
|
// src/tools/check-gate-status.ts
|
|
53959
54092
|
init_dist();
|
|
53960
54093
|
init_create_tool();
|
|
53961
|
-
import * as
|
|
53962
|
-
import * as
|
|
54094
|
+
import * as fs24 from "fs";
|
|
54095
|
+
import * as path37 from "path";
|
|
53963
54096
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
53964
54097
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
53965
54098
|
function isValidTaskId3(taskId) {
|
|
@@ -53976,18 +54109,18 @@ function isValidTaskId3(taskId) {
|
|
|
53976
54109
|
return TASK_ID_PATTERN2.test(taskId);
|
|
53977
54110
|
}
|
|
53978
54111
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
53979
|
-
const normalizedWorkspace =
|
|
53980
|
-
const swarmPath =
|
|
53981
|
-
const normalizedPath =
|
|
54112
|
+
const normalizedWorkspace = path37.resolve(workspaceRoot);
|
|
54113
|
+
const swarmPath = path37.join(normalizedWorkspace, ".swarm", "evidence");
|
|
54114
|
+
const normalizedPath = path37.resolve(filePath);
|
|
53982
54115
|
return normalizedPath.startsWith(swarmPath);
|
|
53983
54116
|
}
|
|
53984
54117
|
function readEvidenceFile(evidencePath) {
|
|
53985
|
-
if (!
|
|
54118
|
+
if (!fs24.existsSync(evidencePath)) {
|
|
53986
54119
|
return null;
|
|
53987
54120
|
}
|
|
53988
54121
|
let content;
|
|
53989
54122
|
try {
|
|
53990
|
-
content =
|
|
54123
|
+
content = fs24.readFileSync(evidencePath, "utf-8");
|
|
53991
54124
|
} catch {
|
|
53992
54125
|
return null;
|
|
53993
54126
|
}
|
|
@@ -54039,7 +54172,7 @@ var check_gate_status = createSwarmTool({
|
|
|
54039
54172
|
};
|
|
54040
54173
|
return JSON.stringify(errorResult, null, 2);
|
|
54041
54174
|
}
|
|
54042
|
-
const evidencePath =
|
|
54175
|
+
const evidencePath = path37.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
54043
54176
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
54044
54177
|
const errorResult = {
|
|
54045
54178
|
taskId: taskIdInput,
|
|
@@ -54099,8 +54232,8 @@ var check_gate_status = createSwarmTool({
|
|
|
54099
54232
|
init_tool();
|
|
54100
54233
|
init_create_tool();
|
|
54101
54234
|
import { spawnSync } from "child_process";
|
|
54102
|
-
import * as
|
|
54103
|
-
import * as
|
|
54235
|
+
import * as fs25 from "fs";
|
|
54236
|
+
import * as path38 from "path";
|
|
54104
54237
|
var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json";
|
|
54105
54238
|
var MAX_LABEL_LENGTH = 100;
|
|
54106
54239
|
var GIT_TIMEOUT_MS = 30000;
|
|
@@ -54151,13 +54284,13 @@ function validateLabel(label) {
|
|
|
54151
54284
|
return null;
|
|
54152
54285
|
}
|
|
54153
54286
|
function getCheckpointLogPath(directory) {
|
|
54154
|
-
return
|
|
54287
|
+
return path38.join(directory, CHECKPOINT_LOG_PATH);
|
|
54155
54288
|
}
|
|
54156
54289
|
function readCheckpointLog(directory) {
|
|
54157
54290
|
const logPath = getCheckpointLogPath(directory);
|
|
54158
54291
|
try {
|
|
54159
|
-
if (
|
|
54160
|
-
const content =
|
|
54292
|
+
if (fs25.existsSync(logPath)) {
|
|
54293
|
+
const content = fs25.readFileSync(logPath, "utf-8");
|
|
54161
54294
|
const parsed = JSON.parse(content);
|
|
54162
54295
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
54163
54296
|
return { version: 1, checkpoints: [] };
|
|
@@ -54169,13 +54302,13 @@ function readCheckpointLog(directory) {
|
|
|
54169
54302
|
}
|
|
54170
54303
|
function writeCheckpointLog(log2, directory) {
|
|
54171
54304
|
const logPath = getCheckpointLogPath(directory);
|
|
54172
|
-
const dir =
|
|
54173
|
-
if (!
|
|
54174
|
-
|
|
54305
|
+
const dir = path38.dirname(logPath);
|
|
54306
|
+
if (!fs25.existsSync(dir)) {
|
|
54307
|
+
fs25.mkdirSync(dir, { recursive: true });
|
|
54175
54308
|
}
|
|
54176
54309
|
const tempPath = `${logPath}.tmp`;
|
|
54177
|
-
|
|
54178
|
-
|
|
54310
|
+
fs25.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
|
|
54311
|
+
fs25.renameSync(tempPath, logPath);
|
|
54179
54312
|
}
|
|
54180
54313
|
function gitExec(args2) {
|
|
54181
54314
|
const result = spawnSync("git", args2, {
|
|
@@ -54376,8 +54509,8 @@ var checkpoint = createSwarmTool({
|
|
|
54376
54509
|
// src/tools/complexity-hotspots.ts
|
|
54377
54510
|
init_dist();
|
|
54378
54511
|
init_create_tool();
|
|
54379
|
-
import * as
|
|
54380
|
-
import * as
|
|
54512
|
+
import * as fs26 from "fs";
|
|
54513
|
+
import * as path39 from "path";
|
|
54381
54514
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
54382
54515
|
var DEFAULT_DAYS = 90;
|
|
54383
54516
|
var DEFAULT_TOP_N = 20;
|
|
@@ -54506,11 +54639,11 @@ function estimateComplexity(content) {
|
|
|
54506
54639
|
}
|
|
54507
54640
|
function getComplexityForFile(filePath) {
|
|
54508
54641
|
try {
|
|
54509
|
-
const stat2 =
|
|
54642
|
+
const stat2 = fs26.statSync(filePath);
|
|
54510
54643
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
54511
54644
|
return null;
|
|
54512
54645
|
}
|
|
54513
|
-
const content =
|
|
54646
|
+
const content = fs26.readFileSync(filePath, "utf-8");
|
|
54514
54647
|
return estimateComplexity(content);
|
|
54515
54648
|
} catch {
|
|
54516
54649
|
return null;
|
|
@@ -54521,7 +54654,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
54521
54654
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
54522
54655
|
const filteredChurn = new Map;
|
|
54523
54656
|
for (const [file3, count] of churnMap) {
|
|
54524
|
-
const ext =
|
|
54657
|
+
const ext = path39.extname(file3).toLowerCase();
|
|
54525
54658
|
if (extSet.has(ext)) {
|
|
54526
54659
|
filteredChurn.set(file3, count);
|
|
54527
54660
|
}
|
|
@@ -54531,8 +54664,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
54531
54664
|
let analyzedFiles = 0;
|
|
54532
54665
|
for (const [file3, churnCount] of filteredChurn) {
|
|
54533
54666
|
let fullPath = file3;
|
|
54534
|
-
if (!
|
|
54535
|
-
fullPath =
|
|
54667
|
+
if (!fs26.existsSync(fullPath)) {
|
|
54668
|
+
fullPath = path39.join(cwd, file3);
|
|
54536
54669
|
}
|
|
54537
54670
|
const complexity = getComplexityForFile(fullPath);
|
|
54538
54671
|
if (complexity !== null) {
|
|
@@ -54679,8 +54812,8 @@ var complexity_hotspots = createSwarmTool({
|
|
|
54679
54812
|
});
|
|
54680
54813
|
// src/tools/declare-scope.ts
|
|
54681
54814
|
init_tool();
|
|
54682
|
-
import * as
|
|
54683
|
-
import * as
|
|
54815
|
+
import * as fs27 from "fs";
|
|
54816
|
+
import * as path40 from "path";
|
|
54684
54817
|
init_create_tool();
|
|
54685
54818
|
function validateTaskIdFormat(taskId) {
|
|
54686
54819
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -54759,8 +54892,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
54759
54892
|
};
|
|
54760
54893
|
}
|
|
54761
54894
|
}
|
|
54762
|
-
normalizedDir =
|
|
54763
|
-
const pathParts = normalizedDir.split(
|
|
54895
|
+
normalizedDir = path40.normalize(args2.working_directory);
|
|
54896
|
+
const pathParts = normalizedDir.split(path40.sep);
|
|
54764
54897
|
if (pathParts.includes("..")) {
|
|
54765
54898
|
return {
|
|
54766
54899
|
success: false,
|
|
@@ -54770,11 +54903,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
54770
54903
|
]
|
|
54771
54904
|
};
|
|
54772
54905
|
}
|
|
54773
|
-
const resolvedDir =
|
|
54906
|
+
const resolvedDir = path40.resolve(normalizedDir);
|
|
54774
54907
|
try {
|
|
54775
|
-
const realPath =
|
|
54776
|
-
const planPath2 =
|
|
54777
|
-
if (!
|
|
54908
|
+
const realPath = fs27.realpathSync(resolvedDir);
|
|
54909
|
+
const planPath2 = path40.join(realPath, ".swarm", "plan.json");
|
|
54910
|
+
if (!fs27.existsSync(planPath2)) {
|
|
54778
54911
|
return {
|
|
54779
54912
|
success: false,
|
|
54780
54913
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -54794,8 +54927,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
54794
54927
|
}
|
|
54795
54928
|
}
|
|
54796
54929
|
const directory = normalizedDir ?? fallbackDir ?? process.cwd();
|
|
54797
|
-
const planPath =
|
|
54798
|
-
if (!
|
|
54930
|
+
const planPath = path40.resolve(directory, ".swarm", "plan.json");
|
|
54931
|
+
if (!fs27.existsSync(planPath)) {
|
|
54799
54932
|
return {
|
|
54800
54933
|
success: false,
|
|
54801
54934
|
message: "No plan found",
|
|
@@ -54804,7 +54937,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
54804
54937
|
}
|
|
54805
54938
|
let planContent;
|
|
54806
54939
|
try {
|
|
54807
|
-
planContent = JSON.parse(
|
|
54940
|
+
planContent = JSON.parse(fs27.readFileSync(planPath, "utf-8"));
|
|
54808
54941
|
} catch {
|
|
54809
54942
|
return {
|
|
54810
54943
|
success: false,
|
|
@@ -54884,20 +55017,20 @@ function validateBase(base) {
|
|
|
54884
55017
|
function validatePaths(paths) {
|
|
54885
55018
|
if (!paths)
|
|
54886
55019
|
return null;
|
|
54887
|
-
for (const
|
|
54888
|
-
if (!
|
|
55020
|
+
for (const path41 of paths) {
|
|
55021
|
+
if (!path41 || path41.length === 0) {
|
|
54889
55022
|
return "empty path not allowed";
|
|
54890
55023
|
}
|
|
54891
|
-
if (
|
|
55024
|
+
if (path41.length > MAX_PATH_LENGTH) {
|
|
54892
55025
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
54893
55026
|
}
|
|
54894
|
-
if (SHELL_METACHARACTERS2.test(
|
|
55027
|
+
if (SHELL_METACHARACTERS2.test(path41)) {
|
|
54895
55028
|
return "path contains shell metacharacters";
|
|
54896
55029
|
}
|
|
54897
|
-
if (
|
|
55030
|
+
if (path41.startsWith("-")) {
|
|
54898
55031
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
54899
55032
|
}
|
|
54900
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
55033
|
+
if (CONTROL_CHAR_PATTERN2.test(path41)) {
|
|
54901
55034
|
return "path contains control characters";
|
|
54902
55035
|
}
|
|
54903
55036
|
}
|
|
@@ -54977,8 +55110,8 @@ var diff = tool({
|
|
|
54977
55110
|
if (parts2.length >= 3) {
|
|
54978
55111
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
54979
55112
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
54980
|
-
const
|
|
54981
|
-
files.push({ path:
|
|
55113
|
+
const path41 = parts2[2];
|
|
55114
|
+
files.push({ path: path41, additions, deletions });
|
|
54982
55115
|
}
|
|
54983
55116
|
}
|
|
54984
55117
|
const contractChanges = [];
|
|
@@ -55207,8 +55340,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
55207
55340
|
// src/tools/evidence-check.ts
|
|
55208
55341
|
init_dist();
|
|
55209
55342
|
init_create_tool();
|
|
55210
|
-
import * as
|
|
55211
|
-
import * as
|
|
55343
|
+
import * as fs28 from "fs";
|
|
55344
|
+
import * as path41 from "path";
|
|
55212
55345
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
55213
55346
|
var MAX_EVIDENCE_FILES = 1000;
|
|
55214
55347
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -55238,9 +55371,9 @@ function validateRequiredTypes(input) {
|
|
|
55238
55371
|
return null;
|
|
55239
55372
|
}
|
|
55240
55373
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
55241
|
-
const normalizedCwd =
|
|
55242
|
-
const swarmPath =
|
|
55243
|
-
const normalizedPath =
|
|
55374
|
+
const normalizedCwd = path41.resolve(cwd);
|
|
55375
|
+
const swarmPath = path41.join(normalizedCwd, ".swarm");
|
|
55376
|
+
const normalizedPath = path41.resolve(filePath);
|
|
55244
55377
|
return normalizedPath.startsWith(swarmPath);
|
|
55245
55378
|
}
|
|
55246
55379
|
function parseCompletedTasks(planContent) {
|
|
@@ -55256,12 +55389,12 @@ function parseCompletedTasks(planContent) {
|
|
|
55256
55389
|
}
|
|
55257
55390
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
55258
55391
|
const evidence = [];
|
|
55259
|
-
if (!
|
|
55392
|
+
if (!fs28.existsSync(evidenceDir) || !fs28.statSync(evidenceDir).isDirectory()) {
|
|
55260
55393
|
return evidence;
|
|
55261
55394
|
}
|
|
55262
55395
|
let files;
|
|
55263
55396
|
try {
|
|
55264
|
-
files =
|
|
55397
|
+
files = fs28.readdirSync(evidenceDir);
|
|
55265
55398
|
} catch {
|
|
55266
55399
|
return evidence;
|
|
55267
55400
|
}
|
|
@@ -55270,14 +55403,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
55270
55403
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
55271
55404
|
continue;
|
|
55272
55405
|
}
|
|
55273
|
-
const filePath =
|
|
55406
|
+
const filePath = path41.join(evidenceDir, filename);
|
|
55274
55407
|
try {
|
|
55275
|
-
const resolvedPath =
|
|
55276
|
-
const evidenceDirResolved =
|
|
55408
|
+
const resolvedPath = path41.resolve(filePath);
|
|
55409
|
+
const evidenceDirResolved = path41.resolve(evidenceDir);
|
|
55277
55410
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
55278
55411
|
continue;
|
|
55279
55412
|
}
|
|
55280
|
-
const stat2 =
|
|
55413
|
+
const stat2 = fs28.lstatSync(filePath);
|
|
55281
55414
|
if (!stat2.isFile()) {
|
|
55282
55415
|
continue;
|
|
55283
55416
|
}
|
|
@@ -55286,7 +55419,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
55286
55419
|
}
|
|
55287
55420
|
let fileStat;
|
|
55288
55421
|
try {
|
|
55289
|
-
fileStat =
|
|
55422
|
+
fileStat = fs28.statSync(filePath);
|
|
55290
55423
|
if (fileStat.size > MAX_FILE_SIZE_BYTES3) {
|
|
55291
55424
|
continue;
|
|
55292
55425
|
}
|
|
@@ -55295,7 +55428,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
55295
55428
|
}
|
|
55296
55429
|
let content;
|
|
55297
55430
|
try {
|
|
55298
|
-
content =
|
|
55431
|
+
content = fs28.readFileSync(filePath, "utf-8");
|
|
55299
55432
|
} catch {
|
|
55300
55433
|
continue;
|
|
55301
55434
|
}
|
|
@@ -55391,7 +55524,7 @@ var evidence_check = createSwarmTool({
|
|
|
55391
55524
|
return JSON.stringify(errorResult, null, 2);
|
|
55392
55525
|
}
|
|
55393
55526
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
55394
|
-
const planPath =
|
|
55527
|
+
const planPath = path41.join(cwd, PLAN_FILE);
|
|
55395
55528
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
55396
55529
|
const errorResult = {
|
|
55397
55530
|
error: "plan file path validation failed",
|
|
@@ -55405,7 +55538,7 @@ var evidence_check = createSwarmTool({
|
|
|
55405
55538
|
}
|
|
55406
55539
|
let planContent;
|
|
55407
55540
|
try {
|
|
55408
|
-
planContent =
|
|
55541
|
+
planContent = fs28.readFileSync(planPath, "utf-8");
|
|
55409
55542
|
} catch {
|
|
55410
55543
|
const result2 = {
|
|
55411
55544
|
message: "No completed tasks found in plan.",
|
|
@@ -55423,7 +55556,7 @@ var evidence_check = createSwarmTool({
|
|
|
55423
55556
|
};
|
|
55424
55557
|
return JSON.stringify(result2, null, 2);
|
|
55425
55558
|
}
|
|
55426
|
-
const evidenceDir =
|
|
55559
|
+
const evidenceDir = path41.join(cwd, EVIDENCE_DIR2);
|
|
55427
55560
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
55428
55561
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
55429
55562
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -55440,8 +55573,8 @@ var evidence_check = createSwarmTool({
|
|
|
55440
55573
|
// src/tools/file-extractor.ts
|
|
55441
55574
|
init_tool();
|
|
55442
55575
|
init_create_tool();
|
|
55443
|
-
import * as
|
|
55444
|
-
import * as
|
|
55576
|
+
import * as fs29 from "fs";
|
|
55577
|
+
import * as path42 from "path";
|
|
55445
55578
|
var EXT_MAP = {
|
|
55446
55579
|
python: ".py",
|
|
55447
55580
|
py: ".py",
|
|
@@ -55503,8 +55636,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
55503
55636
|
execute: async (args2, directory) => {
|
|
55504
55637
|
const { content, output_dir, prefix } = args2;
|
|
55505
55638
|
const targetDir = output_dir || directory;
|
|
55506
|
-
if (!
|
|
55507
|
-
|
|
55639
|
+
if (!fs29.existsSync(targetDir)) {
|
|
55640
|
+
fs29.mkdirSync(targetDir, { recursive: true });
|
|
55508
55641
|
}
|
|
55509
55642
|
if (!content) {
|
|
55510
55643
|
return "Error: content is required";
|
|
@@ -55522,16 +55655,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
55522
55655
|
if (prefix) {
|
|
55523
55656
|
filename = `${prefix}_${filename}`;
|
|
55524
55657
|
}
|
|
55525
|
-
let filepath =
|
|
55526
|
-
const base =
|
|
55527
|
-
const ext =
|
|
55658
|
+
let filepath = path42.join(targetDir, filename);
|
|
55659
|
+
const base = path42.basename(filepath, path42.extname(filepath));
|
|
55660
|
+
const ext = path42.extname(filepath);
|
|
55528
55661
|
let counter = 1;
|
|
55529
|
-
while (
|
|
55530
|
-
filepath =
|
|
55662
|
+
while (fs29.existsSync(filepath)) {
|
|
55663
|
+
filepath = path42.join(targetDir, `${base}_${counter}${ext}`);
|
|
55531
55664
|
counter++;
|
|
55532
55665
|
}
|
|
55533
55666
|
try {
|
|
55534
|
-
|
|
55667
|
+
fs29.writeFileSync(filepath, code.trim(), "utf-8");
|
|
55535
55668
|
savedFiles.push(filepath);
|
|
55536
55669
|
} catch (error93) {
|
|
55537
55670
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -55644,8 +55777,8 @@ var gitingest = tool({
|
|
|
55644
55777
|
});
|
|
55645
55778
|
// src/tools/imports.ts
|
|
55646
55779
|
init_dist();
|
|
55647
|
-
import * as
|
|
55648
|
-
import * as
|
|
55780
|
+
import * as fs30 from "fs";
|
|
55781
|
+
import * as path43 from "path";
|
|
55649
55782
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
55650
55783
|
var MAX_SYMBOL_LENGTH = 256;
|
|
55651
55784
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
@@ -55699,7 +55832,7 @@ function validateSymbolInput(symbol3) {
|
|
|
55699
55832
|
return null;
|
|
55700
55833
|
}
|
|
55701
55834
|
function isBinaryFile2(filePath, buffer) {
|
|
55702
|
-
const ext =
|
|
55835
|
+
const ext = path43.extname(filePath).toLowerCase();
|
|
55703
55836
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
55704
55837
|
return false;
|
|
55705
55838
|
}
|
|
@@ -55723,15 +55856,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
55723
55856
|
const imports = [];
|
|
55724
55857
|
let _resolvedTarget;
|
|
55725
55858
|
try {
|
|
55726
|
-
_resolvedTarget =
|
|
55859
|
+
_resolvedTarget = path43.resolve(targetFile);
|
|
55727
55860
|
} catch {
|
|
55728
55861
|
_resolvedTarget = targetFile;
|
|
55729
55862
|
}
|
|
55730
|
-
const targetBasename =
|
|
55863
|
+
const targetBasename = path43.basename(targetFile, path43.extname(targetFile));
|
|
55731
55864
|
const targetWithExt = targetFile;
|
|
55732
55865
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
55733
|
-
const normalizedTargetWithExt =
|
|
55734
|
-
const normalizedTargetWithoutExt =
|
|
55866
|
+
const normalizedTargetWithExt = path43.normalize(targetWithExt).replace(/\\/g, "/");
|
|
55867
|
+
const normalizedTargetWithoutExt = path43.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
55735
55868
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
55736
55869
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
55737
55870
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -55754,9 +55887,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
55754
55887
|
}
|
|
55755
55888
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
55756
55889
|
let isMatch = false;
|
|
55757
|
-
const _targetDir =
|
|
55758
|
-
const targetExt =
|
|
55759
|
-
const targetBasenameNoExt =
|
|
55890
|
+
const _targetDir = path43.dirname(targetFile);
|
|
55891
|
+
const targetExt = path43.extname(targetFile);
|
|
55892
|
+
const targetBasenameNoExt = path43.basename(targetFile, targetExt);
|
|
55760
55893
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
55761
55894
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
55762
55895
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -55813,7 +55946,7 @@ var SKIP_DIRECTORIES2 = new Set([
|
|
|
55813
55946
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
55814
55947
|
let entries;
|
|
55815
55948
|
try {
|
|
55816
|
-
entries =
|
|
55949
|
+
entries = fs30.readdirSync(dir);
|
|
55817
55950
|
} catch (e) {
|
|
55818
55951
|
stats.fileErrors.push({
|
|
55819
55952
|
path: dir,
|
|
@@ -55824,13 +55957,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
55824
55957
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
55825
55958
|
for (const entry of entries) {
|
|
55826
55959
|
if (SKIP_DIRECTORIES2.has(entry)) {
|
|
55827
|
-
stats.skippedDirs.push(
|
|
55960
|
+
stats.skippedDirs.push(path43.join(dir, entry));
|
|
55828
55961
|
continue;
|
|
55829
55962
|
}
|
|
55830
|
-
const fullPath =
|
|
55963
|
+
const fullPath = path43.join(dir, entry);
|
|
55831
55964
|
let stat2;
|
|
55832
55965
|
try {
|
|
55833
|
-
stat2 =
|
|
55966
|
+
stat2 = fs30.statSync(fullPath);
|
|
55834
55967
|
} catch (e) {
|
|
55835
55968
|
stats.fileErrors.push({
|
|
55836
55969
|
path: fullPath,
|
|
@@ -55841,7 +55974,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
55841
55974
|
if (stat2.isDirectory()) {
|
|
55842
55975
|
findSourceFiles(fullPath, files, stats);
|
|
55843
55976
|
} else if (stat2.isFile()) {
|
|
55844
|
-
const ext =
|
|
55977
|
+
const ext = path43.extname(fullPath).toLowerCase();
|
|
55845
55978
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
55846
55979
|
files.push(fullPath);
|
|
55847
55980
|
}
|
|
@@ -55897,8 +56030,8 @@ var imports = tool({
|
|
|
55897
56030
|
return JSON.stringify(errorResult, null, 2);
|
|
55898
56031
|
}
|
|
55899
56032
|
try {
|
|
55900
|
-
const targetFile =
|
|
55901
|
-
if (!
|
|
56033
|
+
const targetFile = path43.resolve(file3);
|
|
56034
|
+
if (!fs30.existsSync(targetFile)) {
|
|
55902
56035
|
const errorResult = {
|
|
55903
56036
|
error: `target file not found: ${file3}`,
|
|
55904
56037
|
target: file3,
|
|
@@ -55908,7 +56041,7 @@ var imports = tool({
|
|
|
55908
56041
|
};
|
|
55909
56042
|
return JSON.stringify(errorResult, null, 2);
|
|
55910
56043
|
}
|
|
55911
|
-
const targetStat =
|
|
56044
|
+
const targetStat = fs30.statSync(targetFile);
|
|
55912
56045
|
if (!targetStat.isFile()) {
|
|
55913
56046
|
const errorResult = {
|
|
55914
56047
|
error: "target must be a file, not a directory",
|
|
@@ -55919,7 +56052,7 @@ var imports = tool({
|
|
|
55919
56052
|
};
|
|
55920
56053
|
return JSON.stringify(errorResult, null, 2);
|
|
55921
56054
|
}
|
|
55922
|
-
const baseDir =
|
|
56055
|
+
const baseDir = path43.dirname(targetFile);
|
|
55923
56056
|
const scanStats = {
|
|
55924
56057
|
skippedDirs: [],
|
|
55925
56058
|
skippedFiles: 0,
|
|
@@ -55934,12 +56067,12 @@ var imports = tool({
|
|
|
55934
56067
|
if (consumers.length >= MAX_CONSUMERS)
|
|
55935
56068
|
break;
|
|
55936
56069
|
try {
|
|
55937
|
-
const stat2 =
|
|
56070
|
+
const stat2 = fs30.statSync(filePath);
|
|
55938
56071
|
if (stat2.size > MAX_FILE_SIZE_BYTES4) {
|
|
55939
56072
|
skippedFileCount++;
|
|
55940
56073
|
continue;
|
|
55941
56074
|
}
|
|
55942
|
-
const buffer =
|
|
56075
|
+
const buffer = fs30.readFileSync(filePath);
|
|
55943
56076
|
if (isBinaryFile2(filePath, buffer)) {
|
|
55944
56077
|
skippedFileCount++;
|
|
55945
56078
|
continue;
|
|
@@ -56004,7 +56137,7 @@ var imports = tool({
|
|
|
56004
56137
|
});
|
|
56005
56138
|
// src/tools/knowledge-query.ts
|
|
56006
56139
|
init_dist();
|
|
56007
|
-
import { existsSync as
|
|
56140
|
+
import { existsSync as existsSync28 } from "fs";
|
|
56008
56141
|
init_create_tool();
|
|
56009
56142
|
var DEFAULT_LIMIT = 10;
|
|
56010
56143
|
var MAX_LESSON_LENGTH = 200;
|
|
@@ -56074,14 +56207,14 @@ function validateLimit(limit) {
|
|
|
56074
56207
|
}
|
|
56075
56208
|
async function readSwarmKnowledge(directory) {
|
|
56076
56209
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
56077
|
-
if (!
|
|
56210
|
+
if (!existsSync28(swarmPath)) {
|
|
56078
56211
|
return [];
|
|
56079
56212
|
}
|
|
56080
56213
|
return readKnowledge(swarmPath);
|
|
56081
56214
|
}
|
|
56082
56215
|
async function readHiveKnowledge() {
|
|
56083
56216
|
const hivePath = resolveHiveKnowledgePath();
|
|
56084
|
-
if (!
|
|
56217
|
+
if (!existsSync28(hivePath)) {
|
|
56085
56218
|
return [];
|
|
56086
56219
|
}
|
|
56087
56220
|
return readKnowledge(hivePath);
|
|
@@ -56240,8 +56373,8 @@ init_dist();
|
|
|
56240
56373
|
init_config();
|
|
56241
56374
|
init_schema();
|
|
56242
56375
|
init_manager();
|
|
56243
|
-
import * as
|
|
56244
|
-
import * as
|
|
56376
|
+
import * as fs31 from "fs";
|
|
56377
|
+
import * as path44 from "path";
|
|
56245
56378
|
init_utils2();
|
|
56246
56379
|
init_create_tool();
|
|
56247
56380
|
function safeWarn(message, error93) {
|
|
@@ -56436,7 +56569,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56436
56569
|
}
|
|
56437
56570
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
56438
56571
|
try {
|
|
56439
|
-
const projectName =
|
|
56572
|
+
const projectName = path44.basename(dir);
|
|
56440
56573
|
const knowledgeConfig = {
|
|
56441
56574
|
enabled: true,
|
|
56442
56575
|
swarm_max_entries: 100,
|
|
@@ -56484,7 +56617,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56484
56617
|
if (agentsMissing.length > 0) {
|
|
56485
56618
|
try {
|
|
56486
56619
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
56487
|
-
const planRaw =
|
|
56620
|
+
const planRaw = fs31.readFileSync(planPath, "utf-8");
|
|
56488
56621
|
const plan = JSON.parse(planRaw);
|
|
56489
56622
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
56490
56623
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -56525,7 +56658,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56525
56658
|
};
|
|
56526
56659
|
try {
|
|
56527
56660
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
56528
|
-
|
|
56661
|
+
fs31.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
56529
56662
|
`, "utf-8");
|
|
56530
56663
|
} catch (writeError) {
|
|
56531
56664
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -56544,12 +56677,12 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56544
56677
|
}
|
|
56545
56678
|
try {
|
|
56546
56679
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
56547
|
-
const planJson =
|
|
56680
|
+
const planJson = fs31.readFileSync(planPath, "utf-8");
|
|
56548
56681
|
const plan = JSON.parse(planJson);
|
|
56549
56682
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
56550
56683
|
if (phaseObj) {
|
|
56551
56684
|
phaseObj.status = "completed";
|
|
56552
|
-
|
|
56685
|
+
fs31.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
56553
56686
|
`, "utf-8");
|
|
56554
56687
|
}
|
|
56555
56688
|
} catch (error93) {
|
|
@@ -56599,8 +56732,8 @@ init_dist();
|
|
|
56599
56732
|
init_discovery();
|
|
56600
56733
|
init_utils();
|
|
56601
56734
|
init_create_tool();
|
|
56602
|
-
import * as
|
|
56603
|
-
import * as
|
|
56735
|
+
import * as fs32 from "fs";
|
|
56736
|
+
import * as path45 from "path";
|
|
56604
56737
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
56605
56738
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
56606
56739
|
function isValidEcosystem(value) {
|
|
@@ -56618,28 +56751,28 @@ function validateArgs3(args2) {
|
|
|
56618
56751
|
function detectEcosystems(directory) {
|
|
56619
56752
|
const ecosystems = [];
|
|
56620
56753
|
const cwd = directory;
|
|
56621
|
-
if (
|
|
56754
|
+
if (fs32.existsSync(path45.join(cwd, "package.json"))) {
|
|
56622
56755
|
ecosystems.push("npm");
|
|
56623
56756
|
}
|
|
56624
|
-
if (
|
|
56757
|
+
if (fs32.existsSync(path45.join(cwd, "pyproject.toml")) || fs32.existsSync(path45.join(cwd, "requirements.txt"))) {
|
|
56625
56758
|
ecosystems.push("pip");
|
|
56626
56759
|
}
|
|
56627
|
-
if (
|
|
56760
|
+
if (fs32.existsSync(path45.join(cwd, "Cargo.toml"))) {
|
|
56628
56761
|
ecosystems.push("cargo");
|
|
56629
56762
|
}
|
|
56630
|
-
if (
|
|
56763
|
+
if (fs32.existsSync(path45.join(cwd, "go.mod"))) {
|
|
56631
56764
|
ecosystems.push("go");
|
|
56632
56765
|
}
|
|
56633
56766
|
try {
|
|
56634
|
-
const files =
|
|
56767
|
+
const files = fs32.readdirSync(cwd);
|
|
56635
56768
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
56636
56769
|
ecosystems.push("dotnet");
|
|
56637
56770
|
}
|
|
56638
56771
|
} catch {}
|
|
56639
|
-
if (
|
|
56772
|
+
if (fs32.existsSync(path45.join(cwd, "Gemfile")) || fs32.existsSync(path45.join(cwd, "Gemfile.lock"))) {
|
|
56640
56773
|
ecosystems.push("ruby");
|
|
56641
56774
|
}
|
|
56642
|
-
if (
|
|
56775
|
+
if (fs32.existsSync(path45.join(cwd, "pubspec.yaml"))) {
|
|
56643
56776
|
ecosystems.push("dart");
|
|
56644
56777
|
}
|
|
56645
56778
|
return ecosystems;
|
|
@@ -57701,8 +57834,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
57701
57834
|
]);
|
|
57702
57835
|
// src/tools/pre-check-batch.ts
|
|
57703
57836
|
init_dist();
|
|
57704
|
-
import * as
|
|
57705
|
-
import * as
|
|
57837
|
+
import * as fs35 from "fs";
|
|
57838
|
+
import * as path48 from "path";
|
|
57706
57839
|
|
|
57707
57840
|
// node_modules/yocto-queue/index.js
|
|
57708
57841
|
class Node2 {
|
|
@@ -57869,8 +58002,8 @@ init_lint();
|
|
|
57869
58002
|
init_manager();
|
|
57870
58003
|
|
|
57871
58004
|
// src/quality/metrics.ts
|
|
57872
|
-
import * as
|
|
57873
|
-
import * as
|
|
58005
|
+
import * as fs33 from "fs";
|
|
58006
|
+
import * as path46 from "path";
|
|
57874
58007
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
57875
58008
|
var MIN_DUPLICATION_LINES = 10;
|
|
57876
58009
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -57908,11 +58041,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
57908
58041
|
}
|
|
57909
58042
|
function getComplexityForFile2(filePath) {
|
|
57910
58043
|
try {
|
|
57911
|
-
const stat2 =
|
|
58044
|
+
const stat2 = fs33.statSync(filePath);
|
|
57912
58045
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
57913
58046
|
return null;
|
|
57914
58047
|
}
|
|
57915
|
-
const content =
|
|
58048
|
+
const content = fs33.readFileSync(filePath, "utf-8");
|
|
57916
58049
|
return estimateCyclomaticComplexity(content);
|
|
57917
58050
|
} catch {
|
|
57918
58051
|
return null;
|
|
@@ -57922,8 +58055,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
57922
58055
|
let totalComplexity = 0;
|
|
57923
58056
|
const analyzedFiles = [];
|
|
57924
58057
|
for (const file3 of files) {
|
|
57925
|
-
const fullPath =
|
|
57926
|
-
if (!
|
|
58058
|
+
const fullPath = path46.isAbsolute(file3) ? file3 : path46.join(workingDir, file3);
|
|
58059
|
+
if (!fs33.existsSync(fullPath)) {
|
|
57927
58060
|
continue;
|
|
57928
58061
|
}
|
|
57929
58062
|
const complexity = getComplexityForFile2(fullPath);
|
|
@@ -58044,8 +58177,8 @@ function countGoExports(content) {
|
|
|
58044
58177
|
}
|
|
58045
58178
|
function getExportCountForFile(filePath) {
|
|
58046
58179
|
try {
|
|
58047
|
-
const content =
|
|
58048
|
-
const ext =
|
|
58180
|
+
const content = fs33.readFileSync(filePath, "utf-8");
|
|
58181
|
+
const ext = path46.extname(filePath).toLowerCase();
|
|
58049
58182
|
switch (ext) {
|
|
58050
58183
|
case ".ts":
|
|
58051
58184
|
case ".tsx":
|
|
@@ -58071,8 +58204,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58071
58204
|
let totalExports = 0;
|
|
58072
58205
|
const analyzedFiles = [];
|
|
58073
58206
|
for (const file3 of files) {
|
|
58074
|
-
const fullPath =
|
|
58075
|
-
if (!
|
|
58207
|
+
const fullPath = path46.isAbsolute(file3) ? file3 : path46.join(workingDir, file3);
|
|
58208
|
+
if (!fs33.existsSync(fullPath)) {
|
|
58076
58209
|
continue;
|
|
58077
58210
|
}
|
|
58078
58211
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -58105,16 +58238,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58105
58238
|
let duplicateLines = 0;
|
|
58106
58239
|
const analyzedFiles = [];
|
|
58107
58240
|
for (const file3 of files) {
|
|
58108
|
-
const fullPath =
|
|
58109
|
-
if (!
|
|
58241
|
+
const fullPath = path46.isAbsolute(file3) ? file3 : path46.join(workingDir, file3);
|
|
58242
|
+
if (!fs33.existsSync(fullPath)) {
|
|
58110
58243
|
continue;
|
|
58111
58244
|
}
|
|
58112
58245
|
try {
|
|
58113
|
-
const stat2 =
|
|
58246
|
+
const stat2 = fs33.statSync(fullPath);
|
|
58114
58247
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
58115
58248
|
continue;
|
|
58116
58249
|
}
|
|
58117
|
-
const content =
|
|
58250
|
+
const content = fs33.readFileSync(fullPath, "utf-8");
|
|
58118
58251
|
const lines = content.split(`
|
|
58119
58252
|
`).filter((line) => line.trim().length > 0);
|
|
58120
58253
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -58138,8 +58271,8 @@ function countCodeLines(content) {
|
|
|
58138
58271
|
return lines.length;
|
|
58139
58272
|
}
|
|
58140
58273
|
function isTestFile(filePath) {
|
|
58141
|
-
const basename8 =
|
|
58142
|
-
const _ext =
|
|
58274
|
+
const basename8 = path46.basename(filePath);
|
|
58275
|
+
const _ext = path46.extname(filePath).toLowerCase();
|
|
58143
58276
|
const testPatterns = [
|
|
58144
58277
|
".test.",
|
|
58145
58278
|
".spec.",
|
|
@@ -58220,8 +58353,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58220
58353
|
}
|
|
58221
58354
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58222
58355
|
}
|
|
58223
|
-
function matchesGlobSegment(
|
|
58224
|
-
const normalizedPath =
|
|
58356
|
+
function matchesGlobSegment(path47, glob) {
|
|
58357
|
+
const normalizedPath = path47.replace(/\\/g, "/");
|
|
58225
58358
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58226
58359
|
if (normalizedPath.includes("//")) {
|
|
58227
58360
|
return false;
|
|
@@ -58252,8 +58385,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58252
58385
|
function hasGlobstar(glob) {
|
|
58253
58386
|
return glob.includes("**");
|
|
58254
58387
|
}
|
|
58255
|
-
function globMatches(
|
|
58256
|
-
const normalizedPath =
|
|
58388
|
+
function globMatches(path47, glob) {
|
|
58389
|
+
const normalizedPath = path47.replace(/\\/g, "/");
|
|
58257
58390
|
if (!glob || glob === "") {
|
|
58258
58391
|
if (normalizedPath.includes("//")) {
|
|
58259
58392
|
return false;
|
|
@@ -58289,31 +58422,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58289
58422
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58290
58423
|
let testLines = 0;
|
|
58291
58424
|
let codeLines = 0;
|
|
58292
|
-
const srcDir =
|
|
58293
|
-
if (
|
|
58425
|
+
const srcDir = path46.join(workingDir, "src");
|
|
58426
|
+
if (fs33.existsSync(srcDir)) {
|
|
58294
58427
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58295
58428
|
codeLines += lines;
|
|
58296
58429
|
});
|
|
58297
58430
|
}
|
|
58298
58431
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58299
58432
|
for (const dir of possibleSrcDirs) {
|
|
58300
|
-
const dirPath =
|
|
58301
|
-
if (
|
|
58433
|
+
const dirPath = path46.join(workingDir, dir);
|
|
58434
|
+
if (fs33.existsSync(dirPath)) {
|
|
58302
58435
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58303
58436
|
codeLines += lines;
|
|
58304
58437
|
});
|
|
58305
58438
|
}
|
|
58306
58439
|
}
|
|
58307
|
-
const testsDir =
|
|
58308
|
-
if (
|
|
58440
|
+
const testsDir = path46.join(workingDir, "tests");
|
|
58441
|
+
if (fs33.existsSync(testsDir)) {
|
|
58309
58442
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58310
58443
|
testLines += lines;
|
|
58311
58444
|
});
|
|
58312
58445
|
}
|
|
58313
58446
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58314
58447
|
for (const dir of possibleTestDirs) {
|
|
58315
|
-
const dirPath =
|
|
58316
|
-
if (
|
|
58448
|
+
const dirPath = path46.join(workingDir, dir);
|
|
58449
|
+
if (fs33.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58317
58450
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58318
58451
|
testLines += lines;
|
|
58319
58452
|
});
|
|
@@ -58325,9 +58458,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58325
58458
|
}
|
|
58326
58459
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
58327
58460
|
try {
|
|
58328
|
-
const entries =
|
|
58461
|
+
const entries = fs33.readdirSync(dirPath, { withFileTypes: true });
|
|
58329
58462
|
for (const entry of entries) {
|
|
58330
|
-
const fullPath =
|
|
58463
|
+
const fullPath = path46.join(dirPath, entry.name);
|
|
58331
58464
|
if (entry.isDirectory()) {
|
|
58332
58465
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58333
58466
|
continue;
|
|
@@ -58335,7 +58468,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58335
58468
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58336
58469
|
} else if (entry.isFile()) {
|
|
58337
58470
|
const relativePath = fullPath.replace(`${process.cwd()}/`, "");
|
|
58338
|
-
const ext =
|
|
58471
|
+
const ext = path46.extname(entry.name).toLowerCase();
|
|
58339
58472
|
const validExts = [
|
|
58340
58473
|
".ts",
|
|
58341
58474
|
".tsx",
|
|
@@ -58371,7 +58504,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58371
58504
|
continue;
|
|
58372
58505
|
}
|
|
58373
58506
|
try {
|
|
58374
|
-
const content =
|
|
58507
|
+
const content = fs33.readFileSync(fullPath, "utf-8");
|
|
58375
58508
|
const lines = countCodeLines(content);
|
|
58376
58509
|
callback(lines);
|
|
58377
58510
|
} catch {}
|
|
@@ -58585,8 +58718,8 @@ async function qualityBudget(input, directory) {
|
|
|
58585
58718
|
init_dist();
|
|
58586
58719
|
init_manager();
|
|
58587
58720
|
init_detector();
|
|
58588
|
-
import * as
|
|
58589
|
-
import * as
|
|
58721
|
+
import * as fs34 from "fs";
|
|
58722
|
+
import * as path47 from "path";
|
|
58590
58723
|
import { extname as extname9 } from "path";
|
|
58591
58724
|
|
|
58592
58725
|
// src/sast/rules/c.ts
|
|
@@ -59270,7 +59403,7 @@ function executeRulesSync(filePath, content, language) {
|
|
|
59270
59403
|
}
|
|
59271
59404
|
|
|
59272
59405
|
// src/sast/semgrep.ts
|
|
59273
|
-
import { execFile as execFile2, execFileSync as execFileSync2, spawn } from "child_process";
|
|
59406
|
+
import { execFile as execFile2, execFileSync as execFileSync2, spawn as spawn2 } from "child_process";
|
|
59274
59407
|
import { promisify as promisify2 } from "util";
|
|
59275
59408
|
var _execFileAsync = promisify2(execFile2);
|
|
59276
59409
|
var semgrepAvailableCache = null;
|
|
@@ -59335,7 +59468,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
59335
59468
|
}
|
|
59336
59469
|
async function executeWithTimeout(command, args2, options) {
|
|
59337
59470
|
return new Promise((resolve15) => {
|
|
59338
|
-
const child =
|
|
59471
|
+
const child = spawn2(command, args2, {
|
|
59339
59472
|
shell: false,
|
|
59340
59473
|
cwd: options.cwd
|
|
59341
59474
|
});
|
|
@@ -59453,17 +59586,17 @@ var SEVERITY_ORDER = {
|
|
|
59453
59586
|
};
|
|
59454
59587
|
function shouldSkipFile(filePath) {
|
|
59455
59588
|
try {
|
|
59456
|
-
const stats =
|
|
59589
|
+
const stats = fs34.statSync(filePath);
|
|
59457
59590
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
59458
59591
|
return { skip: true, reason: "file too large" };
|
|
59459
59592
|
}
|
|
59460
59593
|
if (stats.size === 0) {
|
|
59461
59594
|
return { skip: true, reason: "empty file" };
|
|
59462
59595
|
}
|
|
59463
|
-
const fd =
|
|
59596
|
+
const fd = fs34.openSync(filePath, "r");
|
|
59464
59597
|
const buffer = Buffer.alloc(8192);
|
|
59465
|
-
const bytesRead =
|
|
59466
|
-
|
|
59598
|
+
const bytesRead = fs34.readSync(fd, buffer, 0, 8192, 0);
|
|
59599
|
+
fs34.closeSync(fd);
|
|
59467
59600
|
if (bytesRead > 0) {
|
|
59468
59601
|
let nullCount = 0;
|
|
59469
59602
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -59502,7 +59635,7 @@ function countBySeverity(findings) {
|
|
|
59502
59635
|
}
|
|
59503
59636
|
function scanFileWithTierA(filePath, language) {
|
|
59504
59637
|
try {
|
|
59505
|
-
const content =
|
|
59638
|
+
const content = fs34.readFileSync(filePath, "utf-8");
|
|
59506
59639
|
const findings = executeRulesSync(filePath, content, language);
|
|
59507
59640
|
return findings.map((f) => ({
|
|
59508
59641
|
rule_id: f.rule_id,
|
|
@@ -59549,8 +59682,8 @@ async function sastScan(input, directory, config3) {
|
|
|
59549
59682
|
_filesSkipped++;
|
|
59550
59683
|
continue;
|
|
59551
59684
|
}
|
|
59552
|
-
const resolvedPath =
|
|
59553
|
-
if (!
|
|
59685
|
+
const resolvedPath = path47.isAbsolute(filePath) ? filePath : path47.resolve(directory, filePath);
|
|
59686
|
+
if (!fs34.existsSync(resolvedPath)) {
|
|
59554
59687
|
_filesSkipped++;
|
|
59555
59688
|
continue;
|
|
59556
59689
|
}
|
|
@@ -59748,18 +59881,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
59748
59881
|
let resolved;
|
|
59749
59882
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
59750
59883
|
if (isWinAbs) {
|
|
59751
|
-
resolved =
|
|
59752
|
-
} else if (
|
|
59753
|
-
resolved =
|
|
59884
|
+
resolved = path48.win32.resolve(inputPath);
|
|
59885
|
+
} else if (path48.isAbsolute(inputPath)) {
|
|
59886
|
+
resolved = path48.resolve(inputPath);
|
|
59754
59887
|
} else {
|
|
59755
|
-
resolved =
|
|
59888
|
+
resolved = path48.resolve(baseDir, inputPath);
|
|
59756
59889
|
}
|
|
59757
|
-
const workspaceResolved =
|
|
59890
|
+
const workspaceResolved = path48.resolve(workspaceDir);
|
|
59758
59891
|
let relative5;
|
|
59759
59892
|
if (isWinAbs) {
|
|
59760
|
-
relative5 =
|
|
59893
|
+
relative5 = path48.win32.relative(workspaceResolved, resolved);
|
|
59761
59894
|
} else {
|
|
59762
|
-
relative5 =
|
|
59895
|
+
relative5 = path48.relative(workspaceResolved, resolved);
|
|
59763
59896
|
}
|
|
59764
59897
|
if (relative5.startsWith("..")) {
|
|
59765
59898
|
return "path traversal detected";
|
|
@@ -59820,13 +59953,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
59820
59953
|
}
|
|
59821
59954
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
59822
59955
|
const isWindows = process.platform === "win32";
|
|
59823
|
-
const binDir =
|
|
59956
|
+
const binDir = path48.join(workspaceDir, "node_modules", ".bin");
|
|
59824
59957
|
const validatedFiles = [];
|
|
59825
59958
|
for (const file3 of files) {
|
|
59826
59959
|
if (typeof file3 !== "string") {
|
|
59827
59960
|
continue;
|
|
59828
59961
|
}
|
|
59829
|
-
const resolvedPath =
|
|
59962
|
+
const resolvedPath = path48.resolve(file3);
|
|
59830
59963
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
59831
59964
|
if (validationError) {
|
|
59832
59965
|
continue;
|
|
@@ -59844,10 +59977,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
59844
59977
|
}
|
|
59845
59978
|
let command;
|
|
59846
59979
|
if (linter === "biome") {
|
|
59847
|
-
const biomeBin = isWindows ?
|
|
59980
|
+
const biomeBin = isWindows ? path48.join(binDir, "biome.EXE") : path48.join(binDir, "biome");
|
|
59848
59981
|
command = [biomeBin, "check", ...validatedFiles];
|
|
59849
59982
|
} else {
|
|
59850
|
-
const eslintBin = isWindows ?
|
|
59983
|
+
const eslintBin = isWindows ? path48.join(binDir, "eslint.cmd") : path48.join(binDir, "eslint");
|
|
59851
59984
|
command = [eslintBin, ...validatedFiles];
|
|
59852
59985
|
}
|
|
59853
59986
|
try {
|
|
@@ -59984,7 +60117,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
59984
60117
|
skippedFiles++;
|
|
59985
60118
|
continue;
|
|
59986
60119
|
}
|
|
59987
|
-
const resolvedPath =
|
|
60120
|
+
const resolvedPath = path48.resolve(file3);
|
|
59988
60121
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
59989
60122
|
if (validationError) {
|
|
59990
60123
|
skippedFiles++;
|
|
@@ -60002,14 +60135,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
60002
60135
|
};
|
|
60003
60136
|
}
|
|
60004
60137
|
for (const file3 of validatedFiles) {
|
|
60005
|
-
const ext =
|
|
60138
|
+
const ext = path48.extname(file3).toLowerCase();
|
|
60006
60139
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
60007
60140
|
skippedFiles++;
|
|
60008
60141
|
continue;
|
|
60009
60142
|
}
|
|
60010
60143
|
let stat2;
|
|
60011
60144
|
try {
|
|
60012
|
-
stat2 =
|
|
60145
|
+
stat2 = fs35.statSync(file3);
|
|
60013
60146
|
} catch {
|
|
60014
60147
|
skippedFiles++;
|
|
60015
60148
|
continue;
|
|
@@ -60020,7 +60153,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
60020
60153
|
}
|
|
60021
60154
|
let content;
|
|
60022
60155
|
try {
|
|
60023
|
-
const buffer =
|
|
60156
|
+
const buffer = fs35.readFileSync(file3);
|
|
60024
60157
|
if (buffer.includes(0)) {
|
|
60025
60158
|
skippedFiles++;
|
|
60026
60159
|
continue;
|
|
@@ -60161,7 +60294,7 @@ async function runPreCheckBatch(input, workspaceDir) {
|
|
|
60161
60294
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
60162
60295
|
continue;
|
|
60163
60296
|
}
|
|
60164
|
-
changedFiles.push(
|
|
60297
|
+
changedFiles.push(path48.resolve(directory, file3));
|
|
60165
60298
|
}
|
|
60166
60299
|
if (changedFiles.length === 0) {
|
|
60167
60300
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -60312,7 +60445,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
60312
60445
|
};
|
|
60313
60446
|
return JSON.stringify(errorResult, null, 2);
|
|
60314
60447
|
}
|
|
60315
|
-
const resolvedDirectory =
|
|
60448
|
+
const resolvedDirectory = path48.resolve(typedArgs.directory);
|
|
60316
60449
|
const workspaceAnchor = resolvedDirectory;
|
|
60317
60450
|
const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
|
|
60318
60451
|
if (dirError) {
|
|
@@ -60419,8 +60552,8 @@ ${paginatedContent}`;
|
|
|
60419
60552
|
init_tool();
|
|
60420
60553
|
init_manager2();
|
|
60421
60554
|
init_create_tool();
|
|
60422
|
-
import * as
|
|
60423
|
-
import * as
|
|
60555
|
+
import * as fs36 from "fs";
|
|
60556
|
+
import * as path49 from "path";
|
|
60424
60557
|
function detectPlaceholderContent(args2) {
|
|
60425
60558
|
const issues = [];
|
|
60426
60559
|
const placeholderPattern = /^\[\w[\w\s]*\]$/;
|
|
@@ -60524,19 +60657,19 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
60524
60657
|
try {
|
|
60525
60658
|
await savePlan(dir, plan);
|
|
60526
60659
|
try {
|
|
60527
|
-
const markerPath =
|
|
60660
|
+
const markerPath = path49.join(dir, ".swarm", ".plan-write-marker");
|
|
60528
60661
|
const marker = JSON.stringify({
|
|
60529
60662
|
source: "save_plan",
|
|
60530
60663
|
timestamp: new Date().toISOString(),
|
|
60531
60664
|
phases_count: plan.phases.length,
|
|
60532
60665
|
tasks_count: tasksCount
|
|
60533
60666
|
});
|
|
60534
|
-
await
|
|
60667
|
+
await fs36.promises.writeFile(markerPath, marker, "utf8");
|
|
60535
60668
|
} catch {}
|
|
60536
60669
|
return {
|
|
60537
60670
|
success: true,
|
|
60538
60671
|
message: "Plan saved successfully",
|
|
60539
|
-
plan_path:
|
|
60672
|
+
plan_path: path49.join(dir, ".swarm", "plan.json"),
|
|
60540
60673
|
phases_count: plan.phases.length,
|
|
60541
60674
|
tasks_count: tasksCount
|
|
60542
60675
|
};
|
|
@@ -60574,8 +60707,8 @@ var save_plan = createSwarmTool({
|
|
|
60574
60707
|
// src/tools/sbom-generate.ts
|
|
60575
60708
|
init_dist();
|
|
60576
60709
|
init_manager();
|
|
60577
|
-
import * as
|
|
60578
|
-
import * as
|
|
60710
|
+
import * as fs37 from "fs";
|
|
60711
|
+
import * as path50 from "path";
|
|
60579
60712
|
|
|
60580
60713
|
// src/sbom/detectors/index.ts
|
|
60581
60714
|
init_utils();
|
|
@@ -61421,9 +61554,9 @@ function findManifestFiles(rootDir) {
|
|
|
61421
61554
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
61422
61555
|
function searchDir(dir) {
|
|
61423
61556
|
try {
|
|
61424
|
-
const entries =
|
|
61557
|
+
const entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
61425
61558
|
for (const entry of entries) {
|
|
61426
|
-
const fullPath =
|
|
61559
|
+
const fullPath = path50.join(dir, entry.name);
|
|
61427
61560
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
61428
61561
|
continue;
|
|
61429
61562
|
}
|
|
@@ -61432,7 +61565,7 @@ function findManifestFiles(rootDir) {
|
|
|
61432
61565
|
} else if (entry.isFile()) {
|
|
61433
61566
|
for (const pattern of patterns) {
|
|
61434
61567
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
61435
|
-
manifestFiles.push(
|
|
61568
|
+
manifestFiles.push(path50.relative(rootDir, fullPath));
|
|
61436
61569
|
break;
|
|
61437
61570
|
}
|
|
61438
61571
|
}
|
|
@@ -61448,13 +61581,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
61448
61581
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
61449
61582
|
for (const dir of directories) {
|
|
61450
61583
|
try {
|
|
61451
|
-
const entries =
|
|
61584
|
+
const entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
61452
61585
|
for (const entry of entries) {
|
|
61453
|
-
const fullPath =
|
|
61586
|
+
const fullPath = path50.join(dir, entry.name);
|
|
61454
61587
|
if (entry.isFile()) {
|
|
61455
61588
|
for (const pattern of patterns) {
|
|
61456
61589
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
61457
|
-
found.push(
|
|
61590
|
+
found.push(path50.relative(workingDir, fullPath));
|
|
61458
61591
|
break;
|
|
61459
61592
|
}
|
|
61460
61593
|
}
|
|
@@ -61467,11 +61600,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
61467
61600
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
61468
61601
|
const dirs = new Set;
|
|
61469
61602
|
for (const file3 of changedFiles) {
|
|
61470
|
-
let currentDir =
|
|
61603
|
+
let currentDir = path50.dirname(file3);
|
|
61471
61604
|
while (true) {
|
|
61472
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
61473
|
-
dirs.add(
|
|
61474
|
-
const parent =
|
|
61605
|
+
if (currentDir && currentDir !== "." && currentDir !== path50.sep) {
|
|
61606
|
+
dirs.add(path50.join(workingDir, currentDir));
|
|
61607
|
+
const parent = path50.dirname(currentDir);
|
|
61475
61608
|
if (parent === currentDir)
|
|
61476
61609
|
break;
|
|
61477
61610
|
currentDir = parent;
|
|
@@ -61485,7 +61618,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
61485
61618
|
}
|
|
61486
61619
|
function ensureOutputDir(outputDir) {
|
|
61487
61620
|
try {
|
|
61488
|
-
|
|
61621
|
+
fs37.mkdirSync(outputDir, { recursive: true });
|
|
61489
61622
|
} catch (error93) {
|
|
61490
61623
|
if (!error93 || error93.code !== "EEXIST") {
|
|
61491
61624
|
throw error93;
|
|
@@ -61555,7 +61688,7 @@ var sbom_generate = createSwarmTool({
|
|
|
61555
61688
|
const changedFiles = obj.changed_files;
|
|
61556
61689
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
61557
61690
|
const workingDir = directory;
|
|
61558
|
-
const outputDir =
|
|
61691
|
+
const outputDir = path50.isAbsolute(relativeOutputDir) ? relativeOutputDir : path50.join(workingDir, relativeOutputDir);
|
|
61559
61692
|
let manifestFiles = [];
|
|
61560
61693
|
if (scope === "all") {
|
|
61561
61694
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -61578,11 +61711,11 @@ var sbom_generate = createSwarmTool({
|
|
|
61578
61711
|
const processedFiles = [];
|
|
61579
61712
|
for (const manifestFile of manifestFiles) {
|
|
61580
61713
|
try {
|
|
61581
|
-
const fullPath =
|
|
61582
|
-
if (!
|
|
61714
|
+
const fullPath = path50.isAbsolute(manifestFile) ? manifestFile : path50.join(workingDir, manifestFile);
|
|
61715
|
+
if (!fs37.existsSync(fullPath)) {
|
|
61583
61716
|
continue;
|
|
61584
61717
|
}
|
|
61585
|
-
const content =
|
|
61718
|
+
const content = fs37.readFileSync(fullPath, "utf-8");
|
|
61586
61719
|
const components = detectComponents(manifestFile, content);
|
|
61587
61720
|
processedFiles.push(manifestFile);
|
|
61588
61721
|
if (components.length > 0) {
|
|
@@ -61595,8 +61728,8 @@ var sbom_generate = createSwarmTool({
|
|
|
61595
61728
|
const bom = generateCycloneDX(allComponents);
|
|
61596
61729
|
const bomJson = serializeCycloneDX(bom);
|
|
61597
61730
|
const filename = generateSbomFilename();
|
|
61598
|
-
const outputPath =
|
|
61599
|
-
|
|
61731
|
+
const outputPath = path50.join(outputDir, filename);
|
|
61732
|
+
fs37.writeFileSync(outputPath, bomJson, "utf-8");
|
|
61600
61733
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
61601
61734
|
try {
|
|
61602
61735
|
const timestamp = new Date().toISOString();
|
|
@@ -61638,8 +61771,8 @@ var sbom_generate = createSwarmTool({
|
|
|
61638
61771
|
// src/tools/schema-drift.ts
|
|
61639
61772
|
init_dist();
|
|
61640
61773
|
init_create_tool();
|
|
61641
|
-
import * as
|
|
61642
|
-
import * as
|
|
61774
|
+
import * as fs38 from "fs";
|
|
61775
|
+
import * as path51 from "path";
|
|
61643
61776
|
var SPEC_CANDIDATES = [
|
|
61644
61777
|
"openapi.json",
|
|
61645
61778
|
"openapi.yaml",
|
|
@@ -61671,28 +61804,28 @@ function normalizePath2(p) {
|
|
|
61671
61804
|
}
|
|
61672
61805
|
function discoverSpecFile(cwd, specFileArg) {
|
|
61673
61806
|
if (specFileArg) {
|
|
61674
|
-
const resolvedPath =
|
|
61675
|
-
const normalizedCwd = cwd.endsWith(
|
|
61807
|
+
const resolvedPath = path51.resolve(cwd, specFileArg);
|
|
61808
|
+
const normalizedCwd = cwd.endsWith(path51.sep) ? cwd : cwd + path51.sep;
|
|
61676
61809
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
61677
61810
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
61678
61811
|
}
|
|
61679
|
-
const ext =
|
|
61812
|
+
const ext = path51.extname(resolvedPath).toLowerCase();
|
|
61680
61813
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
61681
61814
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
61682
61815
|
}
|
|
61683
|
-
const stats =
|
|
61816
|
+
const stats = fs38.statSync(resolvedPath);
|
|
61684
61817
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
61685
61818
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
61686
61819
|
}
|
|
61687
|
-
if (!
|
|
61820
|
+
if (!fs38.existsSync(resolvedPath)) {
|
|
61688
61821
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
61689
61822
|
}
|
|
61690
61823
|
return resolvedPath;
|
|
61691
61824
|
}
|
|
61692
61825
|
for (const candidate of SPEC_CANDIDATES) {
|
|
61693
|
-
const candidatePath =
|
|
61694
|
-
if (
|
|
61695
|
-
const stats =
|
|
61826
|
+
const candidatePath = path51.resolve(cwd, candidate);
|
|
61827
|
+
if (fs38.existsSync(candidatePath)) {
|
|
61828
|
+
const stats = fs38.statSync(candidatePath);
|
|
61696
61829
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
61697
61830
|
return candidatePath;
|
|
61698
61831
|
}
|
|
@@ -61701,8 +61834,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
61701
61834
|
return null;
|
|
61702
61835
|
}
|
|
61703
61836
|
function parseSpec(specFile) {
|
|
61704
|
-
const content =
|
|
61705
|
-
const ext =
|
|
61837
|
+
const content = fs38.readFileSync(specFile, "utf-8");
|
|
61838
|
+
const ext = path51.extname(specFile).toLowerCase();
|
|
61706
61839
|
if (ext === ".json") {
|
|
61707
61840
|
return parseJsonSpec(content);
|
|
61708
61841
|
}
|
|
@@ -61773,12 +61906,12 @@ function extractRoutes(cwd) {
|
|
|
61773
61906
|
function walkDir(dir) {
|
|
61774
61907
|
let entries;
|
|
61775
61908
|
try {
|
|
61776
|
-
entries =
|
|
61909
|
+
entries = fs38.readdirSync(dir, { withFileTypes: true });
|
|
61777
61910
|
} catch {
|
|
61778
61911
|
return;
|
|
61779
61912
|
}
|
|
61780
61913
|
for (const entry of entries) {
|
|
61781
|
-
const fullPath =
|
|
61914
|
+
const fullPath = path51.join(dir, entry.name);
|
|
61782
61915
|
if (entry.isSymbolicLink()) {
|
|
61783
61916
|
continue;
|
|
61784
61917
|
}
|
|
@@ -61788,7 +61921,7 @@ function extractRoutes(cwd) {
|
|
|
61788
61921
|
}
|
|
61789
61922
|
walkDir(fullPath);
|
|
61790
61923
|
} else if (entry.isFile()) {
|
|
61791
|
-
const ext =
|
|
61924
|
+
const ext = path51.extname(entry.name).toLowerCase();
|
|
61792
61925
|
const baseName = entry.name.toLowerCase();
|
|
61793
61926
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
61794
61927
|
continue;
|
|
@@ -61806,7 +61939,7 @@ function extractRoutes(cwd) {
|
|
|
61806
61939
|
}
|
|
61807
61940
|
function extractRoutesFromFile(filePath) {
|
|
61808
61941
|
const routes = [];
|
|
61809
|
-
const content =
|
|
61942
|
+
const content = fs38.readFileSync(filePath, "utf-8");
|
|
61810
61943
|
const lines = content.split(/\r?\n/);
|
|
61811
61944
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
61812
61945
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -61957,8 +62090,8 @@ init_secretscan();
|
|
|
61957
62090
|
// src/tools/symbols.ts
|
|
61958
62091
|
init_tool();
|
|
61959
62092
|
init_create_tool();
|
|
61960
|
-
import * as
|
|
61961
|
-
import * as
|
|
62093
|
+
import * as fs39 from "fs";
|
|
62094
|
+
import * as path52 from "path";
|
|
61962
62095
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
61963
62096
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
61964
62097
|
function containsControlCharacters(str) {
|
|
@@ -61987,11 +62120,11 @@ function containsWindowsAttacks(str) {
|
|
|
61987
62120
|
}
|
|
61988
62121
|
function isPathInWorkspace(filePath, workspace) {
|
|
61989
62122
|
try {
|
|
61990
|
-
const resolvedPath =
|
|
61991
|
-
const realWorkspace =
|
|
61992
|
-
const realResolvedPath =
|
|
61993
|
-
const relativePath =
|
|
61994
|
-
if (relativePath.startsWith("..") ||
|
|
62123
|
+
const resolvedPath = path52.resolve(workspace, filePath);
|
|
62124
|
+
const realWorkspace = fs39.realpathSync(workspace);
|
|
62125
|
+
const realResolvedPath = fs39.realpathSync(resolvedPath);
|
|
62126
|
+
const relativePath = path52.relative(realWorkspace, realResolvedPath);
|
|
62127
|
+
if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
|
|
61995
62128
|
return false;
|
|
61996
62129
|
}
|
|
61997
62130
|
return true;
|
|
@@ -62003,17 +62136,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
62003
62136
|
return isPathInWorkspace(filePath, workspace);
|
|
62004
62137
|
}
|
|
62005
62138
|
function extractTSSymbols(filePath, cwd) {
|
|
62006
|
-
const fullPath =
|
|
62139
|
+
const fullPath = path52.join(cwd, filePath);
|
|
62007
62140
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
62008
62141
|
return [];
|
|
62009
62142
|
}
|
|
62010
62143
|
let content;
|
|
62011
62144
|
try {
|
|
62012
|
-
const stats =
|
|
62145
|
+
const stats = fs39.statSync(fullPath);
|
|
62013
62146
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
62014
62147
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
62015
62148
|
}
|
|
62016
|
-
content =
|
|
62149
|
+
content = fs39.readFileSync(fullPath, "utf-8");
|
|
62017
62150
|
} catch {
|
|
62018
62151
|
return [];
|
|
62019
62152
|
}
|
|
@@ -62155,17 +62288,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
62155
62288
|
});
|
|
62156
62289
|
}
|
|
62157
62290
|
function extractPythonSymbols(filePath, cwd) {
|
|
62158
|
-
const fullPath =
|
|
62291
|
+
const fullPath = path52.join(cwd, filePath);
|
|
62159
62292
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
62160
62293
|
return [];
|
|
62161
62294
|
}
|
|
62162
62295
|
let content;
|
|
62163
62296
|
try {
|
|
62164
|
-
const stats =
|
|
62297
|
+
const stats = fs39.statSync(fullPath);
|
|
62165
62298
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
62166
62299
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
62167
62300
|
}
|
|
62168
|
-
content =
|
|
62301
|
+
content = fs39.readFileSync(fullPath, "utf-8");
|
|
62169
62302
|
} catch {
|
|
62170
62303
|
return [];
|
|
62171
62304
|
}
|
|
@@ -62238,7 +62371,7 @@ var symbols = createSwarmTool({
|
|
|
62238
62371
|
}, null, 2);
|
|
62239
62372
|
}
|
|
62240
62373
|
const cwd = directory;
|
|
62241
|
-
const ext =
|
|
62374
|
+
const ext = path52.extname(file3);
|
|
62242
62375
|
if (containsControlCharacters(file3)) {
|
|
62243
62376
|
return JSON.stringify({
|
|
62244
62377
|
file: file3,
|
|
@@ -62309,8 +62442,8 @@ init_test_runner();
|
|
|
62309
62442
|
init_dist();
|
|
62310
62443
|
init_utils();
|
|
62311
62444
|
init_create_tool();
|
|
62312
|
-
import * as
|
|
62313
|
-
import * as
|
|
62445
|
+
import * as fs40 from "fs";
|
|
62446
|
+
import * as path53 from "path";
|
|
62314
62447
|
var MAX_TEXT_LENGTH = 200;
|
|
62315
62448
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
62316
62449
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -62381,9 +62514,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
62381
62514
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
62382
62515
|
}
|
|
62383
62516
|
try {
|
|
62384
|
-
const resolvedPath =
|
|
62385
|
-
const normalizedCwd =
|
|
62386
|
-
const normalizedResolved =
|
|
62517
|
+
const resolvedPath = path53.resolve(paths);
|
|
62518
|
+
const normalizedCwd = path53.resolve(cwd);
|
|
62519
|
+
const normalizedResolved = path53.resolve(resolvedPath);
|
|
62387
62520
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
62388
62521
|
return {
|
|
62389
62522
|
error: "paths must be within the current working directory",
|
|
@@ -62399,13 +62532,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
62399
62532
|
}
|
|
62400
62533
|
}
|
|
62401
62534
|
function isSupportedExtension(filePath) {
|
|
62402
|
-
const ext =
|
|
62535
|
+
const ext = path53.extname(filePath).toLowerCase();
|
|
62403
62536
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
62404
62537
|
}
|
|
62405
62538
|
function findSourceFiles2(dir, files = []) {
|
|
62406
62539
|
let entries;
|
|
62407
62540
|
try {
|
|
62408
|
-
entries =
|
|
62541
|
+
entries = fs40.readdirSync(dir);
|
|
62409
62542
|
} catch {
|
|
62410
62543
|
return files;
|
|
62411
62544
|
}
|
|
@@ -62414,10 +62547,10 @@ function findSourceFiles2(dir, files = []) {
|
|
|
62414
62547
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
62415
62548
|
continue;
|
|
62416
62549
|
}
|
|
62417
|
-
const fullPath =
|
|
62550
|
+
const fullPath = path53.join(dir, entry);
|
|
62418
62551
|
let stat2;
|
|
62419
62552
|
try {
|
|
62420
|
-
stat2 =
|
|
62553
|
+
stat2 = fs40.statSync(fullPath);
|
|
62421
62554
|
} catch {
|
|
62422
62555
|
continue;
|
|
62423
62556
|
}
|
|
@@ -62510,7 +62643,7 @@ var todo_extract = createSwarmTool({
|
|
|
62510
62643
|
return JSON.stringify(errorResult, null, 2);
|
|
62511
62644
|
}
|
|
62512
62645
|
const scanPath = resolvedPath;
|
|
62513
|
-
if (!
|
|
62646
|
+
if (!fs40.existsSync(scanPath)) {
|
|
62514
62647
|
const errorResult = {
|
|
62515
62648
|
error: `path not found: ${pathsInput}`,
|
|
62516
62649
|
total: 0,
|
|
@@ -62520,13 +62653,13 @@ var todo_extract = createSwarmTool({
|
|
|
62520
62653
|
return JSON.stringify(errorResult, null, 2);
|
|
62521
62654
|
}
|
|
62522
62655
|
const filesToScan = [];
|
|
62523
|
-
const stat2 =
|
|
62656
|
+
const stat2 = fs40.statSync(scanPath);
|
|
62524
62657
|
if (stat2.isFile()) {
|
|
62525
62658
|
if (isSupportedExtension(scanPath)) {
|
|
62526
62659
|
filesToScan.push(scanPath);
|
|
62527
62660
|
} else {
|
|
62528
62661
|
const errorResult = {
|
|
62529
|
-
error: `unsupported file extension: ${
|
|
62662
|
+
error: `unsupported file extension: ${path53.extname(scanPath)}`,
|
|
62530
62663
|
total: 0,
|
|
62531
62664
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
62532
62665
|
entries: []
|
|
@@ -62539,11 +62672,11 @@ var todo_extract = createSwarmTool({
|
|
|
62539
62672
|
const allEntries = [];
|
|
62540
62673
|
for (const filePath of filesToScan) {
|
|
62541
62674
|
try {
|
|
62542
|
-
const fileStat =
|
|
62675
|
+
const fileStat = fs40.statSync(filePath);
|
|
62543
62676
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
62544
62677
|
continue;
|
|
62545
62678
|
}
|
|
62546
|
-
const content =
|
|
62679
|
+
const content = fs40.readFileSync(filePath, "utf-8");
|
|
62547
62680
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
62548
62681
|
allEntries.push(...entries);
|
|
62549
62682
|
} catch {}
|
|
@@ -62571,18 +62704,18 @@ var todo_extract = createSwarmTool({
|
|
|
62571
62704
|
// src/tools/update-task-status.ts
|
|
62572
62705
|
init_tool();
|
|
62573
62706
|
init_schema();
|
|
62574
|
-
import * as
|
|
62575
|
-
import * as
|
|
62707
|
+
import * as fs42 from "fs";
|
|
62708
|
+
import * as path55 from "path";
|
|
62576
62709
|
|
|
62577
62710
|
// src/hooks/diff-scope.ts
|
|
62578
|
-
import * as
|
|
62579
|
-
import * as
|
|
62711
|
+
import * as fs41 from "fs";
|
|
62712
|
+
import * as path54 from "path";
|
|
62580
62713
|
function getDeclaredScope(taskId, directory) {
|
|
62581
62714
|
try {
|
|
62582
|
-
const planPath =
|
|
62583
|
-
if (!
|
|
62715
|
+
const planPath = path54.join(directory, ".swarm", "plan.json");
|
|
62716
|
+
if (!fs41.existsSync(planPath))
|
|
62584
62717
|
return null;
|
|
62585
|
-
const raw =
|
|
62718
|
+
const raw = fs41.readFileSync(planPath, "utf-8");
|
|
62586
62719
|
const plan = JSON.parse(raw);
|
|
62587
62720
|
for (const phase of plan.phases ?? []) {
|
|
62588
62721
|
for (const task of phase.tasks ?? []) {
|
|
@@ -62694,7 +62827,7 @@ var TIER_3_PATTERNS = [
|
|
|
62694
62827
|
];
|
|
62695
62828
|
function matchesTier3Pattern(files) {
|
|
62696
62829
|
for (const file3 of files) {
|
|
62697
|
-
const fileName =
|
|
62830
|
+
const fileName = path55.basename(file3);
|
|
62698
62831
|
for (const pattern of TIER_3_PATTERNS) {
|
|
62699
62832
|
if (pattern.test(fileName)) {
|
|
62700
62833
|
return true;
|
|
@@ -62716,8 +62849,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
62716
62849
|
if (hasActiveTurboMode2()) {
|
|
62717
62850
|
const resolvedDir2 = workingDirectory ?? process.cwd();
|
|
62718
62851
|
try {
|
|
62719
|
-
const planPath =
|
|
62720
|
-
const planRaw =
|
|
62852
|
+
const planPath = path55.join(resolvedDir2, ".swarm", "plan.json");
|
|
62853
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
62721
62854
|
const plan = JSON.parse(planRaw);
|
|
62722
62855
|
for (const planPhase of plan.phases ?? []) {
|
|
62723
62856
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -62736,8 +62869,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
62736
62869
|
}
|
|
62737
62870
|
const resolvedDir = workingDirectory ?? process.cwd();
|
|
62738
62871
|
try {
|
|
62739
|
-
const evidencePath =
|
|
62740
|
-
const raw =
|
|
62872
|
+
const evidencePath = path55.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
|
|
62873
|
+
const raw = fs42.readFileSync(evidencePath, "utf-8");
|
|
62741
62874
|
const evidence = JSON.parse(raw);
|
|
62742
62875
|
if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
|
|
62743
62876
|
const allGatesMet = evidence.required_gates.every((gate) => evidence.gates[gate] != null);
|
|
@@ -62777,8 +62910,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
62777
62910
|
}
|
|
62778
62911
|
try {
|
|
62779
62912
|
const resolvedDir2 = workingDirectory ?? process.cwd();
|
|
62780
|
-
const planPath =
|
|
62781
|
-
const planRaw =
|
|
62913
|
+
const planPath = path55.join(resolvedDir2, ".swarm", "plan.json");
|
|
62914
|
+
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
62782
62915
|
const plan = JSON.parse(planRaw);
|
|
62783
62916
|
for (const planPhase of plan.phases ?? []) {
|
|
62784
62917
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -62959,8 +63092,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
62959
63092
|
};
|
|
62960
63093
|
}
|
|
62961
63094
|
}
|
|
62962
|
-
normalizedDir =
|
|
62963
|
-
const pathParts = normalizedDir.split(
|
|
63095
|
+
normalizedDir = path55.normalize(args2.working_directory);
|
|
63096
|
+
const pathParts = normalizedDir.split(path55.sep);
|
|
62964
63097
|
if (pathParts.includes("..")) {
|
|
62965
63098
|
return {
|
|
62966
63099
|
success: false,
|
|
@@ -62970,11 +63103,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
62970
63103
|
]
|
|
62971
63104
|
};
|
|
62972
63105
|
}
|
|
62973
|
-
const resolvedDir =
|
|
63106
|
+
const resolvedDir = path55.resolve(normalizedDir);
|
|
62974
63107
|
try {
|
|
62975
|
-
const realPath =
|
|
62976
|
-
const planPath =
|
|
62977
|
-
if (!
|
|
63108
|
+
const realPath = fs42.realpathSync(resolvedDir);
|
|
63109
|
+
const planPath = path55.join(realPath, ".swarm", "plan.json");
|
|
63110
|
+
if (!fs42.existsSync(planPath)) {
|
|
62978
63111
|
return {
|
|
62979
63112
|
success: false,
|
|
62980
63113
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -63168,7 +63301,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63168
63301
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
63169
63302
|
preflightTriggerManager = new PTM(automationConfig);
|
|
63170
63303
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
63171
|
-
const swarmDir =
|
|
63304
|
+
const swarmDir = path56.resolve(ctx.directory, ".swarm");
|
|
63172
63305
|
statusArtifact = new ASA(swarmDir);
|
|
63173
63306
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
63174
63307
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|