opencode-swarm 7.58.1 → 7.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/agent-output-schema.d.ts +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/config/constants.d.ts +1 -1
- package/dist/config/schema.d.ts +42 -0
- package/dist/index.js +963 -314
- package/dist/memory/schema.d.ts +1 -1
- package/dist/tools/lean-turbo-run-phase.d.ts +2 -1
- package/dist/turbo/lean/index.d.ts +4 -1
- package/dist/turbo/lean/merge-back.d.ts +180 -0
- package/dist/turbo/lean/runner.d.ts +47 -1
- package/dist/turbo/lean/state.d.ts +10 -0
- package/dist/turbo/lean/worktree.d.ts +194 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var package_default;
|
|
|
69
69
|
var init_package = __esm(() => {
|
|
70
70
|
package_default = {
|
|
71
71
|
name: "opencode-swarm",
|
|
72
|
-
version: "7.
|
|
72
|
+
version: "7.59.0",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -1044,7 +1044,9 @@ var init_constants = __esm(() => {
|
|
|
1044
1044
|
phase_critic: true,
|
|
1045
1045
|
integrated_diff_required: true,
|
|
1046
1046
|
allow_docs_only_without_reviewer: false,
|
|
1047
|
-
worktree_isolation: false
|
|
1047
|
+
worktree_isolation: false,
|
|
1048
|
+
merge_strategy: "merge",
|
|
1049
|
+
worktree_dir: undefined
|
|
1048
1050
|
};
|
|
1049
1051
|
});
|
|
1050
1052
|
|
|
@@ -15917,9 +15919,9 @@ var init_schema = __esm(() => {
|
|
|
15917
15919
|
phase_critic: exports_external.boolean().default(true),
|
|
15918
15920
|
integrated_diff_required: exports_external.boolean().default(true),
|
|
15919
15921
|
allow_docs_only_without_reviewer: exports_external.boolean().default(false),
|
|
15920
|
-
worktree_isolation: exports_external.boolean().default(false)
|
|
15921
|
-
|
|
15922
|
-
|
|
15922
|
+
worktree_isolation: exports_external.boolean().default(false),
|
|
15923
|
+
merge_strategy: exports_external.enum(["merge", "rebase", "cherry-pick"]).default("merge").optional(),
|
|
15924
|
+
worktree_dir: exports_external.string().optional()
|
|
15923
15925
|
});
|
|
15924
15926
|
StandardTurboConfigSchema = exports_external.object({
|
|
15925
15927
|
strategy: exports_external.literal("standard"),
|
|
@@ -93513,10 +93515,10 @@ var init_curator_drift = __esm(() => {
|
|
|
93513
93515
|
var exports_design_doc_drift = {};
|
|
93514
93516
|
__export(exports_design_doc_drift, {
|
|
93515
93517
|
runDesignDocDriftCheck: () => runDesignDocDriftCheck,
|
|
93516
|
-
_internals: () =>
|
|
93518
|
+
_internals: () => _internals69
|
|
93517
93519
|
});
|
|
93518
93520
|
import * as fs109 from "node:fs";
|
|
93519
|
-
import * as
|
|
93521
|
+
import * as path149 from "node:path";
|
|
93520
93522
|
function mtimeMsOrNull(absPath) {
|
|
93521
93523
|
try {
|
|
93522
93524
|
return fs109.statSync(absPath).mtimeMs;
|
|
@@ -93527,35 +93529,35 @@ function mtimeMsOrNull(absPath) {
|
|
|
93527
93529
|
function resolveAnchorWithin(directory, anchor) {
|
|
93528
93530
|
if (!anchor || typeof anchor !== "string")
|
|
93529
93531
|
return null;
|
|
93530
|
-
const root =
|
|
93531
|
-
const resolved =
|
|
93532
|
-
const rel =
|
|
93533
|
-
if (rel.startsWith("..") ||
|
|
93532
|
+
const root = path149.resolve(directory);
|
|
93533
|
+
const resolved = path149.resolve(root, anchor);
|
|
93534
|
+
const rel = path149.relative(root, resolved);
|
|
93535
|
+
if (rel.startsWith("..") || path149.isAbsolute(rel))
|
|
93534
93536
|
return null;
|
|
93535
93537
|
return resolved;
|
|
93536
93538
|
}
|
|
93537
93539
|
async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
93538
93540
|
try {
|
|
93539
|
-
const root =
|
|
93540
|
-
const outAbs =
|
|
93541
|
-
const outRel =
|
|
93542
|
-
if (outRel.startsWith("..") ||
|
|
93541
|
+
const root = path149.resolve(directory);
|
|
93542
|
+
const outAbs = path149.resolve(root, outDir);
|
|
93543
|
+
const outRel = path149.relative(root, outAbs);
|
|
93544
|
+
if (outRel.startsWith("..") || path149.isAbsolute(outRel)) {
|
|
93543
93545
|
return null;
|
|
93544
93546
|
}
|
|
93545
93547
|
const docMtimes = new Map;
|
|
93546
93548
|
const checkedDocs = [];
|
|
93547
93549
|
const missingDocs = [];
|
|
93548
93550
|
for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
|
|
93549
|
-
const abs =
|
|
93551
|
+
const abs = path149.join(outAbs, relFile);
|
|
93550
93552
|
const mtime = mtimeMsOrNull(abs);
|
|
93551
93553
|
docMtimes.set(docName, mtime);
|
|
93552
93554
|
if (mtime === null) {
|
|
93553
|
-
missingDocs.push(
|
|
93555
|
+
missingDocs.push(path149.join(outDir, relFile));
|
|
93554
93556
|
} else {
|
|
93555
|
-
checkedDocs.push(
|
|
93557
|
+
checkedDocs.push(path149.join(outDir, relFile));
|
|
93556
93558
|
}
|
|
93557
93559
|
}
|
|
93558
|
-
const traceabilityAbs =
|
|
93560
|
+
const traceabilityAbs = path149.join(outAbs, TRACEABILITY_REL);
|
|
93559
93561
|
let registry3 = null;
|
|
93560
93562
|
try {
|
|
93561
93563
|
const stat9 = await fs109.promises.stat(traceabilityAbs);
|
|
@@ -93568,7 +93570,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
93568
93570
|
registry3 = null;
|
|
93569
93571
|
}
|
|
93570
93572
|
const noDocs = checkedDocs.length === 0 || registry3 === null;
|
|
93571
|
-
const specMtime = mtimeMsOrNull(
|
|
93573
|
+
const specMtime = mtimeMsOrNull(path149.join(root, ".swarm", "spec.md"));
|
|
93572
93574
|
const staleSections = [];
|
|
93573
93575
|
if (!noDocs && Array.isArray(registry3?.sections)) {
|
|
93574
93576
|
for (const section of registry3.sections) {
|
|
@@ -93624,7 +93626,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
93624
93626
|
};
|
|
93625
93627
|
const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
|
|
93626
93628
|
const filePath = validateSwarmPath(directory, filename);
|
|
93627
|
-
await fs109.promises.mkdir(
|
|
93629
|
+
await fs109.promises.mkdir(path149.dirname(filePath), { recursive: true });
|
|
93628
93630
|
await fs109.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
93629
93631
|
getGlobalEventBus().publish("curator.docdrift.completed", {
|
|
93630
93632
|
phase,
|
|
@@ -93645,7 +93647,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
|
93645
93647
|
return null;
|
|
93646
93648
|
}
|
|
93647
93649
|
}
|
|
93648
|
-
var DOC_DRIFT_REPORT_PREFIX = "doc-drift-phase-", MAX_TRACEABILITY_BYTES, DESIGN_DOC_FILES, TRACEABILITY_REL,
|
|
93650
|
+
var DOC_DRIFT_REPORT_PREFIX = "doc-drift-phase-", MAX_TRACEABILITY_BYTES, DESIGN_DOC_FILES, TRACEABILITY_REL, _internals69;
|
|
93649
93651
|
var init_design_doc_drift = __esm(() => {
|
|
93650
93652
|
init_event_bus();
|
|
93651
93653
|
init_logger();
|
|
@@ -93655,11 +93657,11 @@ var init_design_doc_drift = __esm(() => {
|
|
|
93655
93657
|
domain: "domain.md",
|
|
93656
93658
|
"technical-spec": "technical-spec.md",
|
|
93657
93659
|
"behavior-spec": "behavior-spec.md",
|
|
93658
|
-
"reference-impl":
|
|
93659
|
-
"idiom-notes":
|
|
93660
|
+
"reference-impl": path149.join("reference", "reference-impl.md"),
|
|
93661
|
+
"idiom-notes": path149.join("reference", "idiom-notes.md")
|
|
93660
93662
|
};
|
|
93661
|
-
TRACEABILITY_REL =
|
|
93662
|
-
|
|
93663
|
+
TRACEABILITY_REL = path149.join("reference", "traceability.json");
|
|
93664
|
+
_internals69 = {
|
|
93663
93665
|
mtimeMsOrNull,
|
|
93664
93666
|
resolveAnchorWithin,
|
|
93665
93667
|
DESIGN_DOC_FILES
|
|
@@ -93670,11 +93672,11 @@ var init_design_doc_drift = __esm(() => {
|
|
|
93670
93672
|
var exports_project_context = {};
|
|
93671
93673
|
__export(exports_project_context, {
|
|
93672
93674
|
buildProjectContext: () => buildProjectContext,
|
|
93673
|
-
_internals: () =>
|
|
93675
|
+
_internals: () => _internals80,
|
|
93674
93676
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
93675
93677
|
});
|
|
93676
93678
|
import * as fs133 from "node:fs";
|
|
93677
|
-
import * as
|
|
93679
|
+
import * as path178 from "node:path";
|
|
93678
93680
|
function detectFileExists2(directory, pattern) {
|
|
93679
93681
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
93680
93682
|
try {
|
|
@@ -93686,7 +93688,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
93686
93688
|
}
|
|
93687
93689
|
}
|
|
93688
93690
|
try {
|
|
93689
|
-
fs133.accessSync(
|
|
93691
|
+
fs133.accessSync(path178.join(directory, pattern));
|
|
93690
93692
|
return true;
|
|
93691
93693
|
} catch {
|
|
93692
93694
|
return false;
|
|
@@ -93695,7 +93697,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
93695
93697
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
93696
93698
|
let pkgRaw;
|
|
93697
93699
|
try {
|
|
93698
|
-
pkgRaw = fs133.readFileSync(
|
|
93700
|
+
pkgRaw = fs133.readFileSync(path178.join(directory, "package.json"), "utf-8");
|
|
93699
93701
|
} catch {
|
|
93700
93702
|
return null;
|
|
93701
93703
|
}
|
|
@@ -93754,7 +93756,7 @@ function selectLintCommand(backend, directory) {
|
|
|
93754
93756
|
return null;
|
|
93755
93757
|
}
|
|
93756
93758
|
async function buildProjectContext(directory) {
|
|
93757
|
-
const backend = await
|
|
93759
|
+
const backend = await _internals80.pickBackend(directory);
|
|
93758
93760
|
if (!backend)
|
|
93759
93761
|
return null;
|
|
93760
93762
|
const ctx = emptyProjectContext();
|
|
@@ -93793,17 +93795,17 @@ async function buildProjectContext(directory) {
|
|
|
93793
93795
|
if (backend.prompts.reviewerChecklist.length > 0) {
|
|
93794
93796
|
ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
|
|
93795
93797
|
}
|
|
93796
|
-
const profiles =
|
|
93798
|
+
const profiles = _internals80.pickedProfiles(directory);
|
|
93797
93799
|
if (profiles.length > 1) {
|
|
93798
93800
|
ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
|
|
93799
93801
|
}
|
|
93800
93802
|
return ctx;
|
|
93801
93803
|
}
|
|
93802
|
-
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300,
|
|
93804
|
+
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals80;
|
|
93803
93805
|
var init_project_context = __esm(() => {
|
|
93804
93806
|
init_dispatch();
|
|
93805
93807
|
init_framework_detector();
|
|
93806
|
-
|
|
93808
|
+
_internals80 = {
|
|
93807
93809
|
pickBackend,
|
|
93808
93810
|
pickedProfiles
|
|
93809
93811
|
};
|
|
@@ -93813,7 +93815,7 @@ var init_project_context = __esm(() => {
|
|
|
93813
93815
|
init_package();
|
|
93814
93816
|
init_agents2();
|
|
93815
93817
|
init_critic();
|
|
93816
|
-
import * as
|
|
93818
|
+
import * as path179 from "node:path";
|
|
93817
93819
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
93818
93820
|
|
|
93819
93821
|
// src/background/index.ts
|
|
@@ -116503,7 +116505,468 @@ init_state2();
|
|
|
116503
116505
|
init_file_locks();
|
|
116504
116506
|
init_manager();
|
|
116505
116507
|
init_state();
|
|
116508
|
+
|
|
116509
|
+
// src/turbo/lean/merge-back.ts
|
|
116510
|
+
init_bun_compat();
|
|
116511
|
+
|
|
116512
|
+
// src/turbo/lean/worktree.ts
|
|
116513
|
+
init_bun_compat();
|
|
116514
|
+
import * as os14 from "node:os";
|
|
116515
|
+
import * as path137 from "node:path";
|
|
116516
|
+
var _internals62 = {
|
|
116517
|
+
bunSpawn,
|
|
116518
|
+
platform: process.platform,
|
|
116519
|
+
sleep: (ms) => new Promise((resolve50) => setTimeout(resolve50, ms)),
|
|
116520
|
+
osTmpdir: () => os14.tmpdir(),
|
|
116521
|
+
getCoreLongPaths: async (directory) => {
|
|
116522
|
+
const result = await runGit(["config", "core.longpaths"], directory);
|
|
116523
|
+
if (result.exitCode !== 0) {
|
|
116524
|
+
return;
|
|
116525
|
+
}
|
|
116526
|
+
const value = result.stdout.trim().toLowerCase();
|
|
116527
|
+
return value === "" ? undefined : value;
|
|
116528
|
+
}
|
|
116529
|
+
};
|
|
116530
|
+
var WORKTREE_TIMEOUT_MS = 30000;
|
|
116531
|
+
var WIN_PATH_BUDGET = 250;
|
|
116532
|
+
async function runGit(args2, cwd, timeoutMs = WORKTREE_TIMEOUT_MS) {
|
|
116533
|
+
const proc = _internals62.bunSpawn(["git", ...args2], {
|
|
116534
|
+
cwd,
|
|
116535
|
+
timeout: timeoutMs,
|
|
116536
|
+
stdin: "ignore",
|
|
116537
|
+
stdout: "pipe",
|
|
116538
|
+
stderr: "pipe",
|
|
116539
|
+
env: { ...process.env, LC_ALL: "C" }
|
|
116540
|
+
});
|
|
116541
|
+
try {
|
|
116542
|
+
const exitCode = await proc.exited;
|
|
116543
|
+
const stdout = await proc.stdout.text();
|
|
116544
|
+
const stderr = await proc.stderr.text();
|
|
116545
|
+
return { exitCode, stdout, stderr };
|
|
116546
|
+
} finally {
|
|
116547
|
+
try {
|
|
116548
|
+
proc.kill();
|
|
116549
|
+
} catch {}
|
|
116550
|
+
}
|
|
116551
|
+
}
|
|
116552
|
+
async function checkPathBudget(worktreeRoot, directory) {
|
|
116553
|
+
if (_internals62.platform !== "win32") {
|
|
116554
|
+
return { ok: true };
|
|
116555
|
+
}
|
|
116556
|
+
let longPaths;
|
|
116557
|
+
try {
|
|
116558
|
+
longPaths = await _internals62.getCoreLongPaths(directory);
|
|
116559
|
+
} catch {}
|
|
116560
|
+
if (longPaths === "true") {
|
|
116561
|
+
return { ok: true };
|
|
116562
|
+
}
|
|
116563
|
+
const proc = _internals62.bunSpawn(["git", "ls-files"], {
|
|
116564
|
+
cwd: directory,
|
|
116565
|
+
timeout: WORKTREE_TIMEOUT_MS,
|
|
116566
|
+
stdin: "ignore",
|
|
116567
|
+
stdout: "pipe",
|
|
116568
|
+
stderr: "ignore",
|
|
116569
|
+
env: { ...process.env, LC_ALL: "C" }
|
|
116570
|
+
});
|
|
116571
|
+
try {
|
|
116572
|
+
const exitCode = await proc.exited;
|
|
116573
|
+
const stdout = await proc.stdout.text();
|
|
116574
|
+
if (exitCode !== 0 || stdout.trim().length === 0) {
|
|
116575
|
+
return { ok: true };
|
|
116576
|
+
}
|
|
116577
|
+
const files = stdout.split(/\r?\n/);
|
|
116578
|
+
let longest = 0;
|
|
116579
|
+
for (const file3 of files) {
|
|
116580
|
+
if (file3.length > longest) {
|
|
116581
|
+
longest = file3.length;
|
|
116582
|
+
}
|
|
116583
|
+
}
|
|
116584
|
+
const totalPathLength = worktreeRoot.length + 1 + longest;
|
|
116585
|
+
if (totalPathLength >= WIN_PATH_BUDGET) {
|
|
116586
|
+
return {
|
|
116587
|
+
ok: false,
|
|
116588
|
+
error: `Total path budget exceeded: worktree root "${worktreeRoot}" (${worktreeRoot.length} chars) + longest file "${files.find((f) => f.length === longest)}" (${longest} chars) = ${totalPathLength} chars (budget: ${WIN_PATH_BUDGET})`,
|
|
116589
|
+
suggestion: "Set config.worktree_dir to a shorter absolute path, or let the auto-shorten feature relocate the worktree to the system temp directory."
|
|
116590
|
+
};
|
|
116591
|
+
}
|
|
116592
|
+
return { ok: true };
|
|
116593
|
+
} finally {
|
|
116594
|
+
try {
|
|
116595
|
+
proc.kill();
|
|
116596
|
+
} catch {}
|
|
116597
|
+
}
|
|
116598
|
+
}
|
|
116599
|
+
function shortenWorktreePath(_directory, sessionId, laneId) {
|
|
116600
|
+
return path137.join(_internals62.osTmpdir(), "swwt", sessionId, laneId);
|
|
116601
|
+
}
|
|
116602
|
+
async function provisionWorktree(directory, laneId, sessionId, config3) {
|
|
116603
|
+
const branchName = `swarm-lane/${sessionId}/${laneId}`;
|
|
116604
|
+
let worktreePath = config3.worktree_dir ? path137.resolve(directory, config3.worktree_dir, sessionId, laneId) : path137.resolve(path137.dirname(directory), ".swarm-worktrees", sessionId, laneId);
|
|
116605
|
+
const budgetResult = await checkPathBudget(worktreePath, directory);
|
|
116606
|
+
if (budgetResult.ok === false) {
|
|
116607
|
+
if (config3.worktree_dir) {
|
|
116608
|
+
console.warn(`[swarm] Path budget warning: ${budgetResult.error} ${budgetResult.suggestion}`);
|
|
116609
|
+
} else {
|
|
116610
|
+
const shortPath = shortenWorktreePath(directory, sessionId, laneId);
|
|
116611
|
+
const shortBudget = await checkPathBudget(shortPath, directory);
|
|
116612
|
+
if (shortBudget.ok === false) {
|
|
116613
|
+
return { error: budgetResult.error };
|
|
116614
|
+
}
|
|
116615
|
+
worktreePath = shortPath;
|
|
116616
|
+
}
|
|
116617
|
+
}
|
|
116618
|
+
const checkResult = await runGit(["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`], directory);
|
|
116619
|
+
if (checkResult.exitCode === 0) {
|
|
116620
|
+
return { error: `Branch already exists: ${branchName}` };
|
|
116621
|
+
}
|
|
116622
|
+
const addResult = await runGit(["worktree", "add", "-b", branchName, worktreePath, "HEAD"], directory);
|
|
116623
|
+
if (addResult.exitCode !== 0) {
|
|
116624
|
+
return {
|
|
116625
|
+
error: `Failed to create worktree: ${addResult.stderr.trim() || addResult.stdout.trim()}`
|
|
116626
|
+
};
|
|
116627
|
+
}
|
|
116628
|
+
return { worktreePath, branchName };
|
|
116629
|
+
}
|
|
116630
|
+
async function removeWorktree(worktreePath, projectRoot) {
|
|
116631
|
+
const isWindows = _internals62.platform === "win32";
|
|
116632
|
+
const MAX_RETRIES = 4;
|
|
116633
|
+
const RETRY_DELAY_MS = 2000;
|
|
116634
|
+
let lastError = "";
|
|
116635
|
+
for (let attempt = 0;attempt < MAX_RETRIES; attempt++) {
|
|
116636
|
+
const result = await runGit(["worktree", "remove", worktreePath], projectRoot);
|
|
116637
|
+
if (result.exitCode === 0) {
|
|
116638
|
+
return { success: true };
|
|
116639
|
+
}
|
|
116640
|
+
lastError = result.stderr.trim() || result.stdout.trim();
|
|
116641
|
+
if (isWindows && (lastError.includes("EBUSY") || lastError.includes("EPERM")) && attempt < MAX_RETRIES - 1) {
|
|
116642
|
+
await _internals62.sleep(RETRY_DELAY_MS);
|
|
116643
|
+
continue;
|
|
116644
|
+
}
|
|
116645
|
+
return { error: lastError };
|
|
116646
|
+
}
|
|
116647
|
+
return { error: lastError };
|
|
116648
|
+
}
|
|
116649
|
+
async function autoCommitDirty(worktreePath) {
|
|
116650
|
+
const COMMIT_MESSAGE = "swarm-lane: auto-commit before cleanup";
|
|
116651
|
+
const addResult = await runGit(["add", "-A"], worktreePath);
|
|
116652
|
+
if (addResult.exitCode !== 0) {
|
|
116653
|
+
return {
|
|
116654
|
+
committed: false,
|
|
116655
|
+
reason: `git add failed: ${addResult.stderr.trim() || addResult.stdout.trim()}`
|
|
116656
|
+
};
|
|
116657
|
+
}
|
|
116658
|
+
const commitResult = await runGit(["commit", "-m", COMMIT_MESSAGE], worktreePath);
|
|
116659
|
+
if (commitResult.exitCode !== 0) {
|
|
116660
|
+
const stderr = commitResult.stderr.trim();
|
|
116661
|
+
const stdout = commitResult.stdout.trim();
|
|
116662
|
+
if (stderr.includes("nothing to commit") || stdout.includes("nothing to commit") || stderr.includes("nothing added to commit")) {
|
|
116663
|
+
return { committed: false, reason: "Nothing to commit" };
|
|
116664
|
+
}
|
|
116665
|
+
return {
|
|
116666
|
+
committed: false,
|
|
116667
|
+
reason: `git commit failed: ${stderr || stdout}`
|
|
116668
|
+
};
|
|
116669
|
+
}
|
|
116670
|
+
return { committed: true, message: COMMIT_MESSAGE };
|
|
116671
|
+
}
|
|
116672
|
+
var SAFE_CLEAN_PATTERNS = [
|
|
116673
|
+
"dist/",
|
|
116674
|
+
"build/",
|
|
116675
|
+
".turbo/",
|
|
116676
|
+
"coverage/",
|
|
116677
|
+
"node_modules/.cache/",
|
|
116678
|
+
".log",
|
|
116679
|
+
".tmp",
|
|
116680
|
+
".o",
|
|
116681
|
+
".pyc",
|
|
116682
|
+
".class"
|
|
116683
|
+
];
|
|
116684
|
+
function isSafeToClean(candidatePath) {
|
|
116685
|
+
const normalized = candidatePath.replace(/\\/g, "/").toLowerCase();
|
|
116686
|
+
return SAFE_CLEAN_PATTERNS.some((pattern) => {
|
|
116687
|
+
const p = pattern.toLowerCase();
|
|
116688
|
+
if (p.endsWith("/")) {
|
|
116689
|
+
return normalized.startsWith(p) || normalized.includes("/" + p);
|
|
116690
|
+
}
|
|
116691
|
+
return normalized.endsWith(p);
|
|
116692
|
+
});
|
|
116693
|
+
}
|
|
116694
|
+
async function cleanUntrackedFiles(worktreePath) {
|
|
116695
|
+
const dryRun = await runGit(["clean", "-fdn"], worktreePath);
|
|
116696
|
+
if (dryRun.exitCode === 0) {
|
|
116697
|
+
const candidates = dryRun.stdout.trim().split(`
|
|
116698
|
+
`).map((line) => {
|
|
116699
|
+
const match = line.match(/^Would remove (.+)$/);
|
|
116700
|
+
return match ? match[1].trim() : "";
|
|
116701
|
+
}).filter((p) => p.length > 0);
|
|
116702
|
+
const unsafePaths = candidates.filter((p) => !isSafeToClean(p));
|
|
116703
|
+
if (unsafePaths.length > 0) {
|
|
116704
|
+
console.warn(`[swarm:cleanUntrackedFiles] Skipping clean — untracked source files detected: ${unsafePaths.join(", ")}`);
|
|
116705
|
+
return {
|
|
116706
|
+
cleaned: false,
|
|
116707
|
+
error: "untracked source files detected — skipping clean to prevent data loss"
|
|
116708
|
+
};
|
|
116709
|
+
}
|
|
116710
|
+
}
|
|
116711
|
+
const result = await runGit(["clean", "-fd"], worktreePath);
|
|
116712
|
+
if (result.exitCode !== 0) {
|
|
116713
|
+
return {
|
|
116714
|
+
cleaned: false,
|
|
116715
|
+
error: result.stderr.trim() || result.stdout.trim()
|
|
116716
|
+
};
|
|
116717
|
+
}
|
|
116718
|
+
return { cleaned: true };
|
|
116719
|
+
}
|
|
116720
|
+
async function assertCleanWorkingTree(directory) {
|
|
116721
|
+
const [statusResult, untrackedResult] = await Promise.all([
|
|
116722
|
+
runGit(["status", "--porcelain"], directory),
|
|
116723
|
+
runGit(["ls-files", "--others", "--exclude-standard"], directory)
|
|
116724
|
+
]);
|
|
116725
|
+
if (statusResult.exitCode !== 0) {
|
|
116726
|
+
return {
|
|
116727
|
+
clean: false,
|
|
116728
|
+
error: `Unable to verify working tree cleanliness: ${statusResult.stderr.trim() || statusResult.stdout.trim()}`
|
|
116729
|
+
};
|
|
116730
|
+
}
|
|
116731
|
+
if (untrackedResult.exitCode !== 0) {
|
|
116732
|
+
return {
|
|
116733
|
+
clean: false,
|
|
116734
|
+
error: `Unable to verify working tree cleanliness: ${untrackedResult.stderr.trim() || untrackedResult.stdout.trim()}`
|
|
116735
|
+
};
|
|
116736
|
+
}
|
|
116737
|
+
const hasChanges = statusResult.stdout.trim().length > 0;
|
|
116738
|
+
const hasUntracked = untrackedResult.stdout.trim().length > 0;
|
|
116739
|
+
if (hasChanges || hasUntracked) {
|
|
116740
|
+
return {
|
|
116741
|
+
clean: false,
|
|
116742
|
+
error: "Working tree has uncommitted changes. Please commit or stash before provisioning worktrees. Run 'git status' for details."
|
|
116743
|
+
};
|
|
116744
|
+
}
|
|
116745
|
+
return { clean: true };
|
|
116746
|
+
}
|
|
116747
|
+
|
|
116748
|
+
// src/turbo/lean/merge-back.ts
|
|
116749
|
+
var _internals63 = {
|
|
116750
|
+
bunSpawn,
|
|
116751
|
+
platform: process.platform,
|
|
116752
|
+
sleep: (ms) => new Promise((resolve50) => setTimeout(resolve50, ms))
|
|
116753
|
+
};
|
|
116754
|
+
var MERGE_TIMEOUT_MS = 30000;
|
|
116755
|
+
async function runGit2(args2, cwd, timeoutMs = MERGE_TIMEOUT_MS) {
|
|
116756
|
+
const proc = _internals63.bunSpawn(["git", ...args2], {
|
|
116757
|
+
cwd,
|
|
116758
|
+
timeout: timeoutMs,
|
|
116759
|
+
stdin: "ignore",
|
|
116760
|
+
stdout: "pipe",
|
|
116761
|
+
stderr: "pipe",
|
|
116762
|
+
env: { ...process.env, LC_ALL: "C" }
|
|
116763
|
+
});
|
|
116764
|
+
try {
|
|
116765
|
+
const exitCode = await proc.exited;
|
|
116766
|
+
const stdout = await proc.stdout.text();
|
|
116767
|
+
const stderr = await proc.stderr.text();
|
|
116768
|
+
return { exitCode, stdout, stderr };
|
|
116769
|
+
} finally {
|
|
116770
|
+
try {
|
|
116771
|
+
proc.kill();
|
|
116772
|
+
} catch {}
|
|
116773
|
+
}
|
|
116774
|
+
}
|
|
116775
|
+
function parseConflictFiles(output) {
|
|
116776
|
+
const files = [];
|
|
116777
|
+
const lines = output.split(`
|
|
116778
|
+
`);
|
|
116779
|
+
for (const line of lines) {
|
|
116780
|
+
const match = line.match(/CONFLICT\b.*(?:Merge conflict in |in )(.+)/);
|
|
116781
|
+
if (match?.[1]) {
|
|
116782
|
+
files.push(match[1].trim());
|
|
116783
|
+
}
|
|
116784
|
+
}
|
|
116785
|
+
return files;
|
|
116786
|
+
}
|
|
116787
|
+
function getMergeStrategy(config3) {
|
|
116788
|
+
return config3.merge_strategy ?? "merge";
|
|
116789
|
+
}
|
|
116790
|
+
async function mergeLaneBranch(primaryDir, branchName, strategy) {
|
|
116791
|
+
let result;
|
|
116792
|
+
switch (strategy) {
|
|
116793
|
+
case "merge":
|
|
116794
|
+
result = await runGit2(["merge", "--no-edit", branchName], primaryDir);
|
|
116795
|
+
break;
|
|
116796
|
+
case "rebase":
|
|
116797
|
+
result = await runGit2(["rebase", branchName], primaryDir);
|
|
116798
|
+
break;
|
|
116799
|
+
case "cherry-pick": {
|
|
116800
|
+
const mergeBaseResult = await runGit2(["merge-base", "HEAD", branchName], primaryDir);
|
|
116801
|
+
if (mergeBaseResult.exitCode === 0 && mergeBaseResult.stdout.trim()) {
|
|
116802
|
+
const mergeBase = mergeBaseResult.stdout.trim();
|
|
116803
|
+
result = await runGit2(["cherry-pick", `${mergeBase}..${branchName}`], primaryDir);
|
|
116804
|
+
} else {
|
|
116805
|
+
console.warn("[lean-turbo] mergeLaneBranch: git merge-base failed for cherry-pick; falling back to tip-only cherry-pick");
|
|
116806
|
+
result = await runGit2(["cherry-pick", branchName], primaryDir);
|
|
116807
|
+
}
|
|
116808
|
+
break;
|
|
116809
|
+
}
|
|
116810
|
+
}
|
|
116811
|
+
if (result.exitCode === 0) {
|
|
116812
|
+
return { merged: true, strategy };
|
|
116813
|
+
}
|
|
116814
|
+
const combinedOutput = `${result.stderr}
|
|
116815
|
+
${result.stdout}`;
|
|
116816
|
+
const hasConflict = /CONFLICT/i.test(combinedOutput) || /conflict/i.test(combinedOutput);
|
|
116817
|
+
if (hasConflict) {
|
|
116818
|
+
const files = parseConflictFiles(combinedOutput);
|
|
116819
|
+
const abortArgs = strategy === "rebase" ? ["rebase", "--abort"] : strategy === "cherry-pick" ? ["cherry-pick", "--abort"] : ["merge", "--abort"];
|
|
116820
|
+
await runGit2(abortArgs, primaryDir);
|
|
116821
|
+
return {
|
|
116822
|
+
conflict: true,
|
|
116823
|
+
files,
|
|
116824
|
+
message: result.stderr.trim()
|
|
116825
|
+
};
|
|
116826
|
+
}
|
|
116827
|
+
return {
|
|
116828
|
+
error: result.stderr.trim() || result.stdout.trim()
|
|
116829
|
+
};
|
|
116830
|
+
}
|
|
116831
|
+
async function postMergeCleanup(directory, branchName) {
|
|
116832
|
+
const deleteResult = await runGit2(["branch", "-D", branchName], directory);
|
|
116833
|
+
const deleteOk = deleteResult.exitCode === 0;
|
|
116834
|
+
const pruneResult = await runGit2(["worktree", "prune"], directory);
|
|
116835
|
+
const pruneOk = pruneResult.exitCode === 0;
|
|
116836
|
+
if (deleteOk && pruneOk) {
|
|
116837
|
+
return { cleaned: true };
|
|
116838
|
+
}
|
|
116839
|
+
if (!deleteOk && pruneOk) {
|
|
116840
|
+
return {
|
|
116841
|
+
error: `Branch delete failed: ${deleteResult.stderr.trim() || deleteResult.stdout.trim()}`,
|
|
116842
|
+
partial: true
|
|
116843
|
+
};
|
|
116844
|
+
}
|
|
116845
|
+
return {
|
|
116846
|
+
error: deleteOk ? `Worktree prune failed: ${pruneResult.stderr.trim() || pruneResult.stdout.trim()}` : `Branch delete failed: ${deleteResult.stderr.trim() || deleteResult.stdout.trim()}; worktree prune failed: ${pruneResult.stderr.trim() || pruneResult.stdout.trim()}`
|
|
116847
|
+
};
|
|
116848
|
+
}
|
|
116849
|
+
async function attemptMergeBackFromDirty(worktreePath, branchName, primaryDir, strategy) {
|
|
116850
|
+
let autoCommitted = false;
|
|
116851
|
+
let cleaned = false;
|
|
116852
|
+
let autoCommitFailed = false;
|
|
116853
|
+
let cleanFailed = false;
|
|
116854
|
+
const commitResult = await autoCommitDirty(worktreePath);
|
|
116855
|
+
if (commitResult.committed) {
|
|
116856
|
+
autoCommitted = true;
|
|
116857
|
+
} else if (commitResult.reason !== "Nothing to commit") {
|
|
116858
|
+
autoCommitFailed = true;
|
|
116859
|
+
console.warn(`[lean-turbo] attemptMergeBackFromDirty: auto-commit failed for worktree "${worktreePath}" branch "${branchName}": ${commitResult.reason}`);
|
|
116860
|
+
}
|
|
116861
|
+
const cleanResult = await cleanUntrackedFiles(worktreePath);
|
|
116862
|
+
if (cleanResult.cleaned) {
|
|
116863
|
+
cleaned = true;
|
|
116864
|
+
} else {
|
|
116865
|
+
cleanFailed = true;
|
|
116866
|
+
console.warn(`[lean-turbo] attemptMergeBackFromDirty: clean untracked failed for worktree "${worktreePath}" branch "${branchName}": ${cleanResult.error}`);
|
|
116867
|
+
}
|
|
116868
|
+
if (autoCommitFailed && cleanFailed) {
|
|
116869
|
+
return {
|
|
116870
|
+
failed: true,
|
|
116871
|
+
stage: "cleanup",
|
|
116872
|
+
message: "Auto-commit and clean both failed; abandoning worktree"
|
|
116873
|
+
};
|
|
116874
|
+
}
|
|
116875
|
+
const mergeResult = await mergeLaneBranch(primaryDir, branchName, strategy);
|
|
116876
|
+
if ("merged" in mergeResult && mergeResult.merged) {
|
|
116877
|
+
return { merged: true, strategy, autoCommitted, cleaned };
|
|
116878
|
+
}
|
|
116879
|
+
if ("conflict" in mergeResult) {
|
|
116880
|
+
return {
|
|
116881
|
+
partial: true,
|
|
116882
|
+
stage: "merge",
|
|
116883
|
+
autoCommitted,
|
|
116884
|
+
cleaned,
|
|
116885
|
+
message: mergeResult.message
|
|
116886
|
+
};
|
|
116887
|
+
}
|
|
116888
|
+
if ("error" in mergeResult) {
|
|
116889
|
+
return {
|
|
116890
|
+
failed: true,
|
|
116891
|
+
stage: "merge",
|
|
116892
|
+
message: mergeResult.error
|
|
116893
|
+
};
|
|
116894
|
+
}
|
|
116895
|
+
return {
|
|
116896
|
+
failed: true,
|
|
116897
|
+
stage: "merge",
|
|
116898
|
+
message: "Merge failed with unexpected result"
|
|
116899
|
+
};
|
|
116900
|
+
}
|
|
116901
|
+
function extractSessionId(branchName) {
|
|
116902
|
+
const segments = branchName.trim().split("/");
|
|
116903
|
+
if (segments.length >= 3 && segments[0] === "swarm-lane") {
|
|
116904
|
+
return segments[1];
|
|
116905
|
+
}
|
|
116906
|
+
return null;
|
|
116907
|
+
}
|
|
116908
|
+
async function startupOrphanRecovery(directory, activeSessionIds = []) {
|
|
116909
|
+
const warnings = [];
|
|
116910
|
+
const pruneResult = await runGit2(["worktree", "prune"], directory);
|
|
116911
|
+
if (pruneResult.exitCode !== 0) {
|
|
116912
|
+
warnings.push(`git worktree prune failed: ${pruneResult.stderr.trim() || pruneResult.stdout.trim()}`);
|
|
116913
|
+
}
|
|
116914
|
+
const listResult = await runGit2(["branch", "--format=%(refname:short)", "--list", "swarm-lane/*"], directory);
|
|
116915
|
+
const allBranches = listResult.stdout.split(`
|
|
116916
|
+
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
116917
|
+
const orphanBranches = [];
|
|
116918
|
+
for (const branch of allBranches) {
|
|
116919
|
+
const sessionId = extractSessionId(branch);
|
|
116920
|
+
if (sessionId === null || !activeSessionIds.includes(sessionId)) {
|
|
116921
|
+
orphanBranches.push(branch);
|
|
116922
|
+
warnings.push(`Orphaned swarm-lane branch "${branch}" detected in "${directory}"`);
|
|
116923
|
+
}
|
|
116924
|
+
}
|
|
116925
|
+
for (const warning of warnings) {
|
|
116926
|
+
console.warn(warning);
|
|
116927
|
+
}
|
|
116928
|
+
return {
|
|
116929
|
+
prunedWorktrees: pruneResult.exitCode === 0,
|
|
116930
|
+
remainingBranches: orphanBranches,
|
|
116931
|
+
warnings
|
|
116932
|
+
};
|
|
116933
|
+
}
|
|
116934
|
+
|
|
116935
|
+
// src/turbo/lean/runner.ts
|
|
116506
116936
|
init_state3();
|
|
116937
|
+
function isTransientProvisionError(errorMsg) {
|
|
116938
|
+
const lower = errorMsg.toLowerCase();
|
|
116939
|
+
if (lower.includes("already exists") || lower.includes("not a git repository")) {
|
|
116940
|
+
return false;
|
|
116941
|
+
}
|
|
116942
|
+
const transientCodes = [
|
|
116943
|
+
"enoent",
|
|
116944
|
+
"econnrefused",
|
|
116945
|
+
"etimedout",
|
|
116946
|
+
"ebusy",
|
|
116947
|
+
"eperm",
|
|
116948
|
+
"enomem"
|
|
116949
|
+
];
|
|
116950
|
+
for (const code of transientCodes) {
|
|
116951
|
+
if (lower.includes(code)) {
|
|
116952
|
+
return true;
|
|
116953
|
+
}
|
|
116954
|
+
}
|
|
116955
|
+
const transientMessages = [
|
|
116956
|
+
"disk full",
|
|
116957
|
+
"no space left",
|
|
116958
|
+
"resource temporarily unavailable"
|
|
116959
|
+
];
|
|
116960
|
+
for (const msg of transientMessages) {
|
|
116961
|
+
if (lower.includes(msg)) {
|
|
116962
|
+
return true;
|
|
116963
|
+
}
|
|
116964
|
+
}
|
|
116965
|
+
if (lower.includes("fatal:")) {
|
|
116966
|
+
return true;
|
|
116967
|
+
}
|
|
116968
|
+
return false;
|
|
116969
|
+
}
|
|
116507
116970
|
|
|
116508
116971
|
class LeanTurboRunner {
|
|
116509
116972
|
static _internals = {
|
|
@@ -116516,7 +116979,15 @@ class LeanTurboRunner {
|
|
|
116516
116979
|
hasActiveFullAuto,
|
|
116517
116980
|
loadFullAutoRunState,
|
|
116518
116981
|
writeLaneEvidence,
|
|
116519
|
-
laneDispatchTimeoutMs: undefined
|
|
116982
|
+
laneDispatchTimeoutMs: undefined,
|
|
116983
|
+
provisionWorktree,
|
|
116984
|
+
removeWorktree,
|
|
116985
|
+
mergeLaneBranch,
|
|
116986
|
+
postMergeCleanup,
|
|
116987
|
+
attemptMergeBackFromDirty,
|
|
116988
|
+
startupOrphanRecovery,
|
|
116989
|
+
getMergeStrategy,
|
|
116990
|
+
assertCleanWorkingTree
|
|
116520
116991
|
};
|
|
116521
116992
|
_sessionOps = null;
|
|
116522
116993
|
_directory;
|
|
@@ -116575,6 +117046,22 @@ class LeanTurboRunner {
|
|
|
116575
117046
|
}
|
|
116576
117047
|
}
|
|
116577
117048
|
const leanConfig = this._getLeanConfig(this._leanConfig);
|
|
117049
|
+
if (leanConfig.worktree_isolation) {
|
|
117050
|
+
await LeanTurboRunner._internals.startupOrphanRecovery(this._directory, [
|
|
117051
|
+
this._sessionID
|
|
117052
|
+
]);
|
|
117053
|
+
try {
|
|
117054
|
+
const cleanResult = await LeanTurboRunner._internals.assertCleanWorkingTree(this._directory);
|
|
117055
|
+
if (!cleanResult.clean) {
|
|
117056
|
+
console.warn(`[lean-turbo] worktree isolation requires clean working tree: ${cleanResult.error}`);
|
|
117057
|
+
leanConfig.worktree_isolation = false;
|
|
117058
|
+
}
|
|
117059
|
+
} catch (assertErr) {
|
|
117060
|
+
const assertMsg = assertErr instanceof Error ? assertErr.message : String(assertErr);
|
|
117061
|
+
console.warn(`[lean-turbo] unable to verify working tree cleanliness: ${assertMsg} — degrading to shared directory`);
|
|
117062
|
+
leanConfig.worktree_isolation = false;
|
|
117063
|
+
}
|
|
117064
|
+
}
|
|
116578
117065
|
const lanePlan = LeanTurboRunner._internals.planLeanTurboLanes(this._directory, phaseNumber, { phases: plan.phases }, leanConfig);
|
|
116579
117066
|
const degradedTasks = lanePlan.degradedTasks.map((d) => d.taskId);
|
|
116580
117067
|
if (lanePlan.lanes.length === 0 && degradedTasks.length === 0 && lanePlan.serializedTasks.length === 0) {
|
|
@@ -116598,21 +117085,23 @@ class LeanTurboRunner {
|
|
|
116598
117085
|
await this._withStateLock(() => this._updateDurableState(lanePlan));
|
|
116599
117086
|
this._laneStatuses = new Map(lanePlan.lanes.map((lane) => [lane.laneId, { ...lane }]));
|
|
116600
117087
|
const laneResults = [];
|
|
116601
|
-
const results = await Promise.all(lanePlan.lanes.map((lane) => this._processLane(lane)));
|
|
117088
|
+
const results = await Promise.all(lanePlan.lanes.map((lane) => this._processLane(lane, leanConfig)));
|
|
116602
117089
|
laneResults.push(...results);
|
|
117090
|
+
const mergeBackFailures = await this._sequentialWorktreeCleanup(laneResults, leanConfig);
|
|
116603
117091
|
return {
|
|
116604
117092
|
ok: true,
|
|
116605
117093
|
lanes: laneResults,
|
|
116606
117094
|
degradedTasks,
|
|
116607
|
-
serializedTasks: lanePlan.serializedTasks
|
|
117095
|
+
serializedTasks: lanePlan.serializedTasks,
|
|
117096
|
+
mergeBackFailures: mergeBackFailures.length > 0 ? mergeBackFailures : undefined
|
|
116608
117097
|
};
|
|
116609
117098
|
}
|
|
116610
|
-
async dispatchLane(lane, agentName) {
|
|
117099
|
+
async dispatchLane(lane, agentName, worktreeDirectory) {
|
|
116611
117100
|
const session = this._sessionOps ?? this._client?.session;
|
|
116612
117101
|
if (!session) {
|
|
116613
117102
|
return { ok: false, error: "NO_CLIENT" };
|
|
116614
117103
|
}
|
|
116615
|
-
const dispatchPromise = this._doDispatch(session, lane, agentName);
|
|
117104
|
+
const dispatchPromise = this._doDispatch(session, lane, agentName, worktreeDirectory);
|
|
116616
117105
|
const timeoutMs = LeanTurboRunner._internals.laneDispatchTimeoutMs;
|
|
116617
117106
|
if (timeoutMs !== undefined && timeoutMs > 0) {
|
|
116618
117107
|
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Lane dispatch timed out after ${timeoutMs}ms`)), timeoutMs));
|
|
@@ -116643,10 +117132,11 @@ class LeanTurboRunner {
|
|
|
116643
117132
|
}
|
|
116644
117133
|
return dispatchPromise;
|
|
116645
117134
|
}
|
|
116646
|
-
async _doDispatch(session, lane, agentName) {
|
|
117135
|
+
async _doDispatch(session, lane, agentName, worktreeDirectory) {
|
|
116647
117136
|
try {
|
|
117137
|
+
const effectiveDirectory = worktreeDirectory ?? this._directory;
|
|
116648
117138
|
const createResult = await session.create({
|
|
116649
|
-
query: { directory:
|
|
117139
|
+
query: { directory: effectiveDirectory }
|
|
116650
117140
|
});
|
|
116651
117141
|
if (!createResult.data) {
|
|
116652
117142
|
return {
|
|
@@ -116698,6 +117188,13 @@ class LeanTurboRunner {
|
|
|
116698
117188
|
} catch {}
|
|
116699
117189
|
}
|
|
116700
117190
|
this._laneLockMap = {};
|
|
117191
|
+
for (const [_laneId, lane] of this._laneStatuses) {
|
|
117192
|
+
if (lane.worktreePath) {
|
|
117193
|
+
try {
|
|
117194
|
+
await LeanTurboRunner._internals.removeWorktree(lane.worktreePath, this._directory);
|
|
117195
|
+
} catch {}
|
|
117196
|
+
}
|
|
117197
|
+
}
|
|
116701
117198
|
await this._withStateLock(async () => {
|
|
116702
117199
|
const runState = LeanTurboRunner._internals.loadLeanTurboRunState(this._directory, this._sessionID);
|
|
116703
117200
|
if (runState) {
|
|
@@ -116745,7 +117242,7 @@ class LeanTurboRunner {
|
|
|
116745
117242
|
}
|
|
116746
117243
|
return defaults;
|
|
116747
117244
|
}
|
|
116748
|
-
async _processLane(lane) {
|
|
117245
|
+
async _processLane(lane, leanConfig) {
|
|
116749
117246
|
const laneInState = this._laneStatuses.get(lane.laneId);
|
|
116750
117247
|
if (laneInState) {
|
|
116751
117248
|
laneInState.status = "running";
|
|
@@ -116782,12 +117279,85 @@ class LeanTurboRunner {
|
|
|
116782
117279
|
};
|
|
116783
117280
|
}
|
|
116784
117281
|
this._laneLockMap[lane.laneId] = [...lane.files];
|
|
116785
|
-
|
|
117282
|
+
let worktreeDirectory;
|
|
117283
|
+
if (leanConfig.worktree_isolation) {
|
|
117284
|
+
let provisionError;
|
|
117285
|
+
try {
|
|
117286
|
+
const provisionResult = await LeanTurboRunner._internals.provisionWorktree(this._directory, lane.laneId, this._sessionID, leanConfig);
|
|
117287
|
+
if ("worktreePath" in provisionResult) {
|
|
117288
|
+
worktreeDirectory = provisionResult.worktreePath;
|
|
117289
|
+
if (laneInState) {
|
|
117290
|
+
laneInState.worktreePath = provisionResult.worktreePath;
|
|
117291
|
+
laneInState.branchName = provisionResult.branchName;
|
|
117292
|
+
}
|
|
117293
|
+
await this._persistLaneWorktreeFields(lane.laneId, provisionResult.worktreePath, provisionResult.branchName);
|
|
117294
|
+
} else {
|
|
117295
|
+
provisionError = provisionResult.error;
|
|
117296
|
+
}
|
|
117297
|
+
} catch (provisionErr) {
|
|
117298
|
+
provisionError = provisionErr instanceof Error ? provisionErr.message : String(provisionErr);
|
|
117299
|
+
}
|
|
117300
|
+
if (provisionError) {
|
|
117301
|
+
if (isTransientProvisionError(provisionError)) {
|
|
117302
|
+
console.warn(`[lean-turbo] worktree provision failed for lane ${lane.laneId}: ${provisionError} — retrying once...`);
|
|
117303
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
117304
|
+
try {
|
|
117305
|
+
const retryResult = await LeanTurboRunner._internals.provisionWorktree(this._directory, lane.laneId, this._sessionID, leanConfig);
|
|
117306
|
+
if ("worktreePath" in retryResult) {
|
|
117307
|
+
worktreeDirectory = retryResult.worktreePath;
|
|
117308
|
+
if (laneInState) {
|
|
117309
|
+
laneInState.worktreePath = retryResult.worktreePath;
|
|
117310
|
+
laneInState.branchName = retryResult.branchName;
|
|
117311
|
+
}
|
|
117312
|
+
await this._persistLaneWorktreeFields(lane.laneId, retryResult.worktreePath, retryResult.branchName);
|
|
117313
|
+
console.warn(`[lean-turbo] worktree provision retry succeeded for lane ${lane.laneId}`);
|
|
117314
|
+
provisionError = undefined;
|
|
117315
|
+
} else {
|
|
117316
|
+
provisionError = retryResult.error;
|
|
117317
|
+
console.warn(`[lean-turbo] worktree provision retry failed for lane ${lane.laneId}: ${retryResult.error}`);
|
|
117318
|
+
}
|
|
117319
|
+
} catch (retryErr) {
|
|
117320
|
+
const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
|
117321
|
+
console.warn(`[lean-turbo] worktree provision retry threw for lane ${lane.laneId}: ${retryMsg}`);
|
|
117322
|
+
}
|
|
117323
|
+
} else {
|
|
117324
|
+
console.warn(`[lean-turbo] worktree provision failed for lane ${lane.laneId}: ${provisionError}`);
|
|
117325
|
+
}
|
|
117326
|
+
}
|
|
117327
|
+
if (!worktreeDirectory) {
|
|
117328
|
+
const failMsg = `worktree provision failed: ${provisionError ?? "unknown error"}`;
|
|
117329
|
+
try {
|
|
117330
|
+
await LeanTurboRunner._internals.releaseLaneLocks(this._directory, lane.laneId);
|
|
117331
|
+
} catch {}
|
|
117332
|
+
delete this._laneLockMap[lane.laneId];
|
|
117333
|
+
if (laneInState) {
|
|
117334
|
+
laneInState.status = "failed";
|
|
117335
|
+
laneInState.error = failMsg;
|
|
117336
|
+
}
|
|
117337
|
+
await this._updateDurableStateLaneStatus(lane.laneId, "failed");
|
|
117338
|
+
await this._writeLaneEvidenceSafely(lane, "failed", {
|
|
117339
|
+
status: "failed",
|
|
117340
|
+
error: failMsg,
|
|
117341
|
+
agent
|
|
117342
|
+
});
|
|
117343
|
+
return {
|
|
117344
|
+
laneId: lane.laneId,
|
|
117345
|
+
status: "failed",
|
|
117346
|
+
taskIds: lane.taskIds,
|
|
117347
|
+
agent,
|
|
117348
|
+
error: failMsg
|
|
117349
|
+
};
|
|
117350
|
+
}
|
|
117351
|
+
}
|
|
117352
|
+
const dispatchResult = await this.dispatchLane(lane, agent, worktreeDirectory);
|
|
116786
117353
|
if (!dispatchResult.ok) {
|
|
116787
117354
|
try {
|
|
116788
117355
|
await LeanTurboRunner._internals.releaseLaneLocks(this._directory, lane.laneId);
|
|
116789
117356
|
} catch {}
|
|
116790
117357
|
delete this._laneLockMap[lane.laneId];
|
|
117358
|
+
if (worktreeDirectory && laneInState) {
|
|
117359
|
+
laneInState._failureCleanupPending = true;
|
|
117360
|
+
}
|
|
116791
117361
|
if (laneInState) {
|
|
116792
117362
|
laneInState.status = "failed";
|
|
116793
117363
|
laneInState.error = dispatchResult.error;
|
|
@@ -116832,6 +117402,69 @@ class LeanTurboRunner {
|
|
|
116832
117402
|
sessionId: dispatchResult.sessionId
|
|
116833
117403
|
};
|
|
116834
117404
|
}
|
|
117405
|
+
async _sequentialWorktreeCleanup(laneResults, leanConfig) {
|
|
117406
|
+
const mergeBackFailures = [];
|
|
117407
|
+
for (const lr of laneResults) {
|
|
117408
|
+
const laneInState = this._laneStatuses.get(lr.laneId);
|
|
117409
|
+
if (!laneInState?.worktreePath)
|
|
117410
|
+
continue;
|
|
117411
|
+
let needsPostMergeCleanup = false;
|
|
117412
|
+
if (lr.status === "completed") {
|
|
117413
|
+
if (!laneInState.branchName)
|
|
117414
|
+
continue;
|
|
117415
|
+
try {
|
|
117416
|
+
const strategy = LeanTurboRunner._internals.getMergeStrategy(leanConfig);
|
|
117417
|
+
const mergeResult = await LeanTurboRunner._internals.mergeLaneBranch(this._directory, laneInState.branchName, strategy);
|
|
117418
|
+
if ("merged" in mergeResult && mergeResult.merged) {
|
|
117419
|
+
needsPostMergeCleanup = true;
|
|
117420
|
+
} else if ("conflict" in mergeResult && mergeResult.conflict) {
|
|
117421
|
+
const failureInfo = {
|
|
117422
|
+
laneId: lr.laneId,
|
|
117423
|
+
reason: mergeResult.message || "merge conflict",
|
|
117424
|
+
conflictFiles: mergeResult.files
|
|
117425
|
+
};
|
|
117426
|
+
mergeBackFailures.push(failureInfo);
|
|
117427
|
+
lr.mergeBackFailure = failureInfo;
|
|
117428
|
+
console.warn(`[lean-turbo] merge-back CONFLICT for lane ${lr.laneId}: ${failureInfo.reason} — worktree preserved at ${laneInState.worktreePath} for manual recovery`);
|
|
117429
|
+
continue;
|
|
117430
|
+
} else if ("error" in mergeResult && mergeResult.error) {
|
|
117431
|
+
const failureInfo = {
|
|
117432
|
+
laneId: lr.laneId,
|
|
117433
|
+
reason: mergeResult.error
|
|
117434
|
+
};
|
|
117435
|
+
mergeBackFailures.push(failureInfo);
|
|
117436
|
+
lr.mergeBackFailure = failureInfo;
|
|
117437
|
+
console.warn(`[lean-turbo] merge-back ERROR for lane ${lr.laneId}: ${failureInfo.reason} — worktree preserved at ${laneInState.worktreePath} for manual recovery`);
|
|
117438
|
+
continue;
|
|
117439
|
+
}
|
|
117440
|
+
} catch (err2) {
|
|
117441
|
+
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
117442
|
+
const failureInfo = {
|
|
117443
|
+
laneId: lr.laneId,
|
|
117444
|
+
reason: errMsg
|
|
117445
|
+
};
|
|
117446
|
+
mergeBackFailures.push(failureInfo);
|
|
117447
|
+
lr.mergeBackFailure = failureInfo;
|
|
117448
|
+
console.warn(`[lean-turbo] merge-back EXCEPTION for lane ${lr.laneId}: ${errMsg} — worktree preserved at ${laneInState.worktreePath} for manual recovery`);
|
|
117449
|
+
continue;
|
|
117450
|
+
}
|
|
117451
|
+
} else if (lr.status === "failed" && laneInState._failureCleanupPending) {
|
|
117452
|
+
try {
|
|
117453
|
+
const strategy = LeanTurboRunner._internals.getMergeStrategy(leanConfig);
|
|
117454
|
+
await LeanTurboRunner._internals.attemptMergeBackFromDirty(laneInState.worktreePath, laneInState.branchName ?? `swarm-lane/${this._sessionID}/${lr.laneId}`, this._directory, strategy);
|
|
117455
|
+
} catch {}
|
|
117456
|
+
}
|
|
117457
|
+
try {
|
|
117458
|
+
await LeanTurboRunner._internals.removeWorktree(laneInState.worktreePath, this._directory);
|
|
117459
|
+
} catch {}
|
|
117460
|
+
if (needsPostMergeCleanup && laneInState.branchName) {
|
|
117461
|
+
try {
|
|
117462
|
+
await LeanTurboRunner._internals.postMergeCleanup(this._directory, laneInState.branchName);
|
|
117463
|
+
} catch {}
|
|
117464
|
+
}
|
|
117465
|
+
}
|
|
117466
|
+
return mergeBackFailures;
|
|
117467
|
+
}
|
|
116835
117468
|
_selectNextAgent() {
|
|
116836
117469
|
if (this._availableAgents.length === 0) {
|
|
116837
117470
|
return "coder";
|
|
@@ -116925,6 +117558,21 @@ ${fileList}
|
|
|
116925
117558
|
LeanTurboRunner._internals.saveLeanTurboRunState(this._directory, runState);
|
|
116926
117559
|
} catch {}
|
|
116927
117560
|
}
|
|
117561
|
+
async _persistLaneWorktreeFields(laneId, worktreePath, branchName) {
|
|
117562
|
+
await this._withStateLock(async () => {
|
|
117563
|
+
try {
|
|
117564
|
+
const runState = LeanTurboRunner._internals.loadLeanTurboRunState(this._directory, this._sessionID);
|
|
117565
|
+
if (!runState)
|
|
117566
|
+
return;
|
|
117567
|
+
const lane = runState.lanes.find((l) => l.laneId === laneId);
|
|
117568
|
+
if (lane) {
|
|
117569
|
+
lane.worktreePath = worktreePath;
|
|
117570
|
+
lane.branchName = branchName;
|
|
117571
|
+
LeanTurboRunner._internals.saveLeanTurboRunState(this._directory, runState);
|
|
117572
|
+
}
|
|
117573
|
+
} catch {}
|
|
117574
|
+
});
|
|
117575
|
+
}
|
|
116928
117576
|
async _updateDurableStateLaneStatus(laneId, status) {
|
|
116929
117577
|
await this._withStateLock(async () => {
|
|
116930
117578
|
try {
|
|
@@ -116950,7 +117598,7 @@ ${fileList}
|
|
|
116950
117598
|
|
|
116951
117599
|
// src/tools/lean-turbo-run-phase.ts
|
|
116952
117600
|
init_create_tool();
|
|
116953
|
-
var
|
|
117601
|
+
var _internals64 = {
|
|
116954
117602
|
LeanTurboRunner,
|
|
116955
117603
|
loadPluginConfigWithMeta
|
|
116956
117604
|
};
|
|
@@ -116960,9 +117608,9 @@ async function executeLeanTurboRunPhase(args2) {
|
|
|
116960
117608
|
let runError = null;
|
|
116961
117609
|
let runner = null;
|
|
116962
117610
|
try {
|
|
116963
|
-
const { config: config3 } =
|
|
117611
|
+
const { config: config3 } = _internals64.loadPluginConfigWithMeta(directory);
|
|
116964
117612
|
const leanConfig = config3.turbo?.strategy === "lean" ? config3.turbo.lean : undefined;
|
|
116965
|
-
runner = new
|
|
117613
|
+
runner = new _internals64.LeanTurboRunner({
|
|
116966
117614
|
directory,
|
|
116967
117615
|
sessionID,
|
|
116968
117616
|
opencodeClient: swarmState.opencodeClient ?? null,
|
|
@@ -116995,6 +117643,7 @@ async function executeLeanTurboRunPhase(args2) {
|
|
|
116995
117643
|
lanes: runResult.lanes,
|
|
116996
117644
|
degradedTasks: runResult.degradedTasks,
|
|
116997
117645
|
serializedTasks: runResult.serializedTasks,
|
|
117646
|
+
mergeBackFailures: runResult.mergeBackFailures,
|
|
116998
117647
|
reason: runResult.reason
|
|
116999
117648
|
};
|
|
117000
117649
|
}
|
|
@@ -117121,7 +117770,7 @@ init_lint();
|
|
|
117121
117770
|
init_spec_schema();
|
|
117122
117771
|
init_create_tool();
|
|
117123
117772
|
import * as fs99 from "node:fs";
|
|
117124
|
-
import * as
|
|
117773
|
+
import * as path138 from "node:path";
|
|
117125
117774
|
var SPEC_FILE_NAME = "spec.md";
|
|
117126
117775
|
var SWARM_DIR2 = ".swarm";
|
|
117127
117776
|
var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -117174,7 +117823,7 @@ var lint_spec = createSwarmTool({
|
|
|
117174
117823
|
async execute(_args, directory) {
|
|
117175
117824
|
const errors5 = [];
|
|
117176
117825
|
const warnings = [];
|
|
117177
|
-
const specPath =
|
|
117826
|
+
const specPath = path138.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
117178
117827
|
if (!fs99.existsSync(specPath)) {
|
|
117179
117828
|
const result2 = {
|
|
117180
117829
|
valid: false,
|
|
@@ -117246,12 +117895,12 @@ var lint_spec = createSwarmTool({
|
|
|
117246
117895
|
// src/tools/mutation-test.ts
|
|
117247
117896
|
init_zod();
|
|
117248
117897
|
import * as fs100 from "node:fs";
|
|
117249
|
-
import * as
|
|
117898
|
+
import * as path140 from "node:path";
|
|
117250
117899
|
|
|
117251
117900
|
// src/mutation/engine.ts
|
|
117252
117901
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
117253
117902
|
import { unlinkSync as unlinkSync19, writeFileSync as writeFileSync26 } from "node:fs";
|
|
117254
|
-
import * as
|
|
117903
|
+
import * as path139 from "node:path";
|
|
117255
117904
|
|
|
117256
117905
|
// src/mutation/equivalence.ts
|
|
117257
117906
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -117323,7 +117972,7 @@ function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
|
117323
117972
|
const strippedMutated = stripCode(mutatedCode);
|
|
117324
117973
|
return strippedOriginal === strippedMutated;
|
|
117325
117974
|
}
|
|
117326
|
-
var
|
|
117975
|
+
var _internals65 = {
|
|
117327
117976
|
isStaticallyEquivalent,
|
|
117328
117977
|
checkEquivalence,
|
|
117329
117978
|
batchCheckEquivalence
|
|
@@ -117363,7 +118012,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
117363
118012
|
const results = [];
|
|
117364
118013
|
for (const { patch, originalCode, mutatedCode } of patches) {
|
|
117365
118014
|
try {
|
|
117366
|
-
const result = await
|
|
118015
|
+
const result = await _internals65.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
|
|
117367
118016
|
results.push(result);
|
|
117368
118017
|
} catch (err2) {
|
|
117369
118018
|
results.push({
|
|
@@ -117382,7 +118031,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
117382
118031
|
var MUTATION_TIMEOUT_MS = 30000;
|
|
117383
118032
|
var TOTAL_BUDGET_MS = 300000;
|
|
117384
118033
|
var GIT_APPLY_TIMEOUT_MS = 5000;
|
|
117385
|
-
var
|
|
118034
|
+
var _internals66 = {
|
|
117386
118035
|
executeMutation,
|
|
117387
118036
|
computeReport,
|
|
117388
118037
|
executeMutationSuite,
|
|
@@ -117397,7 +118046,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
117397
118046
|
let patchFile;
|
|
117398
118047
|
try {
|
|
117399
118048
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
117400
|
-
patchFile =
|
|
118049
|
+
patchFile = path139.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
117401
118050
|
try {
|
|
117402
118051
|
writeFileSync26(patchFile, patch.patch);
|
|
117403
118052
|
} catch (writeErr) {
|
|
@@ -117414,7 +118063,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
117414
118063
|
};
|
|
117415
118064
|
}
|
|
117416
118065
|
try {
|
|
117417
|
-
const applyResult =
|
|
118066
|
+
const applyResult = _internals66.spawnSync("git", ["apply", "--", patchFile], {
|
|
117418
118067
|
cwd: workingDir,
|
|
117419
118068
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
117420
118069
|
stdio: "pipe"
|
|
@@ -117443,7 +118092,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
117443
118092
|
}
|
|
117444
118093
|
let testPassed = false;
|
|
117445
118094
|
try {
|
|
117446
|
-
const spawnResult =
|
|
118095
|
+
const spawnResult = _internals66.spawnSync(testCommand[0], testCommand.slice(1), {
|
|
117447
118096
|
cwd: workingDir,
|
|
117448
118097
|
timeout: MUTATION_TIMEOUT_MS,
|
|
117449
118098
|
stdio: "pipe"
|
|
@@ -117476,7 +118125,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
117476
118125
|
} finally {
|
|
117477
118126
|
if (patchFile) {
|
|
117478
118127
|
try {
|
|
117479
|
-
const revertResult =
|
|
118128
|
+
const revertResult = _internals66.spawnSync("git", ["apply", "-R", "--", patchFile], {
|
|
117480
118129
|
cwd: workingDir,
|
|
117481
118130
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
117482
118131
|
stdio: "pipe"
|
|
@@ -117669,7 +118318,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
|
|
|
117669
118318
|
}
|
|
117670
118319
|
|
|
117671
118320
|
// src/mutation/gate.ts
|
|
117672
|
-
var
|
|
118321
|
+
var _internals67 = {
|
|
117673
118322
|
evaluateMutationGate,
|
|
117674
118323
|
buildTestImprovementPrompt,
|
|
117675
118324
|
buildMessage
|
|
@@ -117690,8 +118339,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
|
|
|
117690
118339
|
} else {
|
|
117691
118340
|
verdict = "fail";
|
|
117692
118341
|
}
|
|
117693
|
-
const testImprovementPrompt =
|
|
117694
|
-
const message =
|
|
118342
|
+
const testImprovementPrompt = _internals67.buildTestImprovementPrompt(report, passThreshold, verdict);
|
|
118343
|
+
const message = _internals67.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
|
|
117695
118344
|
return {
|
|
117696
118345
|
verdict,
|
|
117697
118346
|
killRate: report.killRate,
|
|
@@ -117801,7 +118450,7 @@ var mutation_test = createSwarmTool({
|
|
|
117801
118450
|
];
|
|
117802
118451
|
for (const filePath of uniquePaths) {
|
|
117803
118452
|
try {
|
|
117804
|
-
const resolvedPath =
|
|
118453
|
+
const resolvedPath = path140.resolve(cwd, filePath);
|
|
117805
118454
|
sourceFiles.set(filePath, fs100.readFileSync(resolvedPath, "utf-8"));
|
|
117806
118455
|
} catch {}
|
|
117807
118456
|
}
|
|
@@ -117823,22 +118472,22 @@ init_config();
|
|
|
117823
118472
|
init_schema();
|
|
117824
118473
|
init_manager2();
|
|
117825
118474
|
import * as fs110 from "node:fs";
|
|
117826
|
-
import * as
|
|
118475
|
+
import * as path150 from "node:path";
|
|
117827
118476
|
|
|
117828
118477
|
// src/full-auto/phase-approval.ts
|
|
117829
118478
|
init_utils2();
|
|
117830
118479
|
init_logger();
|
|
117831
118480
|
init_state2();
|
|
117832
118481
|
import * as fs101 from "node:fs";
|
|
117833
|
-
import * as
|
|
118482
|
+
import * as path141 from "node:path";
|
|
117834
118483
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
117835
118484
|
function readEvidenceDir(directory, phase) {
|
|
117836
118485
|
try {
|
|
117837
|
-
const dirPath = validateSwarmPath(directory,
|
|
118486
|
+
const dirPath = validateSwarmPath(directory, path141.posix.join("evidence", String(phase)));
|
|
117838
118487
|
if (!fs101.existsSync(dirPath))
|
|
117839
118488
|
return [];
|
|
117840
118489
|
const entries = fs101.readdirSync(dirPath);
|
|
117841
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
118490
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path141.join(dirPath, e));
|
|
117842
118491
|
} catch {
|
|
117843
118492
|
return [];
|
|
117844
118493
|
}
|
|
@@ -117979,16 +118628,16 @@ init_plan_schema();
|
|
|
117979
118628
|
init_ledger();
|
|
117980
118629
|
init_manager();
|
|
117981
118630
|
import * as fs102 from "node:fs";
|
|
117982
|
-
import * as
|
|
118631
|
+
import * as path142 from "node:path";
|
|
117983
118632
|
async function writeCheckpoint(directory) {
|
|
117984
118633
|
try {
|
|
117985
118634
|
const plan = await loadPlan(directory);
|
|
117986
118635
|
if (!plan)
|
|
117987
118636
|
return;
|
|
117988
|
-
const swarmDir =
|
|
118637
|
+
const swarmDir = path142.join(directory, ".swarm");
|
|
117989
118638
|
fs102.mkdirSync(swarmDir, { recursive: true });
|
|
117990
|
-
const jsonPath =
|
|
117991
|
-
const mdPath =
|
|
118639
|
+
const jsonPath = path142.join(swarmDir, "SWARM_PLAN.json");
|
|
118640
|
+
const mdPath = path142.join(swarmDir, "SWARM_PLAN.md");
|
|
117992
118641
|
fs102.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
117993
118642
|
const md = derivePlanMarkdown(plan);
|
|
117994
118643
|
fs102.writeFileSync(mdPath, md, "utf8");
|
|
@@ -118007,7 +118656,7 @@ init_telemetry();
|
|
|
118007
118656
|
// src/turbo/lean/phase-ready.ts
|
|
118008
118657
|
init_file_locks();
|
|
118009
118658
|
import * as fs103 from "node:fs";
|
|
118010
|
-
import * as
|
|
118659
|
+
import * as path143 from "node:path";
|
|
118011
118660
|
init_state3();
|
|
118012
118661
|
var DEFAULT_CONFIG3 = {
|
|
118013
118662
|
phase_reviewer: true,
|
|
@@ -118016,7 +118665,7 @@ var DEFAULT_CONFIG3 = {
|
|
|
118016
118665
|
};
|
|
118017
118666
|
function defaultReadPlanJson(dir) {
|
|
118018
118667
|
try {
|
|
118019
|
-
const planPath =
|
|
118668
|
+
const planPath = path143.join(dir, ".swarm", "plan.json");
|
|
118020
118669
|
if (!fs103.existsSync(planPath))
|
|
118021
118670
|
return null;
|
|
118022
118671
|
const raw = fs103.readFileSync(planPath, "utf-8");
|
|
@@ -118031,7 +118680,7 @@ function defaultReadPlanJson(dir) {
|
|
|
118031
118680
|
}
|
|
118032
118681
|
function readReviewerEvidenceFromFile(directory, phase) {
|
|
118033
118682
|
try {
|
|
118034
|
-
const evidencePath =
|
|
118683
|
+
const evidencePath = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
|
|
118035
118684
|
if (!fs103.existsSync(evidencePath)) {
|
|
118036
118685
|
return null;
|
|
118037
118686
|
}
|
|
@@ -118051,7 +118700,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
|
|
|
118051
118700
|
}
|
|
118052
118701
|
function readCriticEvidenceFromFile(directory, phase) {
|
|
118053
118702
|
try {
|
|
118054
|
-
const evidencePath =
|
|
118703
|
+
const evidencePath = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
|
|
118055
118704
|
if (!fs103.existsSync(evidencePath)) {
|
|
118056
118705
|
return null;
|
|
118057
118706
|
}
|
|
@@ -118070,7 +118719,7 @@ function readCriticEvidenceFromFile(directory, phase) {
|
|
|
118070
118719
|
}
|
|
118071
118720
|
}
|
|
118072
118721
|
function listLaneEvidenceSync(directory, phase) {
|
|
118073
|
-
const evidenceDir =
|
|
118722
|
+
const evidenceDir = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
118074
118723
|
let entries;
|
|
118075
118724
|
try {
|
|
118076
118725
|
entries = fs103.readdirSync(evidenceDir);
|
|
@@ -118086,7 +118735,7 @@ function listLaneEvidenceSync(directory, phase) {
|
|
|
118086
118735
|
}
|
|
118087
118736
|
return laneIds;
|
|
118088
118737
|
}
|
|
118089
|
-
var
|
|
118738
|
+
var _internals68 = {
|
|
118090
118739
|
listActiveLocks,
|
|
118091
118740
|
readPersisted: readPersisted2,
|
|
118092
118741
|
readPlanJson: defaultReadPlanJson,
|
|
@@ -118140,14 +118789,14 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118140
118789
|
...DEFAULT_CONFIG3,
|
|
118141
118790
|
...actualConfig
|
|
118142
118791
|
};
|
|
118143
|
-
const statePath =
|
|
118792
|
+
const statePath = path143.join(directory, ".swarm", "turbo-state.json");
|
|
118144
118793
|
if (!fs103.existsSync(statePath)) {
|
|
118145
118794
|
return {
|
|
118146
118795
|
ok: false,
|
|
118147
118796
|
reason: "Lean Turbo state unreadable or missing"
|
|
118148
118797
|
};
|
|
118149
118798
|
}
|
|
118150
|
-
const persisted =
|
|
118799
|
+
const persisted = _internals68.readPersisted(directory);
|
|
118151
118800
|
if (!persisted) {
|
|
118152
118801
|
return {
|
|
118153
118802
|
ok: false,
|
|
@@ -118211,7 +118860,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118211
118860
|
}
|
|
118212
118861
|
}
|
|
118213
118862
|
if (runState.lanes.length > 0) {
|
|
118214
|
-
const evidenceLaneIds = new Set(
|
|
118863
|
+
const evidenceLaneIds = new Set(_internals68.listLaneEvidenceSync(directory, phase));
|
|
118215
118864
|
for (const lane of runState.lanes) {
|
|
118216
118865
|
if ((lane.status === "completed" || lane.status === "failed") && !evidenceLaneIds.has(lane.laneId)) {
|
|
118217
118866
|
return {
|
|
@@ -118221,7 +118870,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118221
118870
|
}
|
|
118222
118871
|
}
|
|
118223
118872
|
}
|
|
118224
|
-
const activeLocks =
|
|
118873
|
+
const activeLocks = _internals68.listActiveLocks(directory);
|
|
118225
118874
|
const phaseLaneIds = new Set(laneIds);
|
|
118226
118875
|
for (const lock of activeLocks) {
|
|
118227
118876
|
if (lock.laneId && phaseLaneIds.has(lock.laneId)) {
|
|
@@ -118241,7 +118890,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118241
118890
|
}
|
|
118242
118891
|
const serialDegradedTasks = runState.degradedTasks.filter((dt) => !laneTaskIds.has(dt.taskId));
|
|
118243
118892
|
if (serialDegradedTasks.length > 0) {
|
|
118244
|
-
const plan =
|
|
118893
|
+
const plan = _internals68.readPlanJson(directory);
|
|
118245
118894
|
if (!plan) {
|
|
118246
118895
|
return {
|
|
118247
118896
|
ok: false,
|
|
@@ -118285,7 +118934,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118285
118934
|
}
|
|
118286
118935
|
const serializedTasks = runState.serializedTasks;
|
|
118287
118936
|
if (Array.isArray(serializedTasks) && serializedTasks.length > 0) {
|
|
118288
|
-
const plan =
|
|
118937
|
+
const plan = _internals68.readPlanJson(directory);
|
|
118289
118938
|
if (!plan) {
|
|
118290
118939
|
return {
|
|
118291
118940
|
ok: false,
|
|
@@ -118328,7 +118977,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118328
118977
|
}
|
|
118329
118978
|
}
|
|
118330
118979
|
if (mergedConfig.integrated_diff_required) {
|
|
118331
|
-
const evidencePath =
|
|
118980
|
+
const evidencePath = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
|
|
118332
118981
|
let hasDiff = false;
|
|
118333
118982
|
try {
|
|
118334
118983
|
const content = fs103.readFileSync(evidencePath, "utf-8");
|
|
@@ -118344,7 +118993,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118344
118993
|
}
|
|
118345
118994
|
let reviewerVerdict = runState.lastReviewerVerdict;
|
|
118346
118995
|
if (!reviewerVerdict) {
|
|
118347
|
-
const evidence =
|
|
118996
|
+
const evidence = _internals68.readReviewerEvidence(directory, phase);
|
|
118348
118997
|
reviewerVerdict = evidence?.verdict ?? undefined;
|
|
118349
118998
|
}
|
|
118350
118999
|
if (mergedConfig.phase_reviewer) {
|
|
@@ -118357,7 +119006,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
118357
119006
|
}
|
|
118358
119007
|
let criticVerdict = runState.lastCriticVerdict;
|
|
118359
119008
|
if (!criticVerdict) {
|
|
118360
|
-
const evidence =
|
|
119009
|
+
const evidence = _internals68.readCriticEvidence(directory, phase);
|
|
118361
119010
|
criticVerdict = evidence?.verdict ?? undefined;
|
|
118362
119011
|
}
|
|
118363
119012
|
if (mergedConfig.phase_critic) {
|
|
@@ -118480,13 +119129,13 @@ init_qa_gate_profile();
|
|
|
118480
119129
|
init_manager();
|
|
118481
119130
|
init_state();
|
|
118482
119131
|
import * as fs104 from "node:fs";
|
|
118483
|
-
import * as
|
|
119132
|
+
import * as path144 from "node:path";
|
|
118484
119133
|
async function runDriftGate(ctx) {
|
|
118485
119134
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
118486
119135
|
let driftCheckEnabled = true;
|
|
118487
119136
|
let driftHasSpecMd = false;
|
|
118488
119137
|
try {
|
|
118489
|
-
const specMdPath =
|
|
119138
|
+
const specMdPath = path144.join(dir, ".swarm", "spec.md");
|
|
118490
119139
|
driftHasSpecMd = fs104.existsSync(specMdPath);
|
|
118491
119140
|
const gatePlan = await loadPlan(dir);
|
|
118492
119141
|
if (gatePlan) {
|
|
@@ -118514,7 +119163,7 @@ async function runDriftGate(ctx) {
|
|
|
118514
119163
|
}
|
|
118515
119164
|
let phaseType;
|
|
118516
119165
|
try {
|
|
118517
|
-
const planPath =
|
|
119166
|
+
const planPath = path144.join(dir, ".swarm", "plan.json");
|
|
118518
119167
|
if (fs104.existsSync(planPath)) {
|
|
118519
119168
|
const planRaw = fs104.readFileSync(planPath, "utf-8");
|
|
118520
119169
|
const plan = JSON.parse(planRaw);
|
|
@@ -118533,7 +119182,7 @@ async function runDriftGate(ctx) {
|
|
|
118533
119182
|
};
|
|
118534
119183
|
}
|
|
118535
119184
|
try {
|
|
118536
|
-
const driftEvidencePath =
|
|
119185
|
+
const driftEvidencePath = path144.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
118537
119186
|
let driftVerdictFound = false;
|
|
118538
119187
|
let driftVerdictApproved = false;
|
|
118539
119188
|
try {
|
|
@@ -118569,7 +119218,7 @@ async function runDriftGate(ctx) {
|
|
|
118569
119218
|
let incompleteTaskCount = 0;
|
|
118570
119219
|
let planParseable = false;
|
|
118571
119220
|
try {
|
|
118572
|
-
const planPath =
|
|
119221
|
+
const planPath = path144.join(dir, ".swarm", "plan.json");
|
|
118573
119222
|
if (fs104.existsSync(planPath)) {
|
|
118574
119223
|
const planRaw = fs104.readFileSync(planPath, "utf-8");
|
|
118575
119224
|
const plan = JSON.parse(planRaw);
|
|
@@ -118651,7 +119300,7 @@ init_qa_gate_profile();
|
|
|
118651
119300
|
init_manager();
|
|
118652
119301
|
init_state();
|
|
118653
119302
|
import * as fs105 from "node:fs";
|
|
118654
|
-
import * as
|
|
119303
|
+
import * as path145 from "node:path";
|
|
118655
119304
|
async function runFinalCouncilGate(ctx) {
|
|
118656
119305
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
118657
119306
|
let finalCouncilEnabled = false;
|
|
@@ -118669,7 +119318,7 @@ async function runFinalCouncilGate(ctx) {
|
|
|
118669
119318
|
const effective = getEffectiveGates(profile, overrides);
|
|
118670
119319
|
if (effective.final_council === true) {
|
|
118671
119320
|
finalCouncilEnabled = true;
|
|
118672
|
-
const fcPath =
|
|
119321
|
+
const fcPath = path145.join(dir, ".swarm", "evidence", "final-council.json");
|
|
118673
119322
|
let fcVerdictFound = false;
|
|
118674
119323
|
let _fcVerdict;
|
|
118675
119324
|
try {
|
|
@@ -118810,7 +119459,7 @@ init_qa_gate_profile();
|
|
|
118810
119459
|
init_manager();
|
|
118811
119460
|
init_state();
|
|
118812
119461
|
import * as fs106 from "node:fs";
|
|
118813
|
-
import * as
|
|
119462
|
+
import * as path146 from "node:path";
|
|
118814
119463
|
async function runHallucinationGate(ctx) {
|
|
118815
119464
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
118816
119465
|
try {
|
|
@@ -118823,7 +119472,7 @@ async function runHallucinationGate(ctx) {
|
|
|
118823
119472
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
118824
119473
|
const effective = getEffectiveGates(profile, overrides);
|
|
118825
119474
|
if (effective.hallucination_guard === true) {
|
|
118826
|
-
const hgPath =
|
|
119475
|
+
const hgPath = path146.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
118827
119476
|
let hgVerdictFound = false;
|
|
118828
119477
|
let hgVerdictApproved = false;
|
|
118829
119478
|
try {
|
|
@@ -118886,7 +119535,7 @@ init_qa_gate_profile();
|
|
|
118886
119535
|
init_manager();
|
|
118887
119536
|
init_state();
|
|
118888
119537
|
import * as fs107 from "node:fs";
|
|
118889
|
-
import * as
|
|
119538
|
+
import * as path147 from "node:path";
|
|
118890
119539
|
async function runMutationGate(ctx) {
|
|
118891
119540
|
const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
|
|
118892
119541
|
try {
|
|
@@ -118899,7 +119548,7 @@ async function runMutationGate(ctx) {
|
|
|
118899
119548
|
const overrides = session?.qaGateSessionOverrides ?? {};
|
|
118900
119549
|
const effective = getEffectiveGates(profile, overrides);
|
|
118901
119550
|
if (effective.mutation_test === true) {
|
|
118902
|
-
const mgPath =
|
|
119551
|
+
const mgPath = path147.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
118903
119552
|
let mgVerdictFound = false;
|
|
118904
119553
|
let mgVerdict;
|
|
118905
119554
|
try {
|
|
@@ -118962,7 +119611,7 @@ init_qa_gate_profile();
|
|
|
118962
119611
|
init_manager();
|
|
118963
119612
|
init_state();
|
|
118964
119613
|
import * as fs108 from "node:fs";
|
|
118965
|
-
import * as
|
|
119614
|
+
import * as path148 from "node:path";
|
|
118966
119615
|
async function runPhaseCouncilGate(ctx) {
|
|
118967
119616
|
const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
|
|
118968
119617
|
let councilModeEnabled = false;
|
|
@@ -118977,7 +119626,7 @@ async function runPhaseCouncilGate(ctx) {
|
|
|
118977
119626
|
const effective = getEffectiveGates(profile, overrides);
|
|
118978
119627
|
if (effective.council_mode === true) {
|
|
118979
119628
|
councilModeEnabled = true;
|
|
118980
|
-
const pcPath =
|
|
119629
|
+
const pcPath = path148.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
118981
119630
|
let pcVerdictFound = false;
|
|
118982
119631
|
let _pcVerdict;
|
|
118983
119632
|
let pcQuorumSize;
|
|
@@ -119469,7 +120118,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
119469
120118
|
phase_critic: leanConfig.phase_critic,
|
|
119470
120119
|
integrated_diff_required: leanConfig.integrated_diff_required
|
|
119471
120120
|
} : undefined;
|
|
119472
|
-
const leanCheck =
|
|
120121
|
+
const leanCheck = _internals68.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
|
|
119473
120122
|
if (!leanCheck.ok) {
|
|
119474
120123
|
return JSON.stringify({
|
|
119475
120124
|
success: false,
|
|
@@ -119492,7 +120141,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
119492
120141
|
}
|
|
119493
120142
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
119494
120143
|
try {
|
|
119495
|
-
const projectName =
|
|
120144
|
+
const projectName = path150.basename(dir);
|
|
119496
120145
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
119497
120146
|
if (curationResult) {
|
|
119498
120147
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -119935,7 +120584,7 @@ init_utils();
|
|
|
119935
120584
|
init_bun_compat();
|
|
119936
120585
|
init_create_tool();
|
|
119937
120586
|
import * as fs111 from "node:fs";
|
|
119938
|
-
import * as
|
|
120587
|
+
import * as path151 from "node:path";
|
|
119939
120588
|
var MAX_OUTPUT_BYTES6 = 52428800;
|
|
119940
120589
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
119941
120590
|
function isValidEcosystem(value) {
|
|
@@ -119963,16 +120612,16 @@ function validateArgs3(args2) {
|
|
|
119963
120612
|
function detectEcosystems(directory) {
|
|
119964
120613
|
const ecosystems = [];
|
|
119965
120614
|
const cwd = directory;
|
|
119966
|
-
if (fs111.existsSync(
|
|
120615
|
+
if (fs111.existsSync(path151.join(cwd, "package.json"))) {
|
|
119967
120616
|
ecosystems.push("npm");
|
|
119968
120617
|
}
|
|
119969
|
-
if (fs111.existsSync(
|
|
120618
|
+
if (fs111.existsSync(path151.join(cwd, "pyproject.toml")) || fs111.existsSync(path151.join(cwd, "requirements.txt"))) {
|
|
119970
120619
|
ecosystems.push("pip");
|
|
119971
120620
|
}
|
|
119972
|
-
if (fs111.existsSync(
|
|
120621
|
+
if (fs111.existsSync(path151.join(cwd, "Cargo.toml"))) {
|
|
119973
120622
|
ecosystems.push("cargo");
|
|
119974
120623
|
}
|
|
119975
|
-
if (fs111.existsSync(
|
|
120624
|
+
if (fs111.existsSync(path151.join(cwd, "go.mod"))) {
|
|
119976
120625
|
ecosystems.push("go");
|
|
119977
120626
|
}
|
|
119978
120627
|
try {
|
|
@@ -119981,13 +120630,13 @@ function detectEcosystems(directory) {
|
|
|
119981
120630
|
ecosystems.push("dotnet");
|
|
119982
120631
|
}
|
|
119983
120632
|
} catch {}
|
|
119984
|
-
if (fs111.existsSync(
|
|
120633
|
+
if (fs111.existsSync(path151.join(cwd, "Gemfile")) || fs111.existsSync(path151.join(cwd, "Gemfile.lock"))) {
|
|
119985
120634
|
ecosystems.push("ruby");
|
|
119986
120635
|
}
|
|
119987
|
-
if (fs111.existsSync(
|
|
120636
|
+
if (fs111.existsSync(path151.join(cwd, "pubspec.yaml"))) {
|
|
119988
120637
|
ecosystems.push("dart");
|
|
119989
120638
|
}
|
|
119990
|
-
if (fs111.existsSync(
|
|
120639
|
+
if (fs111.existsSync(path151.join(cwd, "composer.lock"))) {
|
|
119991
120640
|
ecosystems.push("composer");
|
|
119992
120641
|
}
|
|
119993
120642
|
return ecosystems;
|
|
@@ -120000,7 +120649,7 @@ async function runNpmAudit(directory) {
|
|
|
120000
120649
|
stderr: "pipe",
|
|
120001
120650
|
cwd: directory
|
|
120002
120651
|
});
|
|
120003
|
-
const timeoutPromise = new Promise((
|
|
120652
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120004
120653
|
const result = await Promise.race([
|
|
120005
120654
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
120006
120655
|
timeoutPromise
|
|
@@ -120120,7 +120769,7 @@ async function runPipAudit(directory) {
|
|
|
120120
120769
|
stderr: "pipe",
|
|
120121
120770
|
cwd: directory
|
|
120122
120771
|
});
|
|
120123
|
-
const timeoutPromise = new Promise((
|
|
120772
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120124
120773
|
const result = await Promise.race([
|
|
120125
120774
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
120126
120775
|
timeoutPromise
|
|
@@ -120248,7 +120897,7 @@ async function runCargoAudit(directory) {
|
|
|
120248
120897
|
stderr: "pipe",
|
|
120249
120898
|
cwd: directory
|
|
120250
120899
|
});
|
|
120251
|
-
const timeoutPromise = new Promise((
|
|
120900
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120252
120901
|
const result = await Promise.race([
|
|
120253
120902
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
120254
120903
|
timeoutPromise
|
|
@@ -120372,7 +121021,7 @@ async function runGoAudit(directory) {
|
|
|
120372
121021
|
stderr: "pipe",
|
|
120373
121022
|
cwd: directory
|
|
120374
121023
|
});
|
|
120375
|
-
const timeoutPromise = new Promise((
|
|
121024
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120376
121025
|
const result = await Promise.race([
|
|
120377
121026
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
120378
121027
|
timeoutPromise
|
|
@@ -120505,7 +121154,7 @@ async function runDotnetAudit(directory) {
|
|
|
120505
121154
|
stderr: "pipe",
|
|
120506
121155
|
cwd: directory
|
|
120507
121156
|
});
|
|
120508
|
-
const timeoutPromise = new Promise((
|
|
121157
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120509
121158
|
const result = await Promise.race([
|
|
120510
121159
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
120511
121160
|
timeoutPromise
|
|
@@ -120621,7 +121270,7 @@ async function runBundleAudit(directory) {
|
|
|
120621
121270
|
stderr: "pipe",
|
|
120622
121271
|
cwd: directory
|
|
120623
121272
|
});
|
|
120624
|
-
const timeoutPromise = new Promise((
|
|
121273
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120625
121274
|
const result = await Promise.race([
|
|
120626
121275
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
120627
121276
|
timeoutPromise
|
|
@@ -120766,7 +121415,7 @@ async function runDartAudit(directory) {
|
|
|
120766
121415
|
stderr: "pipe",
|
|
120767
121416
|
cwd: directory
|
|
120768
121417
|
});
|
|
120769
|
-
const timeoutPromise = new Promise((
|
|
121418
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120770
121419
|
const result = await Promise.race([
|
|
120771
121420
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
120772
121421
|
timeoutPromise
|
|
@@ -120881,7 +121530,7 @@ async function runComposerAudit(directory) {
|
|
|
120881
121530
|
stderr: "pipe",
|
|
120882
121531
|
cwd: directory
|
|
120883
121532
|
});
|
|
120884
|
-
const timeoutPromise = new Promise((
|
|
121533
|
+
const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
|
|
120885
121534
|
const result = await Promise.race([
|
|
120886
121535
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
120887
121536
|
timeoutPromise
|
|
@@ -121124,7 +121773,7 @@ var pkg_audit = createSwarmTool({
|
|
|
121124
121773
|
init_zod();
|
|
121125
121774
|
init_manager2();
|
|
121126
121775
|
import * as fs112 from "node:fs";
|
|
121127
|
-
import * as
|
|
121776
|
+
import * as path152 from "node:path";
|
|
121128
121777
|
init_utils();
|
|
121129
121778
|
init_create_tool();
|
|
121130
121779
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -121247,7 +121896,7 @@ function isScaffoldFile(filePath) {
|
|
|
121247
121896
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
121248
121897
|
return true;
|
|
121249
121898
|
}
|
|
121250
|
-
const filename =
|
|
121899
|
+
const filename = path152.basename(filePath);
|
|
121251
121900
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
121252
121901
|
return true;
|
|
121253
121902
|
}
|
|
@@ -121264,7 +121913,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
121264
121913
|
if (regex.test(normalizedPath)) {
|
|
121265
121914
|
return true;
|
|
121266
121915
|
}
|
|
121267
|
-
const filename =
|
|
121916
|
+
const filename = path152.basename(filePath);
|
|
121268
121917
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
121269
121918
|
if (filenameRegex.test(filename)) {
|
|
121270
121919
|
return true;
|
|
@@ -121273,7 +121922,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
121273
121922
|
return false;
|
|
121274
121923
|
}
|
|
121275
121924
|
function isParserSupported(filePath) {
|
|
121276
|
-
const ext =
|
|
121925
|
+
const ext = path152.extname(filePath).toLowerCase();
|
|
121277
121926
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
121278
121927
|
}
|
|
121279
121928
|
function isPlanFile(filePath) {
|
|
@@ -121520,9 +122169,9 @@ async function placeholderScan(input, directory) {
|
|
|
121520
122169
|
let filesScanned = 0;
|
|
121521
122170
|
const filesWithFindings = new Set;
|
|
121522
122171
|
for (const filePath of changed_files) {
|
|
121523
|
-
const fullPath =
|
|
121524
|
-
const resolvedDirectory =
|
|
121525
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
122172
|
+
const fullPath = path152.isAbsolute(filePath) ? filePath : path152.resolve(directory, filePath);
|
|
122173
|
+
const resolvedDirectory = path152.resolve(directory);
|
|
122174
|
+
if (!fullPath.startsWith(resolvedDirectory + path152.sep) && fullPath !== resolvedDirectory) {
|
|
121526
122175
|
continue;
|
|
121527
122176
|
}
|
|
121528
122177
|
if (!fs112.existsSync(fullPath)) {
|
|
@@ -121531,7 +122180,7 @@ async function placeholderScan(input, directory) {
|
|
|
121531
122180
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
121532
122181
|
continue;
|
|
121533
122182
|
}
|
|
121534
|
-
const relativeFilePath =
|
|
122183
|
+
const relativeFilePath = path152.relative(directory, fullPath).replace(/\\/g, "/");
|
|
121535
122184
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
121536
122185
|
continue;
|
|
121537
122186
|
}
|
|
@@ -121604,7 +122253,7 @@ var placeholder_scan = createSwarmTool({
|
|
|
121604
122253
|
|
|
121605
122254
|
// src/tools/pre-check-batch.ts
|
|
121606
122255
|
import * as fs116 from "node:fs";
|
|
121607
|
-
import * as
|
|
122256
|
+
import * as path156 from "node:path";
|
|
121608
122257
|
init_zod();
|
|
121609
122258
|
init_manager2();
|
|
121610
122259
|
init_utils();
|
|
@@ -121732,11 +122381,11 @@ var quality_budget = createSwarmTool({
|
|
|
121732
122381
|
}).optional().describe("Quality budget thresholds")
|
|
121733
122382
|
},
|
|
121734
122383
|
async execute(args2, directory) {
|
|
121735
|
-
const result = await
|
|
122384
|
+
const result = await _internals70.qualityBudget(args2, directory);
|
|
121736
122385
|
return JSON.stringify(result);
|
|
121737
122386
|
}
|
|
121738
122387
|
});
|
|
121739
|
-
var
|
|
122388
|
+
var _internals70 = {
|
|
121740
122389
|
qualityBudget
|
|
121741
122390
|
};
|
|
121742
122391
|
|
|
@@ -121745,7 +122394,7 @@ init_zod();
|
|
|
121745
122394
|
init_manager2();
|
|
121746
122395
|
init_detector();
|
|
121747
122396
|
import * as fs115 from "node:fs";
|
|
121748
|
-
import * as
|
|
122397
|
+
import * as path155 from "node:path";
|
|
121749
122398
|
import { extname as extname22 } from "node:path";
|
|
121750
122399
|
|
|
121751
122400
|
// src/sast/rules/c.ts
|
|
@@ -122455,13 +123104,13 @@ function executeRulesSync(filePath, content, language) {
|
|
|
122455
123104
|
// src/sast/semgrep.ts
|
|
122456
123105
|
import * as child_process10 from "node:child_process";
|
|
122457
123106
|
import * as fs113 from "node:fs";
|
|
122458
|
-
import * as
|
|
123107
|
+
import * as path153 from "node:path";
|
|
122459
123108
|
var semgrepAvailableCache = null;
|
|
122460
123109
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
122461
123110
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
122462
123111
|
var MAX_OUTPUT_BYTES7 = 10 * 1024 * 1024;
|
|
122463
123112
|
var KILL_GRACE_MS = 2000;
|
|
122464
|
-
var
|
|
123113
|
+
var _internals71 = {
|
|
122465
123114
|
isSemgrepAvailable,
|
|
122466
123115
|
checkSemgrepAvailable,
|
|
122467
123116
|
resetSemgrepCache,
|
|
@@ -122487,7 +123136,7 @@ function isSemgrepAvailable() {
|
|
|
122487
123136
|
}
|
|
122488
123137
|
}
|
|
122489
123138
|
async function checkSemgrepAvailable() {
|
|
122490
|
-
return
|
|
123139
|
+
return _internals71.isSemgrepAvailable();
|
|
122491
123140
|
}
|
|
122492
123141
|
function resetSemgrepCache() {
|
|
122493
123142
|
semgrepAvailableCache = null;
|
|
@@ -122540,7 +123189,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
122540
123189
|
}
|
|
122541
123190
|
async function executeWithTimeout(command, args2, options) {
|
|
122542
123191
|
const maxOutputBytes = options.maxOutputBytes ?? MAX_OUTPUT_BYTES7;
|
|
122543
|
-
return new Promise((
|
|
123192
|
+
return new Promise((resolve54) => {
|
|
122544
123193
|
const child = child_process10.spawn(command, args2, {
|
|
122545
123194
|
shell: false,
|
|
122546
123195
|
cwd: options.cwd,
|
|
@@ -122572,7 +123221,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
122572
123221
|
escalation.unref();
|
|
122573
123222
|
}
|
|
122574
123223
|
}
|
|
122575
|
-
|
|
123224
|
+
resolve54({ ...result, truncated });
|
|
122576
123225
|
};
|
|
122577
123226
|
timeout = setTimeout(() => {
|
|
122578
123227
|
settle({
|
|
@@ -122631,12 +123280,12 @@ async function runSemgrep(options) {
|
|
|
122631
123280
|
const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS3;
|
|
122632
123281
|
if (files.length === 0) {
|
|
122633
123282
|
return {
|
|
122634
|
-
available:
|
|
123283
|
+
available: _internals71.isSemgrepAvailable(),
|
|
122635
123284
|
findings: [],
|
|
122636
123285
|
engine: "tier_a"
|
|
122637
123286
|
};
|
|
122638
123287
|
}
|
|
122639
|
-
if (!
|
|
123288
|
+
if (!_internals71.isSemgrepAvailable()) {
|
|
122640
123289
|
return {
|
|
122641
123290
|
available: false,
|
|
122642
123291
|
findings: [],
|
|
@@ -122700,7 +123349,7 @@ async function runSemgrep(options) {
|
|
|
122700
123349
|
}
|
|
122701
123350
|
function getRulesDirectory(projectRoot) {
|
|
122702
123351
|
if (projectRoot) {
|
|
122703
|
-
return
|
|
123352
|
+
return path153.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
122704
123353
|
}
|
|
122705
123354
|
return DEFAULT_RULES_DIR;
|
|
122706
123355
|
}
|
|
@@ -122721,24 +123370,24 @@ init_create_tool();
|
|
|
122721
123370
|
init_utils2();
|
|
122722
123371
|
import * as crypto12 from "node:crypto";
|
|
122723
123372
|
import * as fs114 from "node:fs";
|
|
122724
|
-
import * as
|
|
123373
|
+
import * as path154 from "node:path";
|
|
122725
123374
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
122726
123375
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
122727
123376
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
122728
123377
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
122729
123378
|
function normalizeFindingPath(directory, file3) {
|
|
122730
|
-
const resolved =
|
|
122731
|
-
const rel =
|
|
123379
|
+
const resolved = path154.isAbsolute(file3) ? file3 : path154.resolve(directory, file3);
|
|
123380
|
+
const rel = path154.relative(path154.resolve(directory), resolved);
|
|
122732
123381
|
return rel.replace(/\\/g, "/");
|
|
122733
123382
|
}
|
|
122734
123383
|
function baselineRelPath(phase) {
|
|
122735
|
-
return
|
|
123384
|
+
return path154.join("evidence", String(phase), "sast-baseline.json");
|
|
122736
123385
|
}
|
|
122737
123386
|
function tempRelPath(phase) {
|
|
122738
|
-
return
|
|
123387
|
+
return path154.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
122739
123388
|
}
|
|
122740
123389
|
function lockRelPath(phase) {
|
|
122741
|
-
return
|
|
123390
|
+
return path154.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
122742
123391
|
}
|
|
122743
123392
|
function getLine(lines, idx) {
|
|
122744
123393
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -122803,7 +123452,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
122803
123452
|
}
|
|
122804
123453
|
const occIdx = countMap.get(baseKey) ?? 0;
|
|
122805
123454
|
countMap.set(baseKey, occIdx + 1);
|
|
122806
|
-
const fp =
|
|
123455
|
+
const fp = _internals72.fingerprintFinding(finding, directory, occIdx);
|
|
122807
123456
|
return {
|
|
122808
123457
|
finding,
|
|
122809
123458
|
index: occIdx,
|
|
@@ -122824,7 +123473,7 @@ async function acquireLock2(lockPath) {
|
|
|
122824
123473
|
};
|
|
122825
123474
|
} catch {
|
|
122826
123475
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
122827
|
-
await new Promise((
|
|
123476
|
+
await new Promise((resolve55) => setTimeout(resolve55, LOCK_RETRY_DELAYS_MS[attempt]));
|
|
122828
123477
|
}
|
|
122829
123478
|
}
|
|
122830
123479
|
}
|
|
@@ -122859,8 +123508,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
122859
123508
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
122860
123509
|
};
|
|
122861
123510
|
}
|
|
122862
|
-
fs114.mkdirSync(
|
|
122863
|
-
fs114.mkdirSync(
|
|
123511
|
+
fs114.mkdirSync(path154.dirname(baselinePath), { recursive: true });
|
|
123512
|
+
fs114.mkdirSync(path154.dirname(tempPath), { recursive: true });
|
|
122864
123513
|
const releaseLock = await acquireLock2(lockPath);
|
|
122865
123514
|
try {
|
|
122866
123515
|
let existing = null;
|
|
@@ -122872,7 +123521,7 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
122872
123521
|
}
|
|
122873
123522
|
} catch {}
|
|
122874
123523
|
const scannedRelFiles = new Set(scannedFiles.map((f) => normalizeFindingPath(directory, f)));
|
|
122875
|
-
const indexed =
|
|
123524
|
+
const indexed = _internals72.assignOccurrenceIndices(findings, directory);
|
|
122876
123525
|
if (existing && !opts?.force) {
|
|
122877
123526
|
const prunedFingerprints = existing.fingerprints.filter((fp) => {
|
|
122878
123527
|
const relFile = fp.slice(0, fp.indexOf("|"));
|
|
@@ -123012,7 +123661,7 @@ function loadBaseline(directory, phase) {
|
|
|
123012
123661
|
};
|
|
123013
123662
|
}
|
|
123014
123663
|
}
|
|
123015
|
-
var
|
|
123664
|
+
var _internals72 = {
|
|
123016
123665
|
fingerprintFinding,
|
|
123017
123666
|
assignOccurrenceIndices,
|
|
123018
123667
|
captureOrMergeBaseline,
|
|
@@ -123133,9 +123782,9 @@ async function sastScan(input, directory, config3) {
|
|
|
123133
123782
|
_filesSkipped++;
|
|
123134
123783
|
continue;
|
|
123135
123784
|
}
|
|
123136
|
-
const resolvedPath =
|
|
123137
|
-
const resolvedDirectory =
|
|
123138
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
123785
|
+
const resolvedPath = path155.isAbsolute(filePath) ? filePath : path155.resolve(directory, filePath);
|
|
123786
|
+
const resolvedDirectory = path155.resolve(directory);
|
|
123787
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path155.sep) && resolvedPath !== resolvedDirectory) {
|
|
123139
123788
|
_filesSkipped++;
|
|
123140
123789
|
continue;
|
|
123141
123790
|
}
|
|
@@ -123422,11 +124071,11 @@ var sast_scan = createSwarmTool({
|
|
|
123422
124071
|
capture_baseline: safeArgs.capture_baseline,
|
|
123423
124072
|
phase: safeArgs.phase
|
|
123424
124073
|
};
|
|
123425
|
-
const result = await
|
|
124074
|
+
const result = await _internals73.sastScan(input, directory);
|
|
123426
124075
|
return JSON.stringify(result, null, 2);
|
|
123427
124076
|
}
|
|
123428
124077
|
});
|
|
123429
|
-
var
|
|
124078
|
+
var _internals73 = {
|
|
123430
124079
|
sastScan,
|
|
123431
124080
|
sast_scan
|
|
123432
124081
|
};
|
|
@@ -123450,18 +124099,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
123450
124099
|
let resolved;
|
|
123451
124100
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
123452
124101
|
if (isWinAbs) {
|
|
123453
|
-
resolved =
|
|
123454
|
-
} else if (
|
|
123455
|
-
resolved =
|
|
124102
|
+
resolved = path156.win32.resolve(inputPath);
|
|
124103
|
+
} else if (path156.isAbsolute(inputPath)) {
|
|
124104
|
+
resolved = path156.resolve(inputPath);
|
|
123456
124105
|
} else {
|
|
123457
|
-
resolved =
|
|
124106
|
+
resolved = path156.resolve(baseDir, inputPath);
|
|
123458
124107
|
}
|
|
123459
|
-
const workspaceResolved =
|
|
124108
|
+
const workspaceResolved = path156.resolve(workspaceDir);
|
|
123460
124109
|
let relative31;
|
|
123461
124110
|
if (isWinAbs) {
|
|
123462
|
-
relative31 =
|
|
124111
|
+
relative31 = path156.win32.relative(workspaceResolved, resolved);
|
|
123463
124112
|
} else {
|
|
123464
|
-
relative31 =
|
|
124113
|
+
relative31 = path156.relative(workspaceResolved, resolved);
|
|
123465
124114
|
}
|
|
123466
124115
|
if (relative31.startsWith("..")) {
|
|
123467
124116
|
return "path traversal detected";
|
|
@@ -123526,7 +124175,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
123526
124175
|
if (typeof file3 !== "string") {
|
|
123527
124176
|
continue;
|
|
123528
124177
|
}
|
|
123529
|
-
const resolvedPath =
|
|
124178
|
+
const resolvedPath = path156.resolve(file3);
|
|
123530
124179
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
123531
124180
|
if (validationError) {
|
|
123532
124181
|
continue;
|
|
@@ -123683,7 +124332,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
123683
124332
|
skippedFiles++;
|
|
123684
124333
|
continue;
|
|
123685
124334
|
}
|
|
123686
|
-
const resolvedPath =
|
|
124335
|
+
const resolvedPath = path156.resolve(file3);
|
|
123687
124336
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
123688
124337
|
if (validationError) {
|
|
123689
124338
|
skippedFiles++;
|
|
@@ -123701,7 +124350,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
123701
124350
|
};
|
|
123702
124351
|
}
|
|
123703
124352
|
for (const file3 of validatedFiles) {
|
|
123704
|
-
const ext =
|
|
124353
|
+
const ext = path156.extname(file3).toLowerCase();
|
|
123705
124354
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
123706
124355
|
skippedFiles++;
|
|
123707
124356
|
continue;
|
|
@@ -123920,7 +124569,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
123920
124569
|
const preexistingFindings = [];
|
|
123921
124570
|
for (const finding of findings) {
|
|
123922
124571
|
const filePath = finding.location.file;
|
|
123923
|
-
const normalised =
|
|
124572
|
+
const normalised = path156.relative(directory, filePath).replace(/\\/g, "/");
|
|
123924
124573
|
const changedLines = changedLineRanges.get(normalised);
|
|
123925
124574
|
if (changedLines?.has(finding.location.line)) {
|
|
123926
124575
|
newFindings.push(finding);
|
|
@@ -123971,7 +124620,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
123971
124620
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
123972
124621
|
continue;
|
|
123973
124622
|
}
|
|
123974
|
-
changedFiles.push(
|
|
124623
|
+
changedFiles.push(path156.resolve(directory, file3));
|
|
123975
124624
|
}
|
|
123976
124625
|
if (changedFiles.length === 0) {
|
|
123977
124626
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -124172,9 +124821,9 @@ var pre_check_batch = createSwarmTool({
|
|
|
124172
124821
|
};
|
|
124173
124822
|
return JSON.stringify(errorResult, null, 2);
|
|
124174
124823
|
}
|
|
124175
|
-
const resolvedDirectory =
|
|
124176
|
-
const workspaceAnchor =
|
|
124177
|
-
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor +
|
|
124824
|
+
const resolvedDirectory = path156.resolve(typedArgs.directory);
|
|
124825
|
+
const workspaceAnchor = path156.resolve(directory);
|
|
124826
|
+
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path156.sep)) {
|
|
124178
124827
|
const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
|
|
124179
124828
|
const subDirResult = {
|
|
124180
124829
|
gates_passed: false,
|
|
@@ -124226,7 +124875,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
124226
124875
|
|
|
124227
124876
|
// src/tools/repo-map.ts
|
|
124228
124877
|
init_zod();
|
|
124229
|
-
import * as
|
|
124878
|
+
import * as path157 from "node:path";
|
|
124230
124879
|
init_path_security();
|
|
124231
124880
|
init_create_tool();
|
|
124232
124881
|
var VALID_ACTIONS = [
|
|
@@ -124251,7 +124900,7 @@ function validateFile(p) {
|
|
|
124251
124900
|
return "file contains control characters";
|
|
124252
124901
|
if (containsPathTraversal(p))
|
|
124253
124902
|
return "file contains path traversal";
|
|
124254
|
-
if (
|
|
124903
|
+
if (path157.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
124255
124904
|
return "file must be a workspace-relative path, not absolute";
|
|
124256
124905
|
}
|
|
124257
124906
|
return null;
|
|
@@ -124274,8 +124923,8 @@ function ok(action, payload) {
|
|
|
124274
124923
|
}
|
|
124275
124924
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
124276
124925
|
const normalized = input.replace(/\\/g, "/");
|
|
124277
|
-
if (
|
|
124278
|
-
const rel =
|
|
124926
|
+
if (path157.isAbsolute(normalized)) {
|
|
124927
|
+
const rel = path157.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
124279
124928
|
return normalizeGraphPath2(rel);
|
|
124280
124929
|
}
|
|
124281
124930
|
return normalizeGraphPath2(normalized);
|
|
@@ -124421,7 +125070,7 @@ var repo_map = createSwarmTool({
|
|
|
124421
125070
|
init_zod();
|
|
124422
125071
|
init_create_tool();
|
|
124423
125072
|
import * as fs117 from "node:fs";
|
|
124424
|
-
import * as
|
|
125073
|
+
import * as path158 from "node:path";
|
|
124425
125074
|
var SPEC_FILE = ".swarm/spec.md";
|
|
124426
125075
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
124427
125076
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -124490,7 +125139,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
124490
125139
|
return [];
|
|
124491
125140
|
}
|
|
124492
125141
|
for (const entry of entries) {
|
|
124493
|
-
const entryPath =
|
|
125142
|
+
const entryPath = path158.join(evidenceDir, entry);
|
|
124494
125143
|
try {
|
|
124495
125144
|
const stat9 = fs117.statSync(entryPath);
|
|
124496
125145
|
if (!stat9.isDirectory()) {
|
|
@@ -124506,11 +125155,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
124506
125155
|
if (entryPhase !== String(phase)) {
|
|
124507
125156
|
continue;
|
|
124508
125157
|
}
|
|
124509
|
-
const evidenceFilePath =
|
|
125158
|
+
const evidenceFilePath = path158.join(entryPath, "evidence.json");
|
|
124510
125159
|
try {
|
|
124511
|
-
const resolvedPath =
|
|
124512
|
-
const evidenceDirResolved =
|
|
124513
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
125160
|
+
const resolvedPath = path158.resolve(evidenceFilePath);
|
|
125161
|
+
const evidenceDirResolved = path158.resolve(evidenceDir);
|
|
125162
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path158.sep)) {
|
|
124514
125163
|
continue;
|
|
124515
125164
|
}
|
|
124516
125165
|
const stat9 = fs117.lstatSync(evidenceFilePath);
|
|
@@ -124544,7 +125193,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
124544
125193
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
124545
125194
|
for (const file3 of diffEntry.files_changed) {
|
|
124546
125195
|
if (typeof file3 === "string") {
|
|
124547
|
-
touchedFiles.add(
|
|
125196
|
+
touchedFiles.add(path158.resolve(cwd, file3));
|
|
124548
125197
|
}
|
|
124549
125198
|
}
|
|
124550
125199
|
}
|
|
@@ -124557,8 +125206,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
124557
125206
|
}
|
|
124558
125207
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
124559
125208
|
try {
|
|
124560
|
-
const resolvedPath =
|
|
124561
|
-
const cwdResolved =
|
|
125209
|
+
const resolvedPath = path158.resolve(filePath);
|
|
125210
|
+
const cwdResolved = path158.resolve(cwd);
|
|
124562
125211
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
124563
125212
|
return false;
|
|
124564
125213
|
}
|
|
@@ -124692,7 +125341,7 @@ var req_coverage = createSwarmTool({
|
|
|
124692
125341
|
}, null, 2);
|
|
124693
125342
|
}
|
|
124694
125343
|
const cwd = inputDirectory || directory;
|
|
124695
|
-
const specPath =
|
|
125344
|
+
const specPath = path158.join(cwd, SPEC_FILE);
|
|
124696
125345
|
let specContent;
|
|
124697
125346
|
try {
|
|
124698
125347
|
specContent = fs117.readFileSync(specPath, "utf-8");
|
|
@@ -124719,7 +125368,7 @@ var req_coverage = createSwarmTool({
|
|
|
124719
125368
|
message: "No FR requirements found in spec.md"
|
|
124720
125369
|
}, null, 2);
|
|
124721
125370
|
}
|
|
124722
|
-
const evidenceDir =
|
|
125371
|
+
const evidenceDir = path158.join(cwd, EVIDENCE_DIR4);
|
|
124723
125372
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
124724
125373
|
const analyzedRequirements = [];
|
|
124725
125374
|
let coveredCount = 0;
|
|
@@ -124745,7 +125394,7 @@ var req_coverage = createSwarmTool({
|
|
|
124745
125394
|
requirements: analyzedRequirements
|
|
124746
125395
|
};
|
|
124747
125396
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
124748
|
-
const reportPath =
|
|
125397
|
+
const reportPath = path158.join(evidenceDir, reportFilename);
|
|
124749
125398
|
try {
|
|
124750
125399
|
if (!fs117.existsSync(evidenceDir)) {
|
|
124751
125400
|
fs117.mkdirSync(evidenceDir, { recursive: true });
|
|
@@ -124835,7 +125484,7 @@ init_qa_gate_profile();
|
|
|
124835
125484
|
init_file_locks();
|
|
124836
125485
|
import * as crypto13 from "node:crypto";
|
|
124837
125486
|
import * as fs118 from "node:fs";
|
|
124838
|
-
import * as
|
|
125487
|
+
import * as path159 from "node:path";
|
|
124839
125488
|
init_ledger();
|
|
124840
125489
|
init_manager();
|
|
124841
125490
|
init_state();
|
|
@@ -124916,8 +125565,8 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
124916
125565
|
};
|
|
124917
125566
|
}
|
|
124918
125567
|
if (args2.working_directory && fallbackDir) {
|
|
124919
|
-
const resolvedTarget =
|
|
124920
|
-
const resolvedRoot =
|
|
125568
|
+
const resolvedTarget = path159.resolve(args2.working_directory);
|
|
125569
|
+
const resolvedRoot = path159.resolve(fallbackDir);
|
|
124921
125570
|
let fallbackExists = false;
|
|
124922
125571
|
try {
|
|
124923
125572
|
fs118.accessSync(resolvedRoot, fs118.constants.F_OK);
|
|
@@ -124926,7 +125575,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
124926
125575
|
fallbackExists = false;
|
|
124927
125576
|
}
|
|
124928
125577
|
if (fallbackExists) {
|
|
124929
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
125578
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path159.sep);
|
|
124930
125579
|
if (isSubdirectory) {
|
|
124931
125580
|
return {
|
|
124932
125581
|
success: false,
|
|
@@ -124942,7 +125591,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
124942
125591
|
let specMtime;
|
|
124943
125592
|
let specHash;
|
|
124944
125593
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
124945
|
-
const specPath =
|
|
125594
|
+
const specPath = path159.join(targetWorkspace, ".swarm", "spec.md");
|
|
124946
125595
|
try {
|
|
124947
125596
|
const stat9 = await fs118.promises.stat(specPath);
|
|
124948
125597
|
specMtime = stat9.mtime.toISOString();
|
|
@@ -124958,7 +125607,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
124958
125607
|
}
|
|
124959
125608
|
}
|
|
124960
125609
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
124961
|
-
const contextPath =
|
|
125610
|
+
const contextPath = path159.join(targetWorkspace, ".swarm", "context.md");
|
|
124962
125611
|
let contextContent = "";
|
|
124963
125612
|
try {
|
|
124964
125613
|
contextContent = await fs118.promises.readFile(contextPath, "utf8");
|
|
@@ -125248,7 +125897,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
125248
125897
|
}
|
|
125249
125898
|
await writeCheckpoint(dir).catch(() => {});
|
|
125250
125899
|
try {
|
|
125251
|
-
const markerPath =
|
|
125900
|
+
const markerPath = path159.join(dir, ".swarm", ".plan-write-marker");
|
|
125252
125901
|
const marker = JSON.stringify({
|
|
125253
125902
|
source: "save_plan",
|
|
125254
125903
|
timestamp: new Date().toISOString(),
|
|
@@ -125271,7 +125920,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
125271
125920
|
return {
|
|
125272
125921
|
success: true,
|
|
125273
125922
|
message: "Plan saved successfully",
|
|
125274
|
-
plan_path:
|
|
125923
|
+
plan_path: path159.join(dir, ".swarm", "plan.json"),
|
|
125275
125924
|
phases_count: plan.phases.length,
|
|
125276
125925
|
tasks_count: tasksCount,
|
|
125277
125926
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -125338,7 +125987,7 @@ var save_plan = createSwarmTool({
|
|
|
125338
125987
|
init_zod();
|
|
125339
125988
|
init_manager2();
|
|
125340
125989
|
import * as fs119 from "node:fs";
|
|
125341
|
-
import * as
|
|
125990
|
+
import * as path160 from "node:path";
|
|
125342
125991
|
|
|
125343
125992
|
// src/sbom/detectors/index.ts
|
|
125344
125993
|
init_utils();
|
|
@@ -126188,7 +126837,7 @@ function findManifestFiles(rootDir) {
|
|
|
126188
126837
|
try {
|
|
126189
126838
|
const entries = fs119.readdirSync(dir, { withFileTypes: true });
|
|
126190
126839
|
for (const entry of entries) {
|
|
126191
|
-
const fullPath =
|
|
126840
|
+
const fullPath = path160.join(dir, entry.name);
|
|
126192
126841
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
126193
126842
|
continue;
|
|
126194
126843
|
}
|
|
@@ -126197,7 +126846,7 @@ function findManifestFiles(rootDir) {
|
|
|
126197
126846
|
} else if (entry.isFile()) {
|
|
126198
126847
|
for (const pattern of patterns) {
|
|
126199
126848
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
126200
|
-
manifestFiles.push(
|
|
126849
|
+
manifestFiles.push(path160.relative(rootDir, fullPath));
|
|
126201
126850
|
break;
|
|
126202
126851
|
}
|
|
126203
126852
|
}
|
|
@@ -126215,11 +126864,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
126215
126864
|
try {
|
|
126216
126865
|
const entries = fs119.readdirSync(dir, { withFileTypes: true });
|
|
126217
126866
|
for (const entry of entries) {
|
|
126218
|
-
const fullPath =
|
|
126867
|
+
const fullPath = path160.join(dir, entry.name);
|
|
126219
126868
|
if (entry.isFile()) {
|
|
126220
126869
|
for (const pattern of patterns) {
|
|
126221
126870
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
126222
|
-
found.push(
|
|
126871
|
+
found.push(path160.relative(workingDir, fullPath));
|
|
126223
126872
|
break;
|
|
126224
126873
|
}
|
|
126225
126874
|
}
|
|
@@ -126232,11 +126881,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
126232
126881
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
126233
126882
|
const dirs = new Set;
|
|
126234
126883
|
for (const file3 of changedFiles) {
|
|
126235
|
-
let currentDir =
|
|
126884
|
+
let currentDir = path160.dirname(file3);
|
|
126236
126885
|
while (true) {
|
|
126237
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
126238
|
-
dirs.add(
|
|
126239
|
-
const parent =
|
|
126886
|
+
if (currentDir && currentDir !== "." && currentDir !== path160.sep) {
|
|
126887
|
+
dirs.add(path160.join(workingDir, currentDir));
|
|
126888
|
+
const parent = path160.dirname(currentDir);
|
|
126240
126889
|
if (parent === currentDir)
|
|
126241
126890
|
break;
|
|
126242
126891
|
currentDir = parent;
|
|
@@ -126320,7 +126969,7 @@ var sbom_generate = createSwarmTool({
|
|
|
126320
126969
|
const changedFiles = obj.changed_files;
|
|
126321
126970
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
126322
126971
|
const workingDir = directory;
|
|
126323
|
-
const outputDir =
|
|
126972
|
+
const outputDir = path160.isAbsolute(relativeOutputDir) ? relativeOutputDir : path160.join(workingDir, relativeOutputDir);
|
|
126324
126973
|
let manifestFiles = [];
|
|
126325
126974
|
if (scope === "all") {
|
|
126326
126975
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -126343,7 +126992,7 @@ var sbom_generate = createSwarmTool({
|
|
|
126343
126992
|
const processedFiles = [];
|
|
126344
126993
|
for (const manifestFile of manifestFiles) {
|
|
126345
126994
|
try {
|
|
126346
|
-
const fullPath =
|
|
126995
|
+
const fullPath = path160.isAbsolute(manifestFile) ? manifestFile : path160.join(workingDir, manifestFile);
|
|
126347
126996
|
if (!fs119.existsSync(fullPath)) {
|
|
126348
126997
|
continue;
|
|
126349
126998
|
}
|
|
@@ -126360,7 +127009,7 @@ var sbom_generate = createSwarmTool({
|
|
|
126360
127009
|
const bom = generateCycloneDX(allComponents);
|
|
126361
127010
|
const bomJson = serializeCycloneDX(bom);
|
|
126362
127011
|
const filename = generateSbomFilename();
|
|
126363
|
-
const outputPath =
|
|
127012
|
+
const outputPath = path160.join(outputDir, filename);
|
|
126364
127013
|
fs119.writeFileSync(outputPath, bomJson, "utf-8");
|
|
126365
127014
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
126366
127015
|
try {
|
|
@@ -126405,7 +127054,7 @@ var sbom_generate = createSwarmTool({
|
|
|
126405
127054
|
init_zod();
|
|
126406
127055
|
init_create_tool();
|
|
126407
127056
|
import * as fs120 from "node:fs";
|
|
126408
|
-
import * as
|
|
127057
|
+
import * as path161 from "node:path";
|
|
126409
127058
|
var SPEC_CANDIDATES = [
|
|
126410
127059
|
"openapi.json",
|
|
126411
127060
|
"openapi.yaml",
|
|
@@ -126437,12 +127086,12 @@ function normalizePath5(p) {
|
|
|
126437
127086
|
}
|
|
126438
127087
|
function discoverSpecFile(cwd, specFileArg) {
|
|
126439
127088
|
if (specFileArg) {
|
|
126440
|
-
const resolvedPath =
|
|
126441
|
-
const normalizedCwd = cwd.endsWith(
|
|
127089
|
+
const resolvedPath = path161.resolve(cwd, specFileArg);
|
|
127090
|
+
const normalizedCwd = cwd.endsWith(path161.sep) ? cwd : cwd + path161.sep;
|
|
126442
127091
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
126443
127092
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
126444
127093
|
}
|
|
126445
|
-
const ext =
|
|
127094
|
+
const ext = path161.extname(resolvedPath).toLowerCase();
|
|
126446
127095
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
126447
127096
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
126448
127097
|
}
|
|
@@ -126456,7 +127105,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
126456
127105
|
return resolvedPath;
|
|
126457
127106
|
}
|
|
126458
127107
|
for (const candidate of SPEC_CANDIDATES) {
|
|
126459
|
-
const candidatePath =
|
|
127108
|
+
const candidatePath = path161.resolve(cwd, candidate);
|
|
126460
127109
|
if (fs120.existsSync(candidatePath)) {
|
|
126461
127110
|
const stats = fs120.statSync(candidatePath);
|
|
126462
127111
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -126468,7 +127117,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
126468
127117
|
}
|
|
126469
127118
|
function parseSpec(specFile) {
|
|
126470
127119
|
const content = fs120.readFileSync(specFile, "utf-8");
|
|
126471
|
-
const ext =
|
|
127120
|
+
const ext = path161.extname(specFile).toLowerCase();
|
|
126472
127121
|
if (ext === ".json") {
|
|
126473
127122
|
return parseJsonSpec(content);
|
|
126474
127123
|
}
|
|
@@ -126544,7 +127193,7 @@ function extractRoutes(cwd) {
|
|
|
126544
127193
|
return;
|
|
126545
127194
|
}
|
|
126546
127195
|
for (const entry of entries) {
|
|
126547
|
-
const fullPath =
|
|
127196
|
+
const fullPath = path161.join(dir, entry.name);
|
|
126548
127197
|
if (entry.isSymbolicLink()) {
|
|
126549
127198
|
continue;
|
|
126550
127199
|
}
|
|
@@ -126554,7 +127203,7 @@ function extractRoutes(cwd) {
|
|
|
126554
127203
|
}
|
|
126555
127204
|
walkDir2(fullPath);
|
|
126556
127205
|
} else if (entry.isFile()) {
|
|
126557
|
-
const ext =
|
|
127206
|
+
const ext = path161.extname(entry.name).toLowerCase();
|
|
126558
127207
|
const baseName = entry.name.toLowerCase();
|
|
126559
127208
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
126560
127209
|
continue;
|
|
@@ -126723,7 +127372,7 @@ init_bun_compat();
|
|
|
126723
127372
|
init_path_security();
|
|
126724
127373
|
init_create_tool();
|
|
126725
127374
|
import * as fs121 from "node:fs";
|
|
126726
|
-
import * as
|
|
127375
|
+
import * as path162 from "node:path";
|
|
126727
127376
|
var DEFAULT_MAX_RESULTS = 100;
|
|
126728
127377
|
var DEFAULT_MAX_LINES = 200;
|
|
126729
127378
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -126759,11 +127408,11 @@ function containsWindowsAttacks4(str) {
|
|
|
126759
127408
|
}
|
|
126760
127409
|
function isPathInWorkspace3(filePath, workspace) {
|
|
126761
127410
|
try {
|
|
126762
|
-
const resolvedPath =
|
|
127411
|
+
const resolvedPath = path162.resolve(workspace, filePath);
|
|
126763
127412
|
const realWorkspace = fs121.realpathSync(workspace);
|
|
126764
127413
|
const realResolvedPath = fs121.realpathSync(resolvedPath);
|
|
126765
|
-
const relativePath =
|
|
126766
|
-
if (relativePath.startsWith("..") ||
|
|
127414
|
+
const relativePath = path162.relative(realWorkspace, realResolvedPath);
|
|
127415
|
+
if (relativePath.startsWith("..") || path162.isAbsolute(relativePath)) {
|
|
126767
127416
|
return false;
|
|
126768
127417
|
}
|
|
126769
127418
|
return true;
|
|
@@ -126776,11 +127425,11 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
126776
127425
|
}
|
|
126777
127426
|
function findRgInEnvPath() {
|
|
126778
127427
|
const searchPath = process.env.PATH ?? "";
|
|
126779
|
-
for (const dir of searchPath.split(
|
|
127428
|
+
for (const dir of searchPath.split(path162.delimiter)) {
|
|
126780
127429
|
if (!dir)
|
|
126781
127430
|
continue;
|
|
126782
127431
|
const isWindows = process.platform === "win32";
|
|
126783
|
-
const candidate =
|
|
127432
|
+
const candidate = path162.join(dir, isWindows ? "rg.exe" : "rg");
|
|
126784
127433
|
if (fs121.existsSync(candidate))
|
|
126785
127434
|
return candidate;
|
|
126786
127435
|
}
|
|
@@ -126835,7 +127484,7 @@ async function ripgrepSearch(opts) {
|
|
|
126835
127484
|
stderr: "pipe",
|
|
126836
127485
|
cwd: opts.workspace
|
|
126837
127486
|
});
|
|
126838
|
-
const timeout = new Promise((
|
|
127487
|
+
const timeout = new Promise((resolve61) => setTimeout(() => resolve61("timeout"), REGEX_TIMEOUT_MS));
|
|
126839
127488
|
const exitPromise = proc.exited;
|
|
126840
127489
|
const result = await Promise.race([exitPromise, timeout]);
|
|
126841
127490
|
if (result === "timeout") {
|
|
@@ -126910,8 +127559,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
126910
127559
|
try {
|
|
126911
127560
|
const entries = fs121.readdirSync(dir, { withFileTypes: true });
|
|
126912
127561
|
for (const entry of entries) {
|
|
126913
|
-
const fullPath =
|
|
126914
|
-
const relativePath =
|
|
127562
|
+
const fullPath = path162.join(dir, entry.name);
|
|
127563
|
+
const relativePath = path162.relative(workspace, fullPath);
|
|
126915
127564
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
126916
127565
|
continue;
|
|
126917
127566
|
}
|
|
@@ -126952,7 +127601,7 @@ async function fallbackSearch(opts) {
|
|
|
126952
127601
|
const matches = [];
|
|
126953
127602
|
let total = 0;
|
|
126954
127603
|
for (const file3 of files) {
|
|
126955
|
-
const fullPath =
|
|
127604
|
+
const fullPath = path162.join(opts.workspace, file3);
|
|
126956
127605
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
126957
127606
|
continue;
|
|
126958
127607
|
}
|
|
@@ -127365,7 +128014,7 @@ init_config();
|
|
|
127365
128014
|
init_schema();
|
|
127366
128015
|
init_create_tool();
|
|
127367
128016
|
import { mkdir as mkdir23, rename as rename10, writeFile as writeFile16 } from "node:fs/promises";
|
|
127368
|
-
import * as
|
|
128017
|
+
import * as path163 from "node:path";
|
|
127369
128018
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
127370
128019
|
var spec_write = createSwarmTool({
|
|
127371
128020
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -127406,8 +128055,8 @@ var spec_write = createSwarmTool({
|
|
|
127406
128055
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
127407
128056
|
}, null, 2);
|
|
127408
128057
|
}
|
|
127409
|
-
const target =
|
|
127410
|
-
await mkdir23(
|
|
128058
|
+
const target = path163.join(directory, ".swarm", "spec.md");
|
|
128059
|
+
await mkdir23(path163.dirname(target), { recursive: true });
|
|
127411
128060
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
127412
128061
|
let finalContent = content;
|
|
127413
128062
|
if (mode === "append") {
|
|
@@ -127443,7 +128092,7 @@ import {
|
|
|
127443
128092
|
unlinkSync as unlinkSync21,
|
|
127444
128093
|
writeFileSync as writeFileSync32
|
|
127445
128094
|
} from "node:fs";
|
|
127446
|
-
import
|
|
128095
|
+
import path164 from "node:path";
|
|
127447
128096
|
init_create_tool();
|
|
127448
128097
|
init_resolve_working_directory();
|
|
127449
128098
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -127587,7 +128236,7 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
127587
128236
|
}
|
|
127588
128237
|
});
|
|
127589
128238
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
127590
|
-
const mutationGatePath =
|
|
128239
|
+
const mutationGatePath = path164.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
127591
128240
|
try {
|
|
127592
128241
|
const raw = readFileSync81(mutationGatePath, "utf-8");
|
|
127593
128242
|
const parsed = JSON.parse(raw);
|
|
@@ -127649,9 +128298,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
127649
128298
|
}
|
|
127650
128299
|
}
|
|
127651
128300
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
127652
|
-
const evidenceDir =
|
|
128301
|
+
const evidenceDir = path164.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
127653
128302
|
mkdirSync41(evidenceDir, { recursive: true });
|
|
127654
|
-
const evidenceFile =
|
|
128303
|
+
const evidenceFile = path164.join(evidenceDir, "phase-council.json");
|
|
127655
128304
|
const evidenceBundle = {
|
|
127656
128305
|
entries: [
|
|
127657
128306
|
{
|
|
@@ -127713,7 +128362,7 @@ init_zod();
|
|
|
127713
128362
|
init_path_security();
|
|
127714
128363
|
init_create_tool();
|
|
127715
128364
|
import * as fs122 from "node:fs";
|
|
127716
|
-
import * as
|
|
128365
|
+
import * as path165 from "node:path";
|
|
127717
128366
|
var BINARY_EXTENSIONS2 = new Set([
|
|
127718
128367
|
".png",
|
|
127719
128368
|
".jpg",
|
|
@@ -127749,14 +128398,14 @@ function containsWindowsAttacks5(str) {
|
|
|
127749
128398
|
}
|
|
127750
128399
|
function isPathInWorkspace4(filePath, workspace) {
|
|
127751
128400
|
try {
|
|
127752
|
-
const resolvedPath =
|
|
128401
|
+
const resolvedPath = path165.resolve(workspace, filePath);
|
|
127753
128402
|
if (!fs122.existsSync(resolvedPath)) {
|
|
127754
128403
|
return true;
|
|
127755
128404
|
}
|
|
127756
128405
|
const realWorkspace = fs122.realpathSync(workspace);
|
|
127757
128406
|
const realResolvedPath = fs122.realpathSync(resolvedPath);
|
|
127758
|
-
const relativePath =
|
|
127759
|
-
if (relativePath.startsWith("..") ||
|
|
128407
|
+
const relativePath = path165.relative(realWorkspace, realResolvedPath);
|
|
128408
|
+
if (relativePath.startsWith("..") || path165.isAbsolute(relativePath)) {
|
|
127760
128409
|
return false;
|
|
127761
128410
|
}
|
|
127762
128411
|
return true;
|
|
@@ -127871,7 +128520,7 @@ function arraysEqual2(a, b) {
|
|
|
127871
128520
|
return true;
|
|
127872
128521
|
}
|
|
127873
128522
|
function isBinaryFile4(filePath) {
|
|
127874
|
-
const ext =
|
|
128523
|
+
const ext = path165.extname(filePath).toLowerCase();
|
|
127875
128524
|
return BINARY_EXTENSIONS2.has(ext);
|
|
127876
128525
|
}
|
|
127877
128526
|
function splitDiffLines(content) {
|
|
@@ -128076,7 +128725,7 @@ var suggestPatch = createSwarmTool({
|
|
|
128076
128725
|
});
|
|
128077
128726
|
continue;
|
|
128078
128727
|
}
|
|
128079
|
-
const fullPath =
|
|
128728
|
+
const fullPath = path165.resolve(directory, change.file);
|
|
128080
128729
|
if (!fs122.existsSync(fullPath)) {
|
|
128081
128730
|
errors5.push({
|
|
128082
128731
|
success: false,
|
|
@@ -128171,7 +128820,7 @@ var suggestPatch = createSwarmTool({
|
|
|
128171
128820
|
const unifiedParts = [];
|
|
128172
128821
|
for (const [file3, entries] of fileGroups) {
|
|
128173
128822
|
entries.sort((a, b) => a.contextMatch.startLineIndex - b.contextMatch.startLineIndex);
|
|
128174
|
-
const entryFullPath =
|
|
128823
|
+
const entryFullPath = path165.resolve(directory, file3);
|
|
128175
128824
|
let entryContent;
|
|
128176
128825
|
try {
|
|
128177
128826
|
entryContent = fs122.readFileSync(entryFullPath, "utf-8");
|
|
@@ -128372,7 +129021,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
128372
129021
|
evidenceRefs: exports_external.array(exports_external.string().min(1).max(500)).max(20).optional().describe("Evidence refs such as files, commits, test outputs, or URLs")
|
|
128373
129022
|
},
|
|
128374
129023
|
execute: async (args2, directory, ctx) => {
|
|
128375
|
-
const { config: config3 } =
|
|
129024
|
+
const { config: config3 } = _internals74.loadPluginConfigWithMeta(directory);
|
|
128376
129025
|
if (config3.memory?.enabled !== true) {
|
|
128377
129026
|
return JSON.stringify({
|
|
128378
129027
|
success: false,
|
|
@@ -128388,7 +129037,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
128388
129037
|
});
|
|
128389
129038
|
}
|
|
128390
129039
|
const agent = getContextAgent2(ctx);
|
|
128391
|
-
const gateway =
|
|
129040
|
+
const gateway = _internals74.createMemoryGateway({
|
|
128392
129041
|
directory,
|
|
128393
129042
|
sessionID: ctx?.sessionID,
|
|
128394
129043
|
agentRole: agent,
|
|
@@ -128413,7 +129062,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
128413
129062
|
}
|
|
128414
129063
|
}
|
|
128415
129064
|
});
|
|
128416
|
-
var
|
|
129065
|
+
var _internals74 = {
|
|
128417
129066
|
loadPluginConfigWithMeta,
|
|
128418
129067
|
createMemoryGateway
|
|
128419
129068
|
};
|
|
@@ -128451,7 +129100,7 @@ var swarm_memory_recall = createSwarmTool({
|
|
|
128451
129100
|
maxItems: exports_external.number().int().min(1).max(20).optional().describe("Maximum memories to return")
|
|
128452
129101
|
},
|
|
128453
129102
|
execute: async (args2, directory, ctx) => {
|
|
128454
|
-
const { config: config3 } =
|
|
129103
|
+
const { config: config3 } = _internals75.loadPluginConfigWithMeta(directory);
|
|
128455
129104
|
if (config3.memory?.enabled !== true) {
|
|
128456
129105
|
return JSON.stringify({
|
|
128457
129106
|
success: false,
|
|
@@ -128467,7 +129116,7 @@ var swarm_memory_recall = createSwarmTool({
|
|
|
128467
129116
|
});
|
|
128468
129117
|
}
|
|
128469
129118
|
const agent = getContextAgent3(ctx);
|
|
128470
|
-
const gateway =
|
|
129119
|
+
const gateway = _internals75.createMemoryGateway({
|
|
128471
129120
|
directory,
|
|
128472
129121
|
sessionID: ctx?.sessionID,
|
|
128473
129122
|
agentRole: agent,
|
|
@@ -128500,7 +129149,7 @@ var RecallArgsSchema = exports_external.object({
|
|
|
128500
129149
|
kinds: exports_external.array(exports_external.enum(MEMORY_KINDS2)).optional(),
|
|
128501
129150
|
maxItems: exports_external.number().int().min(1).max(20).optional()
|
|
128502
129151
|
});
|
|
128503
|
-
var
|
|
129152
|
+
var _internals75 = {
|
|
128504
129153
|
loadPluginConfigWithMeta,
|
|
128505
129154
|
createMemoryGateway
|
|
128506
129155
|
};
|
|
@@ -128513,7 +129162,7 @@ function getContextAgent3(ctx) {
|
|
|
128513
129162
|
|
|
128514
129163
|
// src/tools/syntax-check.ts
|
|
128515
129164
|
import * as fs123 from "node:fs";
|
|
128516
|
-
import * as
|
|
129165
|
+
import * as path166 from "node:path";
|
|
128517
129166
|
init_zod();
|
|
128518
129167
|
init_manager2();
|
|
128519
129168
|
init_detector();
|
|
@@ -128585,7 +129234,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
128585
129234
|
if (languages?.length) {
|
|
128586
129235
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
128587
129236
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
128588
|
-
const ext =
|
|
129237
|
+
const ext = path166.extname(file3.path).toLowerCase();
|
|
128589
129238
|
const langDef = getLanguageForExtension(ext);
|
|
128590
129239
|
const fileProfile = getProfileForFile(file3.path);
|
|
128591
129240
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -128595,7 +129244,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
128595
129244
|
const { loadGrammar: loadGrammar2 } = await Promise.resolve().then(() => (init_runtime(), exports_runtime));
|
|
128596
129245
|
async function checkOneFile(fileInfo) {
|
|
128597
129246
|
const { path: filePath } = fileInfo;
|
|
128598
|
-
const fullPath =
|
|
129247
|
+
const fullPath = path166.isAbsolute(filePath) ? filePath : path166.join(directory, filePath);
|
|
128599
129248
|
const result = {
|
|
128600
129249
|
path: filePath,
|
|
128601
129250
|
language: "",
|
|
@@ -128642,7 +129291,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
128642
129291
|
result.skipped_reason = "binary_file";
|
|
128643
129292
|
return { result, counted: false, failed: false, skipped: true };
|
|
128644
129293
|
}
|
|
128645
|
-
const ext =
|
|
129294
|
+
const ext = path166.extname(filePath).toLowerCase();
|
|
128646
129295
|
const langDef = getLanguageForExtension(ext);
|
|
128647
129296
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
128648
129297
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -128754,7 +129403,7 @@ init_utils();
|
|
|
128754
129403
|
init_create_tool();
|
|
128755
129404
|
init_path_security();
|
|
128756
129405
|
import * as fs124 from "node:fs";
|
|
128757
|
-
import * as
|
|
129406
|
+
import * as path167 from "node:path";
|
|
128758
129407
|
var MAX_TEXT_LENGTH = 200;
|
|
128759
129408
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
128760
129409
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -128820,9 +129469,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
128820
129469
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
128821
129470
|
}
|
|
128822
129471
|
try {
|
|
128823
|
-
const resolvedPath =
|
|
128824
|
-
const normalizedCwd =
|
|
128825
|
-
const normalizedResolved =
|
|
129472
|
+
const resolvedPath = path167.resolve(paths);
|
|
129473
|
+
const normalizedCwd = path167.resolve(cwd);
|
|
129474
|
+
const normalizedResolved = path167.resolve(resolvedPath);
|
|
128826
129475
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
128827
129476
|
return {
|
|
128828
129477
|
error: "paths must be within the current working directory",
|
|
@@ -128838,7 +129487,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
128838
129487
|
}
|
|
128839
129488
|
}
|
|
128840
129489
|
function isSupportedExtension(filePath) {
|
|
128841
|
-
const ext =
|
|
129490
|
+
const ext = path167.extname(filePath).toLowerCase();
|
|
128842
129491
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
128843
129492
|
}
|
|
128844
129493
|
function findSourceFiles4(dir, files = []) {
|
|
@@ -128853,7 +129502,7 @@ function findSourceFiles4(dir, files = []) {
|
|
|
128853
129502
|
if (SKIP_DIRECTORIES6.has(entry)) {
|
|
128854
129503
|
continue;
|
|
128855
129504
|
}
|
|
128856
|
-
const fullPath =
|
|
129505
|
+
const fullPath = path167.join(dir, entry);
|
|
128857
129506
|
let stat9;
|
|
128858
129507
|
try {
|
|
128859
129508
|
stat9 = fs124.statSync(fullPath);
|
|
@@ -128965,7 +129614,7 @@ var todo_extract = createSwarmTool({
|
|
|
128965
129614
|
filesToScan.push(scanPath);
|
|
128966
129615
|
} else {
|
|
128967
129616
|
const errorResult = {
|
|
128968
|
-
error: `unsupported file extension: ${
|
|
129617
|
+
error: `unsupported file extension: ${path167.extname(scanPath)}`,
|
|
128969
129618
|
total: 0,
|
|
128970
129619
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
128971
129620
|
entries: []
|
|
@@ -129015,18 +129664,18 @@ init_schema();
|
|
|
129015
129664
|
init_qa_gate_profile();
|
|
129016
129665
|
init_gate_evidence();
|
|
129017
129666
|
import * as fs128 from "node:fs";
|
|
129018
|
-
import * as
|
|
129667
|
+
import * as path171 from "node:path";
|
|
129019
129668
|
|
|
129020
129669
|
// src/hooks/diff-scope.ts
|
|
129021
129670
|
init_bun_compat();
|
|
129022
129671
|
import * as fs126 from "node:fs";
|
|
129023
|
-
import * as
|
|
129672
|
+
import * as path169 from "node:path";
|
|
129024
129673
|
|
|
129025
129674
|
// src/utils/gitignore-warning.ts
|
|
129026
129675
|
init_bun_compat();
|
|
129027
129676
|
import * as fs125 from "node:fs";
|
|
129028
|
-
import * as
|
|
129029
|
-
var
|
|
129677
|
+
import * as path168 from "node:path";
|
|
129678
|
+
var _internals76 = { bunSpawn };
|
|
129030
129679
|
var _swarmGitExcludedChecked = false;
|
|
129031
129680
|
function fileCoversSwarm(content) {
|
|
129032
129681
|
for (const rawLine of content.split(`
|
|
@@ -129059,7 +129708,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
129059
129708
|
checkIgnoreExitCode
|
|
129060
129709
|
] = await Promise.all([
|
|
129061
129710
|
(async () => {
|
|
129062
|
-
const proc =
|
|
129711
|
+
const proc = _internals76.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
|
|
129063
129712
|
try {
|
|
129064
129713
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
129065
129714
|
} finally {
|
|
@@ -129069,7 +129718,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
129069
129718
|
}
|
|
129070
129719
|
})(),
|
|
129071
129720
|
(async () => {
|
|
129072
|
-
const proc =
|
|
129721
|
+
const proc = _internals76.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
|
|
129073
129722
|
try {
|
|
129074
129723
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
129075
129724
|
} finally {
|
|
@@ -129079,7 +129728,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
129079
129728
|
}
|
|
129080
129729
|
})(),
|
|
129081
129730
|
(async () => {
|
|
129082
|
-
const proc =
|
|
129731
|
+
const proc = _internals76.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
|
|
129083
129732
|
try {
|
|
129084
129733
|
return await proc.exited;
|
|
129085
129734
|
} finally {
|
|
@@ -129099,10 +129748,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
129099
129748
|
const excludeRelPath = excludePathRaw.trim();
|
|
129100
129749
|
if (!excludeRelPath)
|
|
129101
129750
|
return;
|
|
129102
|
-
const excludePath =
|
|
129751
|
+
const excludePath = path168.isAbsolute(excludeRelPath) ? excludeRelPath : path168.join(directory, excludeRelPath);
|
|
129103
129752
|
if (checkIgnoreExitCode !== 0) {
|
|
129104
129753
|
try {
|
|
129105
|
-
fs125.mkdirSync(
|
|
129754
|
+
fs125.mkdirSync(path168.dirname(excludePath), { recursive: true });
|
|
129106
129755
|
let existing = "";
|
|
129107
129756
|
try {
|
|
129108
129757
|
existing = fs125.readFileSync(excludePath, "utf8");
|
|
@@ -129118,7 +129767,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
129118
129767
|
}
|
|
129119
129768
|
} catch {}
|
|
129120
129769
|
}
|
|
129121
|
-
const trackedProc =
|
|
129770
|
+
const trackedProc = _internals76.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
|
|
129122
129771
|
let trackedExitCode;
|
|
129123
129772
|
let trackedOutput;
|
|
129124
129773
|
try {
|
|
@@ -129143,10 +129792,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
129143
129792
|
}
|
|
129144
129793
|
|
|
129145
129794
|
// src/hooks/diff-scope.ts
|
|
129146
|
-
var
|
|
129795
|
+
var _internals77 = { bunSpawn };
|
|
129147
129796
|
function getDeclaredScope(taskId, directory) {
|
|
129148
129797
|
try {
|
|
129149
|
-
const planPath =
|
|
129798
|
+
const planPath = path169.join(directory, ".swarm", "plan.json");
|
|
129150
129799
|
if (!fs126.existsSync(planPath))
|
|
129151
129800
|
return null;
|
|
129152
129801
|
const raw = fs126.readFileSync(planPath, "utf-8");
|
|
@@ -129178,7 +129827,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
|
|
|
129178
129827
|
};
|
|
129179
129828
|
async function getChangedFiles(directory) {
|
|
129180
129829
|
try {
|
|
129181
|
-
const proc =
|
|
129830
|
+
const proc = _internals77.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
|
|
129182
129831
|
cwd: directory,
|
|
129183
129832
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
129184
129833
|
});
|
|
@@ -129195,7 +129844,7 @@ async function getChangedFiles(directory) {
|
|
|
129195
129844
|
return stdout.trim().split(`
|
|
129196
129845
|
`).map((f) => f.trim()).filter((f) => f.length > 0);
|
|
129197
129846
|
}
|
|
129198
|
-
const proc2 =
|
|
129847
|
+
const proc2 = _internals77.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
|
|
129199
129848
|
cwd: directory,
|
|
129200
129849
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
129201
129850
|
});
|
|
@@ -129252,8 +129901,8 @@ init_telemetry();
|
|
|
129252
129901
|
// src/turbo/lean/task-completion.ts
|
|
129253
129902
|
init_file_locks();
|
|
129254
129903
|
import * as fs127 from "node:fs";
|
|
129255
|
-
import * as
|
|
129256
|
-
var
|
|
129904
|
+
import * as path170 from "node:path";
|
|
129905
|
+
var _internals78 = {
|
|
129257
129906
|
listActiveLocks,
|
|
129258
129907
|
verifyLeanTurboTaskCompletion
|
|
129259
129908
|
};
|
|
@@ -129271,7 +129920,7 @@ var TIER_3_PATTERNS = [
|
|
|
129271
129920
|
];
|
|
129272
129921
|
function matchesTier3Pattern(files) {
|
|
129273
129922
|
for (const file3 of files) {
|
|
129274
|
-
const fileName =
|
|
129923
|
+
const fileName = path170.basename(file3);
|
|
129275
129924
|
for (const pattern of TIER_3_PATTERNS) {
|
|
129276
129925
|
if (pattern.test(fileName)) {
|
|
129277
129926
|
return true;
|
|
@@ -129283,7 +129932,7 @@ function matchesTier3Pattern(files) {
|
|
|
129283
129932
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
129284
129933
|
let persisted = null;
|
|
129285
129934
|
try {
|
|
129286
|
-
const statePath =
|
|
129935
|
+
const statePath = path170.join(directory, ".swarm", "turbo-state.json");
|
|
129287
129936
|
if (!fs127.existsSync(statePath)) {
|
|
129288
129937
|
return {
|
|
129289
129938
|
ok: false,
|
|
@@ -129367,11 +130016,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
129367
130016
|
};
|
|
129368
130017
|
}
|
|
129369
130018
|
const phase = runState.phase ?? 0;
|
|
129370
|
-
const evidencePath =
|
|
129371
|
-
const expectedDir =
|
|
129372
|
-
const resolvedPath =
|
|
129373
|
-
const resolvedDir =
|
|
129374
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
130019
|
+
const evidencePath = path170.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
130020
|
+
const expectedDir = path170.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
130021
|
+
const resolvedPath = path170.resolve(evidencePath);
|
|
130022
|
+
const resolvedDir = path170.resolve(expectedDir);
|
|
130023
|
+
if (!resolvedPath.startsWith(resolvedDir + path170.sep) && resolvedPath !== resolvedDir) {
|
|
129375
130024
|
return {
|
|
129376
130025
|
ok: false,
|
|
129377
130026
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -129395,7 +130044,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
129395
130044
|
}
|
|
129396
130045
|
};
|
|
129397
130046
|
}
|
|
129398
|
-
const activeLocks =
|
|
130047
|
+
const activeLocks = _internals78.listActiveLocks(directory);
|
|
129399
130048
|
const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
|
|
129400
130049
|
if (laneLocks.length > 0) {
|
|
129401
130050
|
return {
|
|
@@ -129411,7 +130060,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
129411
130060
|
}
|
|
129412
130061
|
let filesTouched = [];
|
|
129413
130062
|
try {
|
|
129414
|
-
const planPath =
|
|
130063
|
+
const planPath = path170.join(directory, ".swarm", "plan.json");
|
|
129415
130064
|
const planRaw = fs127.readFileSync(planPath, "utf-8");
|
|
129416
130065
|
const plan = JSON.parse(planRaw);
|
|
129417
130066
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -129495,7 +130144,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
129495
130144
|
];
|
|
129496
130145
|
function matchesTier3Pattern2(files) {
|
|
129497
130146
|
for (const file3 of files) {
|
|
129498
|
-
const fileName =
|
|
130147
|
+
const fileName = path171.basename(file3);
|
|
129499
130148
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
129500
130149
|
if (pattern.test(fileName)) {
|
|
129501
130150
|
return true;
|
|
@@ -129534,7 +130183,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
129534
130183
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
129535
130184
|
const resolvedDir2 = workingDirectory;
|
|
129536
130185
|
try {
|
|
129537
|
-
const planPath =
|
|
130186
|
+
const planPath = path171.join(resolvedDir2, ".swarm", "plan.json");
|
|
129538
130187
|
const planRaw = fs128.readFileSync(planPath, "utf-8");
|
|
129539
130188
|
const plan = JSON.parse(planRaw);
|
|
129540
130189
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -129612,7 +130261,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
129612
130261
|
}
|
|
129613
130262
|
if (resolvedDir) {
|
|
129614
130263
|
try {
|
|
129615
|
-
const planPath =
|
|
130264
|
+
const planPath = path171.join(resolvedDir, ".swarm", "plan.json");
|
|
129616
130265
|
const planRaw = fs128.readFileSync(planPath, "utf-8");
|
|
129617
130266
|
const plan = JSON.parse(planRaw);
|
|
129618
130267
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -129854,7 +130503,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
129854
130503
|
};
|
|
129855
130504
|
}
|
|
129856
130505
|
directory = resolveResult.directory;
|
|
129857
|
-
const planPath =
|
|
130506
|
+
const planPath = path171.join(directory, ".swarm", "plan.json");
|
|
129858
130507
|
if (!fs128.existsSync(planPath)) {
|
|
129859
130508
|
return {
|
|
129860
130509
|
success: false,
|
|
@@ -129863,9 +130512,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
129863
130512
|
};
|
|
129864
130513
|
}
|
|
129865
130514
|
if (fallbackDir && directory !== fallbackDir) {
|
|
129866
|
-
const canonicalDir = fs128.realpathSync(
|
|
129867
|
-
const canonicalRoot = fs128.realpathSync(
|
|
129868
|
-
if (canonicalDir.startsWith(canonicalRoot +
|
|
130515
|
+
const canonicalDir = fs128.realpathSync(path171.resolve(directory));
|
|
130516
|
+
const canonicalRoot = fs128.realpathSync(path171.resolve(fallbackDir));
|
|
130517
|
+
if (canonicalDir.startsWith(canonicalRoot + path171.sep)) {
|
|
129869
130518
|
return {
|
|
129870
130519
|
success: false,
|
|
129871
130520
|
message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
|
|
@@ -129877,8 +130526,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
129877
130526
|
}
|
|
129878
130527
|
if (args2.status === "in_progress") {
|
|
129879
130528
|
try {
|
|
129880
|
-
const evidencePath =
|
|
129881
|
-
fs128.mkdirSync(
|
|
130529
|
+
const evidencePath = path171.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
130530
|
+
fs128.mkdirSync(path171.dirname(evidencePath), { recursive: true });
|
|
129882
130531
|
const fd = fs128.openSync(evidencePath, "wx");
|
|
129883
130532
|
let writeOk = false;
|
|
129884
130533
|
try {
|
|
@@ -129902,7 +130551,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
129902
130551
|
recoverTaskStateFromDelegations(args2.task_id, directory);
|
|
129903
130552
|
let phaseRequiresReviewer = true;
|
|
129904
130553
|
try {
|
|
129905
|
-
const planPath2 =
|
|
130554
|
+
const planPath2 = path171.join(directory, ".swarm", "plan.json");
|
|
129906
130555
|
const planRaw = fs128.readFileSync(planPath2, "utf-8");
|
|
129907
130556
|
const plan = JSON.parse(planRaw);
|
|
129908
130557
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
@@ -130199,7 +130848,7 @@ init_utils2();
|
|
|
130199
130848
|
init_redaction();
|
|
130200
130849
|
import { createHash as createHash13 } from "node:crypto";
|
|
130201
130850
|
import { appendFile as appendFile14, mkdir as mkdir24 } from "node:fs/promises";
|
|
130202
|
-
import * as
|
|
130851
|
+
import * as path172 from "node:path";
|
|
130203
130852
|
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
130204
130853
|
var MAX_EVIDENCE_TEXT_LENGTH = 4000;
|
|
130205
130854
|
async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
@@ -130207,7 +130856,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
|
130207
130856
|
const capturedAt = now().toISOString();
|
|
130208
130857
|
const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
|
|
130209
130858
|
if (records.length > 0) {
|
|
130210
|
-
await mkdir24(
|
|
130859
|
+
await mkdir24(path172.dirname(filePath), { recursive: true });
|
|
130211
130860
|
await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
|
|
130212
130861
|
`)}
|
|
130213
130862
|
`, "utf-8");
|
|
@@ -130373,7 +131022,7 @@ var web_search = createSwarmTool({
|
|
|
130373
131022
|
});
|
|
130374
131023
|
async function captureSearchEvidence(directory, query, results) {
|
|
130375
131024
|
try {
|
|
130376
|
-
const written = await
|
|
131025
|
+
const written = await _internals79.writeEvidenceDocuments(directory, results.map((result) => ({
|
|
130377
131026
|
sourceType: "web_search",
|
|
130378
131027
|
query,
|
|
130379
131028
|
title: result.title,
|
|
@@ -130401,7 +131050,7 @@ async function captureSearchEvidence(directory, query, results) {
|
|
|
130401
131050
|
};
|
|
130402
131051
|
}
|
|
130403
131052
|
}
|
|
130404
|
-
var
|
|
131053
|
+
var _internals79 = {
|
|
130405
131054
|
writeEvidenceDocuments
|
|
130406
131055
|
};
|
|
130407
131056
|
|
|
@@ -130415,7 +131064,7 @@ init_schema3();
|
|
|
130415
131064
|
init_store();
|
|
130416
131065
|
init_create_tool();
|
|
130417
131066
|
init_resolve_working_directory();
|
|
130418
|
-
import * as
|
|
131067
|
+
import * as path173 from "node:path";
|
|
130419
131068
|
var FindingSchema2 = exports_external.object({
|
|
130420
131069
|
severity: exports_external.enum(["low", "medium", "high", "critical"]),
|
|
130421
131070
|
category: exports_external.string().min(1),
|
|
@@ -130479,7 +131128,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
130479
131128
|
if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
|
|
130480
131129
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
130481
131130
|
const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
|
|
130482
|
-
const result = await curateAndStoreSwarm(lessons,
|
|
131131
|
+
const result = await curateAndStoreSwarm(lessons, path173.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
|
|
130483
131132
|
knowledgeProposed = result.stored;
|
|
130484
131133
|
}
|
|
130485
131134
|
} catch {}
|
|
@@ -130515,7 +131164,7 @@ init_ledger();
|
|
|
130515
131164
|
init_manager();
|
|
130516
131165
|
init_create_tool();
|
|
130517
131166
|
import fs129 from "node:fs";
|
|
130518
|
-
import
|
|
131167
|
+
import path174 from "node:path";
|
|
130519
131168
|
function normalizeVerdict(verdict) {
|
|
130520
131169
|
switch (verdict) {
|
|
130521
131170
|
case "APPROVED":
|
|
@@ -130563,7 +131212,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
130563
131212
|
entries: [evidenceEntry]
|
|
130564
131213
|
};
|
|
130565
131214
|
const filename = "drift-verifier.json";
|
|
130566
|
-
const relativePath =
|
|
131215
|
+
const relativePath = path174.join("evidence", String(phase), filename);
|
|
130567
131216
|
let validatedPath;
|
|
130568
131217
|
try {
|
|
130569
131218
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -130574,10 +131223,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
130574
131223
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
130575
131224
|
}, null, 2);
|
|
130576
131225
|
}
|
|
130577
|
-
const evidenceDir =
|
|
131226
|
+
const evidenceDir = path174.dirname(validatedPath);
|
|
130578
131227
|
try {
|
|
130579
131228
|
await fs129.promises.mkdir(evidenceDir, { recursive: true });
|
|
130580
|
-
const tempPath =
|
|
131229
|
+
const tempPath = path174.join(evidenceDir, `.${filename}.tmp`);
|
|
130581
131230
|
await fs129.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
130582
131231
|
await fs129.promises.rename(tempPath, validatedPath);
|
|
130583
131232
|
let snapshotInfo;
|
|
@@ -130674,7 +131323,7 @@ var write_drift_evidence = createSwarmTool({
|
|
|
130674
131323
|
init_zod();
|
|
130675
131324
|
init_loader();
|
|
130676
131325
|
import fs130 from "node:fs";
|
|
130677
|
-
import
|
|
131326
|
+
import path175 from "node:path";
|
|
130678
131327
|
init_utils2();
|
|
130679
131328
|
init_manager();
|
|
130680
131329
|
init_create_tool();
|
|
@@ -130768,7 +131417,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
130768
131417
|
timestamp: synthesis.timestamp
|
|
130769
131418
|
};
|
|
130770
131419
|
const filename = "final-council.json";
|
|
130771
|
-
const relativePath =
|
|
131420
|
+
const relativePath = path175.join("evidence", filename);
|
|
130772
131421
|
let validatedPath;
|
|
130773
131422
|
try {
|
|
130774
131423
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -130782,10 +131431,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
130782
131431
|
const evidenceContent = {
|
|
130783
131432
|
entries: [evidenceEntry]
|
|
130784
131433
|
};
|
|
130785
|
-
const evidenceDir =
|
|
131434
|
+
const evidenceDir = path175.dirname(validatedPath);
|
|
130786
131435
|
try {
|
|
130787
131436
|
await fs130.promises.mkdir(evidenceDir, { recursive: true });
|
|
130788
|
-
const tempPath =
|
|
131437
|
+
const tempPath = path175.join(evidenceDir, `.${filename}.tmp`);
|
|
130789
131438
|
await fs130.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
130790
131439
|
await fs130.promises.rename(tempPath, validatedPath);
|
|
130791
131440
|
return JSON.stringify({
|
|
@@ -130845,7 +131494,7 @@ init_zod();
|
|
|
130845
131494
|
init_utils2();
|
|
130846
131495
|
init_create_tool();
|
|
130847
131496
|
import fs131 from "node:fs";
|
|
130848
|
-
import
|
|
131497
|
+
import path176 from "node:path";
|
|
130849
131498
|
function normalizeVerdict2(verdict) {
|
|
130850
131499
|
switch (verdict) {
|
|
130851
131500
|
case "APPROVED":
|
|
@@ -130893,7 +131542,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
130893
131542
|
entries: [evidenceEntry]
|
|
130894
131543
|
};
|
|
130895
131544
|
const filename = "hallucination-guard.json";
|
|
130896
|
-
const relativePath =
|
|
131545
|
+
const relativePath = path176.join("evidence", String(phase), filename);
|
|
130897
131546
|
let validatedPath;
|
|
130898
131547
|
try {
|
|
130899
131548
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -130904,10 +131553,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
130904
131553
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
130905
131554
|
}, null, 2);
|
|
130906
131555
|
}
|
|
130907
|
-
const evidenceDir =
|
|
131556
|
+
const evidenceDir = path176.dirname(validatedPath);
|
|
130908
131557
|
try {
|
|
130909
131558
|
await fs131.promises.mkdir(evidenceDir, { recursive: true });
|
|
130910
|
-
const tempPath =
|
|
131559
|
+
const tempPath = path176.join(evidenceDir, `.${filename}.tmp`);
|
|
130911
131560
|
await fs131.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
130912
131561
|
await fs131.promises.rename(tempPath, validatedPath);
|
|
130913
131562
|
return JSON.stringify({
|
|
@@ -130957,7 +131606,7 @@ init_zod();
|
|
|
130957
131606
|
init_utils2();
|
|
130958
131607
|
init_create_tool();
|
|
130959
131608
|
import fs132 from "node:fs";
|
|
130960
|
-
import
|
|
131609
|
+
import path177 from "node:path";
|
|
130961
131610
|
function normalizeVerdict3(verdict) {
|
|
130962
131611
|
switch (verdict) {
|
|
130963
131612
|
case "PASS":
|
|
@@ -131031,7 +131680,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
131031
131680
|
entries: [evidenceEntry]
|
|
131032
131681
|
};
|
|
131033
131682
|
const filename = "mutation-gate.json";
|
|
131034
|
-
const relativePath =
|
|
131683
|
+
const relativePath = path177.join("evidence", String(phase), filename);
|
|
131035
131684
|
let validatedPath;
|
|
131036
131685
|
try {
|
|
131037
131686
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -131042,10 +131691,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
131042
131691
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
131043
131692
|
}, null, 2);
|
|
131044
131693
|
}
|
|
131045
|
-
const evidenceDir =
|
|
131694
|
+
const evidenceDir = path177.dirname(validatedPath);
|
|
131046
131695
|
try {
|
|
131047
131696
|
await fs132.promises.mkdir(evidenceDir, { recursive: true });
|
|
131048
|
-
const tempPath =
|
|
131697
|
+
const tempPath = path177.join(evidenceDir, `.${filename}.tmp`);
|
|
131049
131698
|
await fs132.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
131050
131699
|
await fs132.promises.rename(tempPath, validatedPath);
|
|
131051
131700
|
return JSON.stringify({
|
|
@@ -131233,7 +131882,7 @@ ${footerLines.join(`
|
|
|
131233
131882
|
init_warning_buffer();
|
|
131234
131883
|
var _heartbeatTimers = new Map;
|
|
131235
131884
|
var SWARM_COMMAND_SYSTEM_RULE_TAG = "[opencode-swarm:swarm-command-rule]";
|
|
131236
|
-
var PACKAGE_ROOT2 =
|
|
131885
|
+
var PACKAGE_ROOT2 = path179.resolve(path179.dirname(fileURLToPath5(import.meta.url)), "..");
|
|
131237
131886
|
function createSwarmCommandSystemRuleHook(agentDefinitions, registeredAgents) {
|
|
131238
131887
|
return async (input, output) => {
|
|
131239
131888
|
const { sessionID } = input;
|
|
@@ -131503,7 +132152,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
131503
132152
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
131504
132153
|
preflightTriggerManager = new PTM(automationConfig);
|
|
131505
132154
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
131506
|
-
const swarmDir =
|
|
132155
|
+
const swarmDir = path179.resolve(ctx.directory, ".swarm");
|
|
131507
132156
|
statusArtifact = new ASA(swarmDir);
|
|
131508
132157
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
131509
132158
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -132034,7 +132683,7 @@ ${promptRaw}`;
|
|
|
132034
132683
|
const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
|
|
132035
132684
|
let desc = meta3.description || "";
|
|
132036
132685
|
if (!desc || desc === "No description provided") {
|
|
132037
|
-
desc =
|
|
132686
|
+
desc = path179.basename(path179.dirname(s.skillPath));
|
|
132038
132687
|
}
|
|
132039
132688
|
desc = desc.replace(/,/g, ";");
|
|
132040
132689
|
return `file:${s.skillPath} (-- ${desc})`;
|
|
@@ -132044,7 +132693,7 @@ ${promptRaw}`;
|
|
|
132044
132693
|
|
|
132045
132694
|
${promptRaw}`;
|
|
132046
132695
|
argsRecord.prompt = newPrompt;
|
|
132047
|
-
const skillNames = topSkills.map((s) => `${
|
|
132696
|
+
const skillNames = topSkills.map((s) => `${path179.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
132048
132697
|
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
132049
132698
|
for (const skill of topSkills) {
|
|
132050
132699
|
try {
|