opencode-swarm 6.23.0 → 6.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +33 -0
- package/dist/config/schema.d.ts +2 -2
- package/dist/gate-evidence.d.ts +56 -0
- package/dist/gate-evidence.test.d.ts +1 -0
- package/dist/hooks/delegation-gate.evidence.test.d.ts +4 -0
- package/dist/index.js +419 -163
- package/dist/tools/update-task-status.d.ts +11 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15749,6 +15749,39 @@ async function savePlan(directory, plan) {
|
|
|
15749
15749
|
throw new Error(`Invalid directory: directory must be a non-empty string`);
|
|
15750
15750
|
}
|
|
15751
15751
|
const validated = PlanSchema.parse(plan);
|
|
15752
|
+
try {
|
|
15753
|
+
const currentPlan = await loadPlanJsonOnly(directory);
|
|
15754
|
+
if (currentPlan) {
|
|
15755
|
+
const completedTaskIds = new Set;
|
|
15756
|
+
for (const phase of currentPlan.phases) {
|
|
15757
|
+
for (const task of phase.tasks) {
|
|
15758
|
+
if (task.status === "completed")
|
|
15759
|
+
completedTaskIds.add(task.id);
|
|
15760
|
+
}
|
|
15761
|
+
}
|
|
15762
|
+
if (completedTaskIds.size > 0) {
|
|
15763
|
+
for (const phase of validated.phases) {
|
|
15764
|
+
for (const task of phase.tasks) {
|
|
15765
|
+
if (completedTaskIds.has(task.id) && task.status !== "completed") {
|
|
15766
|
+
task.status = "completed";
|
|
15767
|
+
}
|
|
15768
|
+
}
|
|
15769
|
+
}
|
|
15770
|
+
}
|
|
15771
|
+
}
|
|
15772
|
+
} catch {}
|
|
15773
|
+
for (const phase of validated.phases) {
|
|
15774
|
+
const tasks = phase.tasks;
|
|
15775
|
+
if (tasks.length > 0 && tasks.every((t) => t.status === "completed")) {
|
|
15776
|
+
phase.status = "complete";
|
|
15777
|
+
} else if (tasks.some((t) => t.status === "in_progress")) {
|
|
15778
|
+
phase.status = "in_progress";
|
|
15779
|
+
} else if (tasks.some((t) => t.status === "blocked")) {
|
|
15780
|
+
phase.status = "blocked";
|
|
15781
|
+
} else {
|
|
15782
|
+
phase.status = "pending";
|
|
15783
|
+
}
|
|
15784
|
+
}
|
|
15752
15785
|
const swarmDir = path4.resolve(directory, ".swarm");
|
|
15753
15786
|
const planPath = path4.join(swarmDir, "plan.json");
|
|
15754
15787
|
const tempPath = path4.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
@@ -35824,6 +35857,133 @@ var init_preflight_service = __esm(() => {
|
|
|
35824
35857
|
};
|
|
35825
35858
|
});
|
|
35826
35859
|
|
|
35860
|
+
// src/gate-evidence.ts
|
|
35861
|
+
var exports_gate_evidence = {};
|
|
35862
|
+
__export(exports_gate_evidence, {
|
|
35863
|
+
recordGateEvidence: () => recordGateEvidence,
|
|
35864
|
+
recordAgentDispatch: () => recordAgentDispatch,
|
|
35865
|
+
readTaskEvidence: () => readTaskEvidence,
|
|
35866
|
+
hasPassedAllGates: () => hasPassedAllGates,
|
|
35867
|
+
expandRequiredGates: () => expandRequiredGates,
|
|
35868
|
+
deriveRequiredGates: () => deriveRequiredGates,
|
|
35869
|
+
DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
|
|
35870
|
+
});
|
|
35871
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "fs";
|
|
35872
|
+
import * as path27 from "path";
|
|
35873
|
+
function assertValidTaskId(taskId) {
|
|
35874
|
+
if (!taskId || taskId.includes("..") || taskId.includes("/") || taskId.includes("\\") || taskId.includes("\x00") || !TASK_ID_PATTERN.test(taskId)) {
|
|
35875
|
+
throw new Error(`Invalid taskId: "${taskId}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3").`);
|
|
35876
|
+
}
|
|
35877
|
+
}
|
|
35878
|
+
function deriveRequiredGates(agentType) {
|
|
35879
|
+
switch (agentType) {
|
|
35880
|
+
case "coder":
|
|
35881
|
+
return ["reviewer", "test_engineer"];
|
|
35882
|
+
case "docs":
|
|
35883
|
+
return ["docs"];
|
|
35884
|
+
case "designer":
|
|
35885
|
+
return ["designer", "reviewer", "test_engineer"];
|
|
35886
|
+
case "explorer":
|
|
35887
|
+
return ["explorer"];
|
|
35888
|
+
case "sme":
|
|
35889
|
+
return ["sme"];
|
|
35890
|
+
case "reviewer":
|
|
35891
|
+
return ["reviewer"];
|
|
35892
|
+
case "test_engineer":
|
|
35893
|
+
return ["test_engineer"];
|
|
35894
|
+
case "critic":
|
|
35895
|
+
return ["critic"];
|
|
35896
|
+
default:
|
|
35897
|
+
return ["reviewer", "test_engineer"];
|
|
35898
|
+
}
|
|
35899
|
+
}
|
|
35900
|
+
function expandRequiredGates(existingGates, newAgentType) {
|
|
35901
|
+
const newGates = deriveRequiredGates(newAgentType);
|
|
35902
|
+
const combined = [...new Set([...existingGates, ...newGates])];
|
|
35903
|
+
return combined.sort();
|
|
35904
|
+
}
|
|
35905
|
+
function getEvidenceDir(directory) {
|
|
35906
|
+
return path27.join(directory, ".swarm", "evidence");
|
|
35907
|
+
}
|
|
35908
|
+
function getEvidencePath(directory, taskId) {
|
|
35909
|
+
return path27.join(getEvidenceDir(directory), `${taskId}.json`);
|
|
35910
|
+
}
|
|
35911
|
+
function readExisting(evidencePath) {
|
|
35912
|
+
try {
|
|
35913
|
+
const raw = readFileSync13(evidencePath, "utf-8");
|
|
35914
|
+
return JSON.parse(raw);
|
|
35915
|
+
} catch {
|
|
35916
|
+
return null;
|
|
35917
|
+
}
|
|
35918
|
+
}
|
|
35919
|
+
async function atomicWrite(targetPath, content) {
|
|
35920
|
+
const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
35921
|
+
try {
|
|
35922
|
+
await Bun.write(tempPath, content);
|
|
35923
|
+
renameSync7(tempPath, targetPath);
|
|
35924
|
+
} finally {
|
|
35925
|
+
try {
|
|
35926
|
+
unlinkSync4(tempPath);
|
|
35927
|
+
} catch {}
|
|
35928
|
+
}
|
|
35929
|
+
}
|
|
35930
|
+
async function recordGateEvidence(directory, taskId, gate, sessionId) {
|
|
35931
|
+
assertValidTaskId(taskId);
|
|
35932
|
+
const evidenceDir = getEvidenceDir(directory);
|
|
35933
|
+
const evidencePath = getEvidencePath(directory, taskId);
|
|
35934
|
+
mkdirSync8(evidenceDir, { recursive: true });
|
|
35935
|
+
const existing = readExisting(evidencePath);
|
|
35936
|
+
const requiredGates = existing ? expandRequiredGates(existing.required_gates, gate) : deriveRequiredGates(gate);
|
|
35937
|
+
const updated = {
|
|
35938
|
+
taskId,
|
|
35939
|
+
required_gates: requiredGates,
|
|
35940
|
+
gates: {
|
|
35941
|
+
...existing?.gates ?? {},
|
|
35942
|
+
[gate]: {
|
|
35943
|
+
sessionId,
|
|
35944
|
+
timestamp: new Date().toISOString(),
|
|
35945
|
+
agent: gate
|
|
35946
|
+
}
|
|
35947
|
+
}
|
|
35948
|
+
};
|
|
35949
|
+
await atomicWrite(evidencePath, JSON.stringify(updated, null, 2));
|
|
35950
|
+
}
|
|
35951
|
+
async function recordAgentDispatch(directory, taskId, agentType) {
|
|
35952
|
+
assertValidTaskId(taskId);
|
|
35953
|
+
const evidenceDir = getEvidenceDir(directory);
|
|
35954
|
+
const evidencePath = getEvidencePath(directory, taskId);
|
|
35955
|
+
mkdirSync8(evidenceDir, { recursive: true });
|
|
35956
|
+
const existing = readExisting(evidencePath);
|
|
35957
|
+
const requiredGates = existing ? expandRequiredGates(existing.required_gates, agentType) : deriveRequiredGates(agentType);
|
|
35958
|
+
const updated = {
|
|
35959
|
+
taskId,
|
|
35960
|
+
required_gates: requiredGates,
|
|
35961
|
+
gates: existing?.gates ?? {}
|
|
35962
|
+
};
|
|
35963
|
+
await atomicWrite(evidencePath, JSON.stringify(updated, null, 2));
|
|
35964
|
+
}
|
|
35965
|
+
async function readTaskEvidence(directory, taskId) {
|
|
35966
|
+
try {
|
|
35967
|
+
assertValidTaskId(taskId);
|
|
35968
|
+
return readExisting(getEvidencePath(directory, taskId));
|
|
35969
|
+
} catch {
|
|
35970
|
+
return null;
|
|
35971
|
+
}
|
|
35972
|
+
}
|
|
35973
|
+
async function hasPassedAllGates(directory, taskId) {
|
|
35974
|
+
const evidence = await readTaskEvidence(directory, taskId);
|
|
35975
|
+
if (!evidence)
|
|
35976
|
+
return false;
|
|
35977
|
+
if (!Array.isArray(evidence.required_gates) || evidence.required_gates.length === 0)
|
|
35978
|
+
return false;
|
|
35979
|
+
return evidence.required_gates.every((gate) => evidence.gates[gate] != null);
|
|
35980
|
+
}
|
|
35981
|
+
var DEFAULT_REQUIRED_GATES, TASK_ID_PATTERN;
|
|
35982
|
+
var init_gate_evidence = __esm(() => {
|
|
35983
|
+
DEFAULT_REQUIRED_GATES = ["reviewer", "test_engineer"];
|
|
35984
|
+
TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
|
|
35985
|
+
});
|
|
35986
|
+
|
|
35827
35987
|
// src/services/preflight-integration.ts
|
|
35828
35988
|
var exports_preflight_integration = {};
|
|
35829
35989
|
__export(exports_preflight_integration, {
|
|
@@ -37353,11 +37513,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37353
37513
|
throw toThrow;
|
|
37354
37514
|
}, "quit_");
|
|
37355
37515
|
var scriptDirectory = "";
|
|
37356
|
-
function locateFile(
|
|
37516
|
+
function locateFile(path40) {
|
|
37357
37517
|
if (Module["locateFile"]) {
|
|
37358
|
-
return Module["locateFile"](
|
|
37518
|
+
return Module["locateFile"](path40, scriptDirectory);
|
|
37359
37519
|
}
|
|
37360
|
-
return scriptDirectory +
|
|
37520
|
+
return scriptDirectory + path40;
|
|
37361
37521
|
}
|
|
37362
37522
|
__name(locateFile, "locateFile");
|
|
37363
37523
|
var readAsync, readBinary;
|
|
@@ -39105,7 +39265,7 @@ var init_runtime = __esm(() => {
|
|
|
39105
39265
|
});
|
|
39106
39266
|
|
|
39107
39267
|
// src/index.ts
|
|
39108
|
-
import * as
|
|
39268
|
+
import * as path49 from "path";
|
|
39109
39269
|
|
|
39110
39270
|
// src/agents/index.ts
|
|
39111
39271
|
init_config();
|
|
@@ -48774,6 +48934,28 @@ function createDelegationGateHook(config3) {
|
|
|
48774
48934
|
}
|
|
48775
48935
|
}
|
|
48776
48936
|
}
|
|
48937
|
+
if (typeof subagentType === "string") {
|
|
48938
|
+
const evidenceTaskId = session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
48939
|
+
if (evidenceTaskId) {
|
|
48940
|
+
try {
|
|
48941
|
+
const gateAgents = [
|
|
48942
|
+
"reviewer",
|
|
48943
|
+
"test_engineer",
|
|
48944
|
+
"docs",
|
|
48945
|
+
"designer",
|
|
48946
|
+
"critic"
|
|
48947
|
+
];
|
|
48948
|
+
const targetAgentForEvidence = stripKnownSwarmPrefix(subagentType);
|
|
48949
|
+
if (gateAgents.includes(targetAgentForEvidence)) {
|
|
48950
|
+
const { recordGateEvidence: recordGateEvidence2 } = await Promise.resolve().then(() => (init_gate_evidence(), exports_gate_evidence));
|
|
48951
|
+
await recordGateEvidence2(process.cwd(), evidenceTaskId, targetAgentForEvidence, input.sessionID);
|
|
48952
|
+
} else {
|
|
48953
|
+
const { recordAgentDispatch: recordAgentDispatch2 } = await Promise.resolve().then(() => (init_gate_evidence(), exports_gate_evidence));
|
|
48954
|
+
await recordAgentDispatch2(process.cwd(), evidenceTaskId, targetAgentForEvidence);
|
|
48955
|
+
}
|
|
48956
|
+
} catch {}
|
|
48957
|
+
}
|
|
48958
|
+
}
|
|
48777
48959
|
if (storedArgs !== undefined) {
|
|
48778
48960
|
deleteStoredInputArgs(input.callID);
|
|
48779
48961
|
}
|
|
@@ -48788,10 +48970,8 @@ function createDelegationGateHook(config3) {
|
|
|
48788
48970
|
break;
|
|
48789
48971
|
}
|
|
48790
48972
|
}
|
|
48791
|
-
|
|
48792
|
-
|
|
48793
|
-
}
|
|
48794
|
-
const afterCoder = delegationChain.slice(lastCoderIndex);
|
|
48973
|
+
const searchStart = lastCoderIndex === -1 ? 0 : lastCoderIndex;
|
|
48974
|
+
const afterCoder = delegationChain.slice(searchStart);
|
|
48795
48975
|
for (const delegation of afterCoder) {
|
|
48796
48976
|
const target = stripKnownSwarmPrefix(delegation.to);
|
|
48797
48977
|
if (target === "reviewer")
|
|
@@ -48799,7 +48979,7 @@ function createDelegationGateHook(config3) {
|
|
|
48799
48979
|
if (target === "test_engineer")
|
|
48800
48980
|
hasTestEngineer = true;
|
|
48801
48981
|
}
|
|
48802
|
-
if (hasReviewer && hasTestEngineer) {
|
|
48982
|
+
if (lastCoderIndex !== -1 && hasReviewer && hasTestEngineer) {
|
|
48803
48983
|
session.qaSkipCount = 0;
|
|
48804
48984
|
session.qaSkipTaskIds = [];
|
|
48805
48985
|
}
|
|
@@ -48868,6 +49048,21 @@ function createDelegationGateHook(config3) {
|
|
|
48868
49048
|
}
|
|
48869
49049
|
}
|
|
48870
49050
|
}
|
|
49051
|
+
{
|
|
49052
|
+
const evidenceTaskId = session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
49053
|
+
if (evidenceTaskId) {
|
|
49054
|
+
try {
|
|
49055
|
+
if (hasReviewer) {
|
|
49056
|
+
const { recordGateEvidence: recordGateEvidence2 } = await Promise.resolve().then(() => (init_gate_evidence(), exports_gate_evidence));
|
|
49057
|
+
await recordGateEvidence2(process.cwd(), evidenceTaskId, "reviewer", input.sessionID);
|
|
49058
|
+
}
|
|
49059
|
+
if (hasTestEngineer) {
|
|
49060
|
+
const { recordGateEvidence: recordGateEvidence2 } = await Promise.resolve().then(() => (init_gate_evidence(), exports_gate_evidence));
|
|
49061
|
+
await recordGateEvidence2(process.cwd(), evidenceTaskId, "test_engineer", input.sessionID);
|
|
49062
|
+
}
|
|
49063
|
+
} catch {}
|
|
49064
|
+
}
|
|
49065
|
+
}
|
|
48871
49066
|
}
|
|
48872
49067
|
}
|
|
48873
49068
|
};
|
|
@@ -49059,11 +49254,11 @@ ${trimComment}${after}`;
|
|
|
49059
49254
|
if (!hasReviewer || !hasTestEngineer || priorTaskStuckAtCoder) {
|
|
49060
49255
|
if (session.qaSkipCount >= 1) {
|
|
49061
49256
|
const skippedTasks = session.qaSkipTaskIds.join(", ");
|
|
49062
|
-
throw new Error(`\uD83D\uDED1 QA GATE ENFORCEMENT: ${session.qaSkipCount + 1} consecutive coder delegations without reviewer/test_engineer.
|
|
49257
|
+
throw new Error(`\uD83D\uDED1 QA GATE ENFORCEMENT: ${session.qaSkipCount + 1} consecutive coder delegations without reviewer/test_engineer. Skipped tasks: [${skippedTasks}]. DELEGATE to reviewer and test_engineer NOW before any further coder work.`);
|
|
49063
49258
|
}
|
|
49064
49259
|
session.qaSkipCount++;
|
|
49065
49260
|
session.qaSkipTaskIds.push(currentTaskId ?? "unknown");
|
|
49066
|
-
warnings.push(`\u26A0\uFE0F PROTOCOL VIOLATION: Previous coder task completed, but QA gate was skipped. ` + `You MUST delegate to reviewer (code review) and test_engineer (test execution)
|
|
49261
|
+
warnings.push(`\u26A0\uFE0F PROTOCOL VIOLATION: Previous coder task completed, but QA gate was skipped. ` + `You MUST delegate to reviewer (code review) and test_engineer (test execution) before starting a new coder task. Review RULES 7-8 in your system prompt.`);
|
|
49067
49262
|
}
|
|
49068
49263
|
}
|
|
49069
49264
|
}
|
|
@@ -49415,7 +49610,7 @@ import * as fs16 from "fs";
|
|
|
49415
49610
|
init_utils2();
|
|
49416
49611
|
init_manager2();
|
|
49417
49612
|
import * as fs15 from "fs";
|
|
49418
|
-
import * as
|
|
49613
|
+
import * as path28 from "path";
|
|
49419
49614
|
var DEFAULT_DRIFT_CONFIG = {
|
|
49420
49615
|
staleThresholdPhases: 1,
|
|
49421
49616
|
detectContradictions: true,
|
|
@@ -49569,7 +49764,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
49569
49764
|
currentPhase = legacyPhase;
|
|
49570
49765
|
}
|
|
49571
49766
|
}
|
|
49572
|
-
const contextPath =
|
|
49767
|
+
const contextPath = path28.join(directory, ".swarm", "context.md");
|
|
49573
49768
|
let contextContent = "";
|
|
49574
49769
|
try {
|
|
49575
49770
|
if (fs15.existsSync(contextPath)) {
|
|
@@ -51192,7 +51387,7 @@ function createDarkMatterDetectorHook(directory) {
|
|
|
51192
51387
|
// src/hooks/knowledge-reader.ts
|
|
51193
51388
|
import { existsSync as existsSync18 } from "fs";
|
|
51194
51389
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
51195
|
-
import * as
|
|
51390
|
+
import * as path29 from "path";
|
|
51196
51391
|
var JACCARD_THRESHOLD = 0.6;
|
|
51197
51392
|
var HIVE_TIER_BOOST = 0.05;
|
|
51198
51393
|
var SAME_PROJECT_PENALTY = -0.05;
|
|
@@ -51240,7 +51435,7 @@ function inferCategoriesFromPhase(phaseDescription) {
|
|
|
51240
51435
|
return ["process", "tooling"];
|
|
51241
51436
|
}
|
|
51242
51437
|
async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
51243
|
-
const shownFile =
|
|
51438
|
+
const shownFile = path29.join(directory, ".swarm", ".knowledge-shown.json");
|
|
51244
51439
|
try {
|
|
51245
51440
|
let shownData = {};
|
|
51246
51441
|
if (existsSync18(shownFile)) {
|
|
@@ -51248,7 +51443,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
|
51248
51443
|
shownData = JSON.parse(content);
|
|
51249
51444
|
}
|
|
51250
51445
|
shownData[currentPhase] = lessonIds;
|
|
51251
|
-
await mkdir4(
|
|
51446
|
+
await mkdir4(path29.dirname(shownFile), { recursive: true });
|
|
51252
51447
|
await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
51253
51448
|
} catch {
|
|
51254
51449
|
console.warn("[swarm] Knowledge: failed to record shown lessons");
|
|
@@ -51343,7 +51538,7 @@ async function readMergedKnowledge(directory, config3, context) {
|
|
|
51343
51538
|
return topN;
|
|
51344
51539
|
}
|
|
51345
51540
|
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
51346
|
-
const shownFile =
|
|
51541
|
+
const shownFile = path29.join(directory, ".swarm", ".knowledge-shown.json");
|
|
51347
51542
|
try {
|
|
51348
51543
|
if (!existsSync18(shownFile)) {
|
|
51349
51544
|
return;
|
|
@@ -51816,10 +52011,10 @@ Use this data to avoid repeating known failure patterns.`;
|
|
|
51816
52011
|
init_event_bus();
|
|
51817
52012
|
init_utils2();
|
|
51818
52013
|
import * as fs17 from "fs";
|
|
51819
|
-
import * as
|
|
52014
|
+
import * as path30 from "path";
|
|
51820
52015
|
var DRIFT_REPORT_PREFIX = "drift-report-phase-";
|
|
51821
52016
|
async function readPriorDriftReports(directory) {
|
|
51822
|
-
const swarmDir =
|
|
52017
|
+
const swarmDir = path30.join(directory, ".swarm");
|
|
51823
52018
|
const entries = await fs17.promises.readdir(swarmDir).catch(() => null);
|
|
51824
52019
|
if (entries === null)
|
|
51825
52020
|
return [];
|
|
@@ -51846,7 +52041,7 @@ async function readPriorDriftReports(directory) {
|
|
|
51846
52041
|
async function writeDriftReport(directory, report) {
|
|
51847
52042
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
51848
52043
|
const filePath = validateSwarmPath(directory, filename);
|
|
51849
|
-
const swarmDir =
|
|
52044
|
+
const swarmDir = path30.dirname(filePath);
|
|
51850
52045
|
await fs17.promises.mkdir(swarmDir, { recursive: true });
|
|
51851
52046
|
try {
|
|
51852
52047
|
await fs17.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
@@ -52155,7 +52350,7 @@ init_config_doctor();
|
|
|
52155
52350
|
|
|
52156
52351
|
// src/session/snapshot-reader.ts
|
|
52157
52352
|
init_utils2();
|
|
52158
|
-
import
|
|
52353
|
+
import path31 from "path";
|
|
52159
52354
|
var VALID_TASK_WORKFLOW_STATES = [
|
|
52160
52355
|
"idle",
|
|
52161
52356
|
"coder_delegated",
|
|
@@ -52278,7 +52473,7 @@ function rehydrateState(snapshot) {
|
|
|
52278
52473
|
async function reconcileTaskStatesFromPlan(directory) {
|
|
52279
52474
|
let raw;
|
|
52280
52475
|
try {
|
|
52281
|
-
raw = await Bun.file(
|
|
52476
|
+
raw = await Bun.file(path31.join(directory, ".swarm/plan.json")).text();
|
|
52282
52477
|
} catch {
|
|
52283
52478
|
return;
|
|
52284
52479
|
}
|
|
@@ -52502,7 +52697,7 @@ init_tool();
|
|
|
52502
52697
|
init_create_tool();
|
|
52503
52698
|
import { spawnSync } from "child_process";
|
|
52504
52699
|
import * as fs19 from "fs";
|
|
52505
|
-
import * as
|
|
52700
|
+
import * as path32 from "path";
|
|
52506
52701
|
var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json";
|
|
52507
52702
|
var MAX_LABEL_LENGTH = 100;
|
|
52508
52703
|
var GIT_TIMEOUT_MS = 30000;
|
|
@@ -52553,7 +52748,7 @@ function validateLabel(label) {
|
|
|
52553
52748
|
return null;
|
|
52554
52749
|
}
|
|
52555
52750
|
function getCheckpointLogPath(directory) {
|
|
52556
|
-
return
|
|
52751
|
+
return path32.join(directory, CHECKPOINT_LOG_PATH);
|
|
52557
52752
|
}
|
|
52558
52753
|
function readCheckpointLog(directory) {
|
|
52559
52754
|
const logPath = getCheckpointLogPath(directory);
|
|
@@ -52571,7 +52766,7 @@ function readCheckpointLog(directory) {
|
|
|
52571
52766
|
}
|
|
52572
52767
|
function writeCheckpointLog(log2, directory) {
|
|
52573
52768
|
const logPath = getCheckpointLogPath(directory);
|
|
52574
|
-
const dir =
|
|
52769
|
+
const dir = path32.dirname(logPath);
|
|
52575
52770
|
if (!fs19.existsSync(dir)) {
|
|
52576
52771
|
fs19.mkdirSync(dir, { recursive: true });
|
|
52577
52772
|
}
|
|
@@ -52779,7 +52974,7 @@ var checkpoint = createSwarmTool({
|
|
|
52779
52974
|
init_dist();
|
|
52780
52975
|
init_create_tool();
|
|
52781
52976
|
import * as fs20 from "fs";
|
|
52782
|
-
import * as
|
|
52977
|
+
import * as path33 from "path";
|
|
52783
52978
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
52784
52979
|
var DEFAULT_DAYS = 90;
|
|
52785
52980
|
var DEFAULT_TOP_N = 20;
|
|
@@ -52923,7 +53118,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
52923
53118
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
52924
53119
|
const filteredChurn = new Map;
|
|
52925
53120
|
for (const [file3, count] of churnMap) {
|
|
52926
|
-
const ext =
|
|
53121
|
+
const ext = path33.extname(file3).toLowerCase();
|
|
52927
53122
|
if (extSet.has(ext)) {
|
|
52928
53123
|
filteredChurn.set(file3, count);
|
|
52929
53124
|
}
|
|
@@ -52934,7 +53129,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
52934
53129
|
for (const [file3, churnCount] of filteredChurn) {
|
|
52935
53130
|
let fullPath = file3;
|
|
52936
53131
|
if (!fs20.existsSync(fullPath)) {
|
|
52937
|
-
fullPath =
|
|
53132
|
+
fullPath = path33.join(cwd, file3);
|
|
52938
53133
|
}
|
|
52939
53134
|
const complexity = getComplexityForFile(fullPath);
|
|
52940
53135
|
if (complexity !== null) {
|
|
@@ -53082,7 +53277,7 @@ var complexity_hotspots = createSwarmTool({
|
|
|
53082
53277
|
// src/tools/declare-scope.ts
|
|
53083
53278
|
init_tool();
|
|
53084
53279
|
import * as fs21 from "fs";
|
|
53085
|
-
import * as
|
|
53280
|
+
import * as path34 from "path";
|
|
53086
53281
|
init_create_tool();
|
|
53087
53282
|
function validateTaskIdFormat(taskId) {
|
|
53088
53283
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -53161,8 +53356,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
53161
53356
|
};
|
|
53162
53357
|
}
|
|
53163
53358
|
}
|
|
53164
|
-
normalizedDir =
|
|
53165
|
-
const pathParts = normalizedDir.split(
|
|
53359
|
+
normalizedDir = path34.normalize(args2.working_directory);
|
|
53360
|
+
const pathParts = normalizedDir.split(path34.sep);
|
|
53166
53361
|
if (pathParts.includes("..")) {
|
|
53167
53362
|
return {
|
|
53168
53363
|
success: false,
|
|
@@ -53172,10 +53367,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
53172
53367
|
]
|
|
53173
53368
|
};
|
|
53174
53369
|
}
|
|
53175
|
-
const resolvedDir =
|
|
53370
|
+
const resolvedDir = path34.resolve(normalizedDir);
|
|
53176
53371
|
try {
|
|
53177
53372
|
const realPath = fs21.realpathSync(resolvedDir);
|
|
53178
|
-
const planPath2 =
|
|
53373
|
+
const planPath2 = path34.join(realPath, ".swarm", "plan.json");
|
|
53179
53374
|
if (!fs21.existsSync(planPath2)) {
|
|
53180
53375
|
return {
|
|
53181
53376
|
success: false,
|
|
@@ -53196,7 +53391,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
53196
53391
|
}
|
|
53197
53392
|
}
|
|
53198
53393
|
const directory = normalizedDir ?? fallbackDir ?? process.cwd();
|
|
53199
|
-
const planPath =
|
|
53394
|
+
const planPath = path34.resolve(directory, ".swarm", "plan.json");
|
|
53200
53395
|
if (!fs21.existsSync(planPath)) {
|
|
53201
53396
|
return {
|
|
53202
53397
|
success: false,
|
|
@@ -53286,20 +53481,20 @@ function validateBase(base) {
|
|
|
53286
53481
|
function validatePaths(paths) {
|
|
53287
53482
|
if (!paths)
|
|
53288
53483
|
return null;
|
|
53289
|
-
for (const
|
|
53290
|
-
if (!
|
|
53484
|
+
for (const path35 of paths) {
|
|
53485
|
+
if (!path35 || path35.length === 0) {
|
|
53291
53486
|
return "empty path not allowed";
|
|
53292
53487
|
}
|
|
53293
|
-
if (
|
|
53488
|
+
if (path35.length > MAX_PATH_LENGTH) {
|
|
53294
53489
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
53295
53490
|
}
|
|
53296
|
-
if (SHELL_METACHARACTERS2.test(
|
|
53491
|
+
if (SHELL_METACHARACTERS2.test(path35)) {
|
|
53297
53492
|
return "path contains shell metacharacters";
|
|
53298
53493
|
}
|
|
53299
|
-
if (
|
|
53494
|
+
if (path35.startsWith("-")) {
|
|
53300
53495
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
53301
53496
|
}
|
|
53302
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
53497
|
+
if (CONTROL_CHAR_PATTERN2.test(path35)) {
|
|
53303
53498
|
return "path contains control characters";
|
|
53304
53499
|
}
|
|
53305
53500
|
}
|
|
@@ -53379,8 +53574,8 @@ var diff = tool({
|
|
|
53379
53574
|
if (parts2.length >= 3) {
|
|
53380
53575
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
53381
53576
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
53382
|
-
const
|
|
53383
|
-
files.push({ path:
|
|
53577
|
+
const path35 = parts2[2];
|
|
53578
|
+
files.push({ path: path35, additions, deletions });
|
|
53384
53579
|
}
|
|
53385
53580
|
}
|
|
53386
53581
|
const contractChanges = [];
|
|
@@ -53610,7 +53805,7 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
53610
53805
|
init_dist();
|
|
53611
53806
|
init_create_tool();
|
|
53612
53807
|
import * as fs22 from "fs";
|
|
53613
|
-
import * as
|
|
53808
|
+
import * as path35 from "path";
|
|
53614
53809
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
53615
53810
|
var MAX_EVIDENCE_FILES = 1000;
|
|
53616
53811
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
@@ -53633,9 +53828,9 @@ function validateRequiredTypes(input) {
|
|
|
53633
53828
|
return null;
|
|
53634
53829
|
}
|
|
53635
53830
|
function isPathWithinSwarm(filePath, cwd) {
|
|
53636
|
-
const normalizedCwd =
|
|
53637
|
-
const swarmPath =
|
|
53638
|
-
const normalizedPath =
|
|
53831
|
+
const normalizedCwd = path35.resolve(cwd);
|
|
53832
|
+
const swarmPath = path35.join(normalizedCwd, ".swarm");
|
|
53833
|
+
const normalizedPath = path35.resolve(filePath);
|
|
53639
53834
|
return normalizedPath.startsWith(swarmPath);
|
|
53640
53835
|
}
|
|
53641
53836
|
function parseCompletedTasks(planContent) {
|
|
@@ -53665,10 +53860,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
53665
53860
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
53666
53861
|
continue;
|
|
53667
53862
|
}
|
|
53668
|
-
const filePath =
|
|
53863
|
+
const filePath = path35.join(evidenceDir, filename);
|
|
53669
53864
|
try {
|
|
53670
|
-
const resolvedPath =
|
|
53671
|
-
const evidenceDirResolved =
|
|
53865
|
+
const resolvedPath = path35.resolve(filePath);
|
|
53866
|
+
const evidenceDirResolved = path35.resolve(evidenceDir);
|
|
53672
53867
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
53673
53868
|
continue;
|
|
53674
53869
|
}
|
|
@@ -53775,7 +53970,7 @@ var evidence_check = createSwarmTool({
|
|
|
53775
53970
|
return JSON.stringify(errorResult, null, 2);
|
|
53776
53971
|
}
|
|
53777
53972
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
53778
|
-
const planPath =
|
|
53973
|
+
const planPath = path35.join(cwd, PLAN_FILE);
|
|
53779
53974
|
if (!isPathWithinSwarm(planPath, cwd)) {
|
|
53780
53975
|
const errorResult = {
|
|
53781
53976
|
error: "plan file path validation failed",
|
|
@@ -53807,7 +54002,7 @@ var evidence_check = createSwarmTool({
|
|
|
53807
54002
|
};
|
|
53808
54003
|
return JSON.stringify(result2, null, 2);
|
|
53809
54004
|
}
|
|
53810
|
-
const evidenceDir =
|
|
54005
|
+
const evidenceDir = path35.join(cwd, EVIDENCE_DIR);
|
|
53811
54006
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
53812
54007
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
53813
54008
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -53825,7 +54020,7 @@ var evidence_check = createSwarmTool({
|
|
|
53825
54020
|
init_tool();
|
|
53826
54021
|
init_create_tool();
|
|
53827
54022
|
import * as fs23 from "fs";
|
|
53828
|
-
import * as
|
|
54023
|
+
import * as path36 from "path";
|
|
53829
54024
|
var EXT_MAP = {
|
|
53830
54025
|
python: ".py",
|
|
53831
54026
|
py: ".py",
|
|
@@ -53906,12 +54101,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
53906
54101
|
if (prefix) {
|
|
53907
54102
|
filename = `${prefix}_${filename}`;
|
|
53908
54103
|
}
|
|
53909
|
-
let filepath =
|
|
53910
|
-
const base =
|
|
53911
|
-
const ext =
|
|
54104
|
+
let filepath = path36.join(targetDir, filename);
|
|
54105
|
+
const base = path36.basename(filepath, path36.extname(filepath));
|
|
54106
|
+
const ext = path36.extname(filepath);
|
|
53912
54107
|
let counter = 1;
|
|
53913
54108
|
while (fs23.existsSync(filepath)) {
|
|
53914
|
-
filepath =
|
|
54109
|
+
filepath = path36.join(targetDir, `${base}_${counter}${ext}`);
|
|
53915
54110
|
counter++;
|
|
53916
54111
|
}
|
|
53917
54112
|
try {
|
|
@@ -54029,7 +54224,7 @@ var gitingest = tool({
|
|
|
54029
54224
|
// src/tools/imports.ts
|
|
54030
54225
|
init_dist();
|
|
54031
54226
|
import * as fs24 from "fs";
|
|
54032
|
-
import * as
|
|
54227
|
+
import * as path37 from "path";
|
|
54033
54228
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
54034
54229
|
var MAX_SYMBOL_LENGTH = 256;
|
|
54035
54230
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
@@ -54083,7 +54278,7 @@ function validateSymbolInput(symbol3) {
|
|
|
54083
54278
|
return null;
|
|
54084
54279
|
}
|
|
54085
54280
|
function isBinaryFile2(filePath, buffer) {
|
|
54086
|
-
const ext =
|
|
54281
|
+
const ext = path37.extname(filePath).toLowerCase();
|
|
54087
54282
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
54088
54283
|
return false;
|
|
54089
54284
|
}
|
|
@@ -54107,15 +54302,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
54107
54302
|
const imports = [];
|
|
54108
54303
|
let _resolvedTarget;
|
|
54109
54304
|
try {
|
|
54110
|
-
_resolvedTarget =
|
|
54305
|
+
_resolvedTarget = path37.resolve(targetFile);
|
|
54111
54306
|
} catch {
|
|
54112
54307
|
_resolvedTarget = targetFile;
|
|
54113
54308
|
}
|
|
54114
|
-
const targetBasename =
|
|
54309
|
+
const targetBasename = path37.basename(targetFile, path37.extname(targetFile));
|
|
54115
54310
|
const targetWithExt = targetFile;
|
|
54116
54311
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
54117
|
-
const normalizedTargetWithExt =
|
|
54118
|
-
const normalizedTargetWithoutExt =
|
|
54312
|
+
const normalizedTargetWithExt = path37.normalize(targetWithExt).replace(/\\/g, "/");
|
|
54313
|
+
const normalizedTargetWithoutExt = path37.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
54119
54314
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
54120
54315
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
54121
54316
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -54138,9 +54333,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
54138
54333
|
}
|
|
54139
54334
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
54140
54335
|
let isMatch = false;
|
|
54141
|
-
const _targetDir =
|
|
54142
|
-
const targetExt =
|
|
54143
|
-
const targetBasenameNoExt =
|
|
54336
|
+
const _targetDir = path37.dirname(targetFile);
|
|
54337
|
+
const targetExt = path37.extname(targetFile);
|
|
54338
|
+
const targetBasenameNoExt = path37.basename(targetFile, targetExt);
|
|
54144
54339
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
54145
54340
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
54146
54341
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -54208,10 +54403,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
54208
54403
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
54209
54404
|
for (const entry of entries) {
|
|
54210
54405
|
if (SKIP_DIRECTORIES2.has(entry)) {
|
|
54211
|
-
stats.skippedDirs.push(
|
|
54406
|
+
stats.skippedDirs.push(path37.join(dir, entry));
|
|
54212
54407
|
continue;
|
|
54213
54408
|
}
|
|
54214
|
-
const fullPath =
|
|
54409
|
+
const fullPath = path37.join(dir, entry);
|
|
54215
54410
|
let stat2;
|
|
54216
54411
|
try {
|
|
54217
54412
|
stat2 = fs24.statSync(fullPath);
|
|
@@ -54225,7 +54420,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
54225
54420
|
if (stat2.isDirectory()) {
|
|
54226
54421
|
findSourceFiles2(fullPath, files, stats);
|
|
54227
54422
|
} else if (stat2.isFile()) {
|
|
54228
|
-
const ext =
|
|
54423
|
+
const ext = path37.extname(fullPath).toLowerCase();
|
|
54229
54424
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
54230
54425
|
files.push(fullPath);
|
|
54231
54426
|
}
|
|
@@ -54281,7 +54476,7 @@ var imports = tool({
|
|
|
54281
54476
|
return JSON.stringify(errorResult, null, 2);
|
|
54282
54477
|
}
|
|
54283
54478
|
try {
|
|
54284
|
-
const targetFile =
|
|
54479
|
+
const targetFile = path37.resolve(file3);
|
|
54285
54480
|
if (!fs24.existsSync(targetFile)) {
|
|
54286
54481
|
const errorResult = {
|
|
54287
54482
|
error: `target file not found: ${file3}`,
|
|
@@ -54303,7 +54498,7 @@ var imports = tool({
|
|
|
54303
54498
|
};
|
|
54304
54499
|
return JSON.stringify(errorResult, null, 2);
|
|
54305
54500
|
}
|
|
54306
|
-
const baseDir =
|
|
54501
|
+
const baseDir = path37.dirname(targetFile);
|
|
54307
54502
|
const scanStats = {
|
|
54308
54503
|
skippedDirs: [],
|
|
54309
54504
|
skippedFiles: 0,
|
|
@@ -54625,7 +54820,7 @@ init_config();
|
|
|
54625
54820
|
init_schema();
|
|
54626
54821
|
init_manager();
|
|
54627
54822
|
import * as fs25 from "fs";
|
|
54628
|
-
import * as
|
|
54823
|
+
import * as path38 from "path";
|
|
54629
54824
|
init_utils2();
|
|
54630
54825
|
init_create_tool();
|
|
54631
54826
|
function safeWarn(message, error93) {
|
|
@@ -54820,7 +55015,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
54820
55015
|
}
|
|
54821
55016
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
54822
55017
|
try {
|
|
54823
|
-
const projectName =
|
|
55018
|
+
const projectName = path38.basename(dir);
|
|
54824
55019
|
const knowledgeConfig = {
|
|
54825
55020
|
enabled: true,
|
|
54826
55021
|
swarm_max_entries: 100,
|
|
@@ -54984,7 +55179,7 @@ init_discovery();
|
|
|
54984
55179
|
init_utils();
|
|
54985
55180
|
init_create_tool();
|
|
54986
55181
|
import * as fs26 from "fs";
|
|
54987
|
-
import * as
|
|
55182
|
+
import * as path39 from "path";
|
|
54988
55183
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
54989
55184
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
54990
55185
|
function isValidEcosystem(value) {
|
|
@@ -55002,16 +55197,16 @@ function validateArgs3(args2) {
|
|
|
55002
55197
|
function detectEcosystems(directory) {
|
|
55003
55198
|
const ecosystems = [];
|
|
55004
55199
|
const cwd = directory;
|
|
55005
|
-
if (fs26.existsSync(
|
|
55200
|
+
if (fs26.existsSync(path39.join(cwd, "package.json"))) {
|
|
55006
55201
|
ecosystems.push("npm");
|
|
55007
55202
|
}
|
|
55008
|
-
if (fs26.existsSync(
|
|
55203
|
+
if (fs26.existsSync(path39.join(cwd, "pyproject.toml")) || fs26.existsSync(path39.join(cwd, "requirements.txt"))) {
|
|
55009
55204
|
ecosystems.push("pip");
|
|
55010
55205
|
}
|
|
55011
|
-
if (fs26.existsSync(
|
|
55206
|
+
if (fs26.existsSync(path39.join(cwd, "Cargo.toml"))) {
|
|
55012
55207
|
ecosystems.push("cargo");
|
|
55013
55208
|
}
|
|
55014
|
-
if (fs26.existsSync(
|
|
55209
|
+
if (fs26.existsSync(path39.join(cwd, "go.mod"))) {
|
|
55015
55210
|
ecosystems.push("go");
|
|
55016
55211
|
}
|
|
55017
55212
|
try {
|
|
@@ -55020,10 +55215,10 @@ function detectEcosystems(directory) {
|
|
|
55020
55215
|
ecosystems.push("dotnet");
|
|
55021
55216
|
}
|
|
55022
55217
|
} catch {}
|
|
55023
|
-
if (fs26.existsSync(
|
|
55218
|
+
if (fs26.existsSync(path39.join(cwd, "Gemfile")) || fs26.existsSync(path39.join(cwd, "Gemfile.lock"))) {
|
|
55024
55219
|
ecosystems.push("ruby");
|
|
55025
55220
|
}
|
|
55026
|
-
if (fs26.existsSync(
|
|
55221
|
+
if (fs26.existsSync(path39.join(cwd, "pubspec.yaml"))) {
|
|
55027
55222
|
ecosystems.push("dart");
|
|
55028
55223
|
}
|
|
55029
55224
|
return ecosystems;
|
|
@@ -56086,7 +56281,7 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
56086
56281
|
// src/tools/pre-check-batch.ts
|
|
56087
56282
|
init_dist();
|
|
56088
56283
|
import * as fs29 from "fs";
|
|
56089
|
-
import * as
|
|
56284
|
+
import * as path42 from "path";
|
|
56090
56285
|
|
|
56091
56286
|
// node_modules/yocto-queue/index.js
|
|
56092
56287
|
class Node2 {
|
|
@@ -56254,7 +56449,7 @@ init_manager();
|
|
|
56254
56449
|
|
|
56255
56450
|
// src/quality/metrics.ts
|
|
56256
56451
|
import * as fs27 from "fs";
|
|
56257
|
-
import * as
|
|
56452
|
+
import * as path40 from "path";
|
|
56258
56453
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
56259
56454
|
var MIN_DUPLICATION_LINES = 10;
|
|
56260
56455
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -56306,7 +56501,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
56306
56501
|
let totalComplexity = 0;
|
|
56307
56502
|
const analyzedFiles = [];
|
|
56308
56503
|
for (const file3 of files) {
|
|
56309
|
-
const fullPath =
|
|
56504
|
+
const fullPath = path40.isAbsolute(file3) ? file3 : path40.join(workingDir, file3);
|
|
56310
56505
|
if (!fs27.existsSync(fullPath)) {
|
|
56311
56506
|
continue;
|
|
56312
56507
|
}
|
|
@@ -56429,7 +56624,7 @@ function countGoExports(content) {
|
|
|
56429
56624
|
function getExportCountForFile(filePath) {
|
|
56430
56625
|
try {
|
|
56431
56626
|
const content = fs27.readFileSync(filePath, "utf-8");
|
|
56432
|
-
const ext =
|
|
56627
|
+
const ext = path40.extname(filePath).toLowerCase();
|
|
56433
56628
|
switch (ext) {
|
|
56434
56629
|
case ".ts":
|
|
56435
56630
|
case ".tsx":
|
|
@@ -56455,7 +56650,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
56455
56650
|
let totalExports = 0;
|
|
56456
56651
|
const analyzedFiles = [];
|
|
56457
56652
|
for (const file3 of files) {
|
|
56458
|
-
const fullPath =
|
|
56653
|
+
const fullPath = path40.isAbsolute(file3) ? file3 : path40.join(workingDir, file3);
|
|
56459
56654
|
if (!fs27.existsSync(fullPath)) {
|
|
56460
56655
|
continue;
|
|
56461
56656
|
}
|
|
@@ -56489,7 +56684,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
56489
56684
|
let duplicateLines = 0;
|
|
56490
56685
|
const analyzedFiles = [];
|
|
56491
56686
|
for (const file3 of files) {
|
|
56492
|
-
const fullPath =
|
|
56687
|
+
const fullPath = path40.isAbsolute(file3) ? file3 : path40.join(workingDir, file3);
|
|
56493
56688
|
if (!fs27.existsSync(fullPath)) {
|
|
56494
56689
|
continue;
|
|
56495
56690
|
}
|
|
@@ -56522,8 +56717,8 @@ function countCodeLines(content) {
|
|
|
56522
56717
|
return lines.length;
|
|
56523
56718
|
}
|
|
56524
56719
|
function isTestFile(filePath) {
|
|
56525
|
-
const basename8 =
|
|
56526
|
-
const _ext =
|
|
56720
|
+
const basename8 = path40.basename(filePath);
|
|
56721
|
+
const _ext = path40.extname(filePath).toLowerCase();
|
|
56527
56722
|
const testPatterns = [
|
|
56528
56723
|
".test.",
|
|
56529
56724
|
".spec.",
|
|
@@ -56604,8 +56799,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
56604
56799
|
}
|
|
56605
56800
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
56606
56801
|
}
|
|
56607
|
-
function matchesGlobSegment(
|
|
56608
|
-
const normalizedPath =
|
|
56802
|
+
function matchesGlobSegment(path41, glob) {
|
|
56803
|
+
const normalizedPath = path41.replace(/\\/g, "/");
|
|
56609
56804
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
56610
56805
|
if (normalizedPath.includes("//")) {
|
|
56611
56806
|
return false;
|
|
@@ -56636,8 +56831,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
56636
56831
|
function hasGlobstar(glob) {
|
|
56637
56832
|
return glob.includes("**");
|
|
56638
56833
|
}
|
|
56639
|
-
function globMatches(
|
|
56640
|
-
const normalizedPath =
|
|
56834
|
+
function globMatches(path41, glob) {
|
|
56835
|
+
const normalizedPath = path41.replace(/\\/g, "/");
|
|
56641
56836
|
if (!glob || glob === "") {
|
|
56642
56837
|
if (normalizedPath.includes("//")) {
|
|
56643
56838
|
return false;
|
|
@@ -56673,7 +56868,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
56673
56868
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
56674
56869
|
let testLines = 0;
|
|
56675
56870
|
let codeLines = 0;
|
|
56676
|
-
const srcDir =
|
|
56871
|
+
const srcDir = path40.join(workingDir, "src");
|
|
56677
56872
|
if (fs27.existsSync(srcDir)) {
|
|
56678
56873
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
56679
56874
|
codeLines += lines;
|
|
@@ -56681,14 +56876,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
56681
56876
|
}
|
|
56682
56877
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
56683
56878
|
for (const dir of possibleSrcDirs) {
|
|
56684
|
-
const dirPath =
|
|
56879
|
+
const dirPath = path40.join(workingDir, dir);
|
|
56685
56880
|
if (fs27.existsSync(dirPath)) {
|
|
56686
56881
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
56687
56882
|
codeLines += lines;
|
|
56688
56883
|
});
|
|
56689
56884
|
}
|
|
56690
56885
|
}
|
|
56691
|
-
const testsDir =
|
|
56886
|
+
const testsDir = path40.join(workingDir, "tests");
|
|
56692
56887
|
if (fs27.existsSync(testsDir)) {
|
|
56693
56888
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
56694
56889
|
testLines += lines;
|
|
@@ -56696,7 +56891,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
56696
56891
|
}
|
|
56697
56892
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
56698
56893
|
for (const dir of possibleTestDirs) {
|
|
56699
|
-
const dirPath =
|
|
56894
|
+
const dirPath = path40.join(workingDir, dir);
|
|
56700
56895
|
if (fs27.existsSync(dirPath) && dirPath !== testsDir) {
|
|
56701
56896
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
56702
56897
|
testLines += lines;
|
|
@@ -56711,7 +56906,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
56711
56906
|
try {
|
|
56712
56907
|
const entries = fs27.readdirSync(dirPath, { withFileTypes: true });
|
|
56713
56908
|
for (const entry of entries) {
|
|
56714
|
-
const fullPath =
|
|
56909
|
+
const fullPath = path40.join(dirPath, entry.name);
|
|
56715
56910
|
if (entry.isDirectory()) {
|
|
56716
56911
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
56717
56912
|
continue;
|
|
@@ -56719,7 +56914,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
56719
56914
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
56720
56915
|
} else if (entry.isFile()) {
|
|
56721
56916
|
const relativePath = fullPath.replace(`${process.cwd()}/`, "");
|
|
56722
|
-
const ext =
|
|
56917
|
+
const ext = path40.extname(entry.name).toLowerCase();
|
|
56723
56918
|
const validExts = [
|
|
56724
56919
|
".ts",
|
|
56725
56920
|
".tsx",
|
|
@@ -56970,7 +57165,7 @@ init_dist();
|
|
|
56970
57165
|
init_manager();
|
|
56971
57166
|
init_detector();
|
|
56972
57167
|
import * as fs28 from "fs";
|
|
56973
|
-
import * as
|
|
57168
|
+
import * as path41 from "path";
|
|
56974
57169
|
import { extname as extname9 } from "path";
|
|
56975
57170
|
|
|
56976
57171
|
// src/sast/rules/c.ts
|
|
@@ -57933,7 +58128,7 @@ async function sastScan(input, directory, config3) {
|
|
|
57933
58128
|
_filesSkipped++;
|
|
57934
58129
|
continue;
|
|
57935
58130
|
}
|
|
57936
|
-
const resolvedPath =
|
|
58131
|
+
const resolvedPath = path41.isAbsolute(filePath) ? filePath : path41.resolve(directory, filePath);
|
|
57937
58132
|
if (!fs28.existsSync(resolvedPath)) {
|
|
57938
58133
|
_filesSkipped++;
|
|
57939
58134
|
continue;
|
|
@@ -58132,18 +58327,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
58132
58327
|
let resolved;
|
|
58133
58328
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
58134
58329
|
if (isWinAbs) {
|
|
58135
|
-
resolved =
|
|
58136
|
-
} else if (
|
|
58137
|
-
resolved =
|
|
58330
|
+
resolved = path42.win32.resolve(inputPath);
|
|
58331
|
+
} else if (path42.isAbsolute(inputPath)) {
|
|
58332
|
+
resolved = path42.resolve(inputPath);
|
|
58138
58333
|
} else {
|
|
58139
|
-
resolved =
|
|
58334
|
+
resolved = path42.resolve(baseDir, inputPath);
|
|
58140
58335
|
}
|
|
58141
|
-
const workspaceResolved =
|
|
58336
|
+
const workspaceResolved = path42.resolve(workspaceDir);
|
|
58142
58337
|
let relative5;
|
|
58143
58338
|
if (isWinAbs) {
|
|
58144
|
-
relative5 =
|
|
58339
|
+
relative5 = path42.win32.relative(workspaceResolved, resolved);
|
|
58145
58340
|
} else {
|
|
58146
|
-
relative5 =
|
|
58341
|
+
relative5 = path42.relative(workspaceResolved, resolved);
|
|
58147
58342
|
}
|
|
58148
58343
|
if (relative5.startsWith("..")) {
|
|
58149
58344
|
return "path traversal detected";
|
|
@@ -58204,13 +58399,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
58204
58399
|
}
|
|
58205
58400
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
58206
58401
|
const isWindows = process.platform === "win32";
|
|
58207
|
-
const binDir =
|
|
58402
|
+
const binDir = path42.join(workspaceDir, "node_modules", ".bin");
|
|
58208
58403
|
const validatedFiles = [];
|
|
58209
58404
|
for (const file3 of files) {
|
|
58210
58405
|
if (typeof file3 !== "string") {
|
|
58211
58406
|
continue;
|
|
58212
58407
|
}
|
|
58213
|
-
const resolvedPath =
|
|
58408
|
+
const resolvedPath = path42.resolve(file3);
|
|
58214
58409
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
58215
58410
|
if (validationError) {
|
|
58216
58411
|
continue;
|
|
@@ -58228,10 +58423,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
58228
58423
|
}
|
|
58229
58424
|
let command;
|
|
58230
58425
|
if (linter === "biome") {
|
|
58231
|
-
const biomeBin = isWindows ?
|
|
58426
|
+
const biomeBin = isWindows ? path42.join(binDir, "biome.EXE") : path42.join(binDir, "biome");
|
|
58232
58427
|
command = [biomeBin, "check", ...validatedFiles];
|
|
58233
58428
|
} else {
|
|
58234
|
-
const eslintBin = isWindows ?
|
|
58429
|
+
const eslintBin = isWindows ? path42.join(binDir, "eslint.cmd") : path42.join(binDir, "eslint");
|
|
58235
58430
|
command = [eslintBin, ...validatedFiles];
|
|
58236
58431
|
}
|
|
58237
58432
|
try {
|
|
@@ -58368,7 +58563,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
58368
58563
|
skippedFiles++;
|
|
58369
58564
|
continue;
|
|
58370
58565
|
}
|
|
58371
|
-
const resolvedPath =
|
|
58566
|
+
const resolvedPath = path42.resolve(file3);
|
|
58372
58567
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
58373
58568
|
if (validationError) {
|
|
58374
58569
|
skippedFiles++;
|
|
@@ -58386,7 +58581,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
58386
58581
|
};
|
|
58387
58582
|
}
|
|
58388
58583
|
for (const file3 of validatedFiles) {
|
|
58389
|
-
const ext =
|
|
58584
|
+
const ext = path42.extname(file3).toLowerCase();
|
|
58390
58585
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
58391
58586
|
skippedFiles++;
|
|
58392
58587
|
continue;
|
|
@@ -58545,7 +58740,7 @@ async function runPreCheckBatch(input, workspaceDir) {
|
|
|
58545
58740
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
58546
58741
|
continue;
|
|
58547
58742
|
}
|
|
58548
|
-
changedFiles.push(
|
|
58743
|
+
changedFiles.push(path42.resolve(directory, file3));
|
|
58549
58744
|
}
|
|
58550
58745
|
if (changedFiles.length === 0) {
|
|
58551
58746
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -58696,7 +58891,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
58696
58891
|
};
|
|
58697
58892
|
return JSON.stringify(errorResult, null, 2);
|
|
58698
58893
|
}
|
|
58699
|
-
const resolvedDirectory =
|
|
58894
|
+
const resolvedDirectory = path42.resolve(typedArgs.directory);
|
|
58700
58895
|
const workspaceAnchor = resolvedDirectory;
|
|
58701
58896
|
const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
|
|
58702
58897
|
if (dirError) {
|
|
@@ -58804,7 +58999,7 @@ init_tool();
|
|
|
58804
58999
|
init_manager2();
|
|
58805
59000
|
init_create_tool();
|
|
58806
59001
|
import * as fs30 from "fs";
|
|
58807
|
-
import * as
|
|
59002
|
+
import * as path43 from "path";
|
|
58808
59003
|
function detectPlaceholderContent(args2) {
|
|
58809
59004
|
const issues = [];
|
|
58810
59005
|
const placeholderPattern = /^\[\w[\w\s]*\]$/;
|
|
@@ -58908,7 +59103,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
58908
59103
|
try {
|
|
58909
59104
|
await savePlan(dir, plan);
|
|
58910
59105
|
try {
|
|
58911
|
-
const markerPath =
|
|
59106
|
+
const markerPath = path43.join(dir, ".swarm", ".plan-write-marker");
|
|
58912
59107
|
const marker = JSON.stringify({
|
|
58913
59108
|
source: "save_plan",
|
|
58914
59109
|
timestamp: new Date().toISOString(),
|
|
@@ -58920,7 +59115,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
58920
59115
|
return {
|
|
58921
59116
|
success: true,
|
|
58922
59117
|
message: "Plan saved successfully",
|
|
58923
|
-
plan_path:
|
|
59118
|
+
plan_path: path43.join(dir, ".swarm", "plan.json"),
|
|
58924
59119
|
phases_count: plan.phases.length,
|
|
58925
59120
|
tasks_count: tasksCount
|
|
58926
59121
|
};
|
|
@@ -58959,7 +59154,7 @@ var save_plan = createSwarmTool({
|
|
|
58959
59154
|
init_dist();
|
|
58960
59155
|
init_manager();
|
|
58961
59156
|
import * as fs31 from "fs";
|
|
58962
|
-
import * as
|
|
59157
|
+
import * as path44 from "path";
|
|
58963
59158
|
|
|
58964
59159
|
// src/sbom/detectors/index.ts
|
|
58965
59160
|
init_utils();
|
|
@@ -59807,7 +60002,7 @@ function findManifestFiles(rootDir) {
|
|
|
59807
60002
|
try {
|
|
59808
60003
|
const entries = fs31.readdirSync(dir, { withFileTypes: true });
|
|
59809
60004
|
for (const entry of entries) {
|
|
59810
|
-
const fullPath =
|
|
60005
|
+
const fullPath = path44.join(dir, entry.name);
|
|
59811
60006
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
59812
60007
|
continue;
|
|
59813
60008
|
}
|
|
@@ -59816,7 +60011,7 @@ function findManifestFiles(rootDir) {
|
|
|
59816
60011
|
} else if (entry.isFile()) {
|
|
59817
60012
|
for (const pattern of patterns) {
|
|
59818
60013
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
59819
|
-
manifestFiles.push(
|
|
60014
|
+
manifestFiles.push(path44.relative(rootDir, fullPath));
|
|
59820
60015
|
break;
|
|
59821
60016
|
}
|
|
59822
60017
|
}
|
|
@@ -59834,11 +60029,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
59834
60029
|
try {
|
|
59835
60030
|
const entries = fs31.readdirSync(dir, { withFileTypes: true });
|
|
59836
60031
|
for (const entry of entries) {
|
|
59837
|
-
const fullPath =
|
|
60032
|
+
const fullPath = path44.join(dir, entry.name);
|
|
59838
60033
|
if (entry.isFile()) {
|
|
59839
60034
|
for (const pattern of patterns) {
|
|
59840
60035
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
59841
|
-
found.push(
|
|
60036
|
+
found.push(path44.relative(workingDir, fullPath));
|
|
59842
60037
|
break;
|
|
59843
60038
|
}
|
|
59844
60039
|
}
|
|
@@ -59851,11 +60046,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
59851
60046
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
59852
60047
|
const dirs = new Set;
|
|
59853
60048
|
for (const file3 of changedFiles) {
|
|
59854
|
-
let currentDir =
|
|
60049
|
+
let currentDir = path44.dirname(file3);
|
|
59855
60050
|
while (true) {
|
|
59856
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
59857
|
-
dirs.add(
|
|
59858
|
-
const parent =
|
|
60051
|
+
if (currentDir && currentDir !== "." && currentDir !== path44.sep) {
|
|
60052
|
+
dirs.add(path44.join(workingDir, currentDir));
|
|
60053
|
+
const parent = path44.dirname(currentDir);
|
|
59859
60054
|
if (parent === currentDir)
|
|
59860
60055
|
break;
|
|
59861
60056
|
currentDir = parent;
|
|
@@ -59939,7 +60134,7 @@ var sbom_generate = createSwarmTool({
|
|
|
59939
60134
|
const changedFiles = obj.changed_files;
|
|
59940
60135
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
59941
60136
|
const workingDir = directory;
|
|
59942
|
-
const outputDir =
|
|
60137
|
+
const outputDir = path44.isAbsolute(relativeOutputDir) ? relativeOutputDir : path44.join(workingDir, relativeOutputDir);
|
|
59943
60138
|
let manifestFiles = [];
|
|
59944
60139
|
if (scope === "all") {
|
|
59945
60140
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -59962,7 +60157,7 @@ var sbom_generate = createSwarmTool({
|
|
|
59962
60157
|
const processedFiles = [];
|
|
59963
60158
|
for (const manifestFile of manifestFiles) {
|
|
59964
60159
|
try {
|
|
59965
|
-
const fullPath =
|
|
60160
|
+
const fullPath = path44.isAbsolute(manifestFile) ? manifestFile : path44.join(workingDir, manifestFile);
|
|
59966
60161
|
if (!fs31.existsSync(fullPath)) {
|
|
59967
60162
|
continue;
|
|
59968
60163
|
}
|
|
@@ -59979,7 +60174,7 @@ var sbom_generate = createSwarmTool({
|
|
|
59979
60174
|
const bom = generateCycloneDX(allComponents);
|
|
59980
60175
|
const bomJson = serializeCycloneDX(bom);
|
|
59981
60176
|
const filename = generateSbomFilename();
|
|
59982
|
-
const outputPath =
|
|
60177
|
+
const outputPath = path44.join(outputDir, filename);
|
|
59983
60178
|
fs31.writeFileSync(outputPath, bomJson, "utf-8");
|
|
59984
60179
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
59985
60180
|
try {
|
|
@@ -60023,7 +60218,7 @@ var sbom_generate = createSwarmTool({
|
|
|
60023
60218
|
init_dist();
|
|
60024
60219
|
init_create_tool();
|
|
60025
60220
|
import * as fs32 from "fs";
|
|
60026
|
-
import * as
|
|
60221
|
+
import * as path45 from "path";
|
|
60027
60222
|
var SPEC_CANDIDATES = [
|
|
60028
60223
|
"openapi.json",
|
|
60029
60224
|
"openapi.yaml",
|
|
@@ -60055,12 +60250,12 @@ function normalizePath2(p) {
|
|
|
60055
60250
|
}
|
|
60056
60251
|
function discoverSpecFile(cwd, specFileArg) {
|
|
60057
60252
|
if (specFileArg) {
|
|
60058
|
-
const resolvedPath =
|
|
60059
|
-
const normalizedCwd = cwd.endsWith(
|
|
60253
|
+
const resolvedPath = path45.resolve(cwd, specFileArg);
|
|
60254
|
+
const normalizedCwd = cwd.endsWith(path45.sep) ? cwd : cwd + path45.sep;
|
|
60060
60255
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
60061
60256
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
60062
60257
|
}
|
|
60063
|
-
const ext =
|
|
60258
|
+
const ext = path45.extname(resolvedPath).toLowerCase();
|
|
60064
60259
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
60065
60260
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
60066
60261
|
}
|
|
@@ -60074,7 +60269,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
60074
60269
|
return resolvedPath;
|
|
60075
60270
|
}
|
|
60076
60271
|
for (const candidate of SPEC_CANDIDATES) {
|
|
60077
|
-
const candidatePath =
|
|
60272
|
+
const candidatePath = path45.resolve(cwd, candidate);
|
|
60078
60273
|
if (fs32.existsSync(candidatePath)) {
|
|
60079
60274
|
const stats = fs32.statSync(candidatePath);
|
|
60080
60275
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -60086,7 +60281,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
60086
60281
|
}
|
|
60087
60282
|
function parseSpec(specFile) {
|
|
60088
60283
|
const content = fs32.readFileSync(specFile, "utf-8");
|
|
60089
|
-
const ext =
|
|
60284
|
+
const ext = path45.extname(specFile).toLowerCase();
|
|
60090
60285
|
if (ext === ".json") {
|
|
60091
60286
|
return parseJsonSpec(content);
|
|
60092
60287
|
}
|
|
@@ -60162,7 +60357,7 @@ function extractRoutes(cwd) {
|
|
|
60162
60357
|
return;
|
|
60163
60358
|
}
|
|
60164
60359
|
for (const entry of entries) {
|
|
60165
|
-
const fullPath =
|
|
60360
|
+
const fullPath = path45.join(dir, entry.name);
|
|
60166
60361
|
if (entry.isSymbolicLink()) {
|
|
60167
60362
|
continue;
|
|
60168
60363
|
}
|
|
@@ -60172,7 +60367,7 @@ function extractRoutes(cwd) {
|
|
|
60172
60367
|
}
|
|
60173
60368
|
walkDir(fullPath);
|
|
60174
60369
|
} else if (entry.isFile()) {
|
|
60175
|
-
const ext =
|
|
60370
|
+
const ext = path45.extname(entry.name).toLowerCase();
|
|
60176
60371
|
const baseName = entry.name.toLowerCase();
|
|
60177
60372
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
60178
60373
|
continue;
|
|
@@ -60342,7 +60537,7 @@ init_secretscan();
|
|
|
60342
60537
|
init_tool();
|
|
60343
60538
|
init_create_tool();
|
|
60344
60539
|
import * as fs33 from "fs";
|
|
60345
|
-
import * as
|
|
60540
|
+
import * as path46 from "path";
|
|
60346
60541
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
60347
60542
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
60348
60543
|
function containsControlCharacters(str) {
|
|
@@ -60371,11 +60566,11 @@ function containsWindowsAttacks(str) {
|
|
|
60371
60566
|
}
|
|
60372
60567
|
function isPathInWorkspace(filePath, workspace) {
|
|
60373
60568
|
try {
|
|
60374
|
-
const resolvedPath =
|
|
60569
|
+
const resolvedPath = path46.resolve(workspace, filePath);
|
|
60375
60570
|
const realWorkspace = fs33.realpathSync(workspace);
|
|
60376
60571
|
const realResolvedPath = fs33.realpathSync(resolvedPath);
|
|
60377
|
-
const relativePath =
|
|
60378
|
-
if (relativePath.startsWith("..") ||
|
|
60572
|
+
const relativePath = path46.relative(realWorkspace, realResolvedPath);
|
|
60573
|
+
if (relativePath.startsWith("..") || path46.isAbsolute(relativePath)) {
|
|
60379
60574
|
return false;
|
|
60380
60575
|
}
|
|
60381
60576
|
return true;
|
|
@@ -60387,7 +60582,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
60387
60582
|
return isPathInWorkspace(filePath, workspace);
|
|
60388
60583
|
}
|
|
60389
60584
|
function extractTSSymbols(filePath, cwd) {
|
|
60390
|
-
const fullPath =
|
|
60585
|
+
const fullPath = path46.join(cwd, filePath);
|
|
60391
60586
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
60392
60587
|
return [];
|
|
60393
60588
|
}
|
|
@@ -60539,7 +60734,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
60539
60734
|
});
|
|
60540
60735
|
}
|
|
60541
60736
|
function extractPythonSymbols(filePath, cwd) {
|
|
60542
|
-
const fullPath =
|
|
60737
|
+
const fullPath = path46.join(cwd, filePath);
|
|
60543
60738
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
60544
60739
|
return [];
|
|
60545
60740
|
}
|
|
@@ -60622,7 +60817,7 @@ var symbols = createSwarmTool({
|
|
|
60622
60817
|
}, null, 2);
|
|
60623
60818
|
}
|
|
60624
60819
|
const cwd = directory;
|
|
60625
|
-
const ext =
|
|
60820
|
+
const ext = path46.extname(file3);
|
|
60626
60821
|
if (containsControlCharacters(file3)) {
|
|
60627
60822
|
return JSON.stringify({
|
|
60628
60823
|
file: file3,
|
|
@@ -60694,7 +60889,7 @@ init_dist();
|
|
|
60694
60889
|
init_utils();
|
|
60695
60890
|
init_create_tool();
|
|
60696
60891
|
import * as fs34 from "fs";
|
|
60697
|
-
import * as
|
|
60892
|
+
import * as path47 from "path";
|
|
60698
60893
|
var MAX_TEXT_LENGTH = 200;
|
|
60699
60894
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
60700
60895
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -60765,9 +60960,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
60765
60960
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
60766
60961
|
}
|
|
60767
60962
|
try {
|
|
60768
|
-
const resolvedPath =
|
|
60769
|
-
const normalizedCwd =
|
|
60770
|
-
const normalizedResolved =
|
|
60963
|
+
const resolvedPath = path47.resolve(paths);
|
|
60964
|
+
const normalizedCwd = path47.resolve(cwd);
|
|
60965
|
+
const normalizedResolved = path47.resolve(resolvedPath);
|
|
60771
60966
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
60772
60967
|
return {
|
|
60773
60968
|
error: "paths must be within the current working directory",
|
|
@@ -60783,7 +60978,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
60783
60978
|
}
|
|
60784
60979
|
}
|
|
60785
60980
|
function isSupportedExtension(filePath) {
|
|
60786
|
-
const ext =
|
|
60981
|
+
const ext = path47.extname(filePath).toLowerCase();
|
|
60787
60982
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
60788
60983
|
}
|
|
60789
60984
|
function findSourceFiles3(dir, files = []) {
|
|
@@ -60798,7 +60993,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
60798
60993
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
60799
60994
|
continue;
|
|
60800
60995
|
}
|
|
60801
|
-
const fullPath =
|
|
60996
|
+
const fullPath = path47.join(dir, entry);
|
|
60802
60997
|
let stat2;
|
|
60803
60998
|
try {
|
|
60804
60999
|
stat2 = fs34.statSync(fullPath);
|
|
@@ -60910,7 +61105,7 @@ var todo_extract = createSwarmTool({
|
|
|
60910
61105
|
filesToScan.push(scanPath);
|
|
60911
61106
|
} else {
|
|
60912
61107
|
const errorResult = {
|
|
60913
|
-
error: `unsupported file extension: ${
|
|
61108
|
+
error: `unsupported file extension: ${path47.extname(scanPath)}`,
|
|
60914
61109
|
total: 0,
|
|
60915
61110
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
60916
61111
|
entries: []
|
|
@@ -60954,9 +61149,10 @@ var todo_extract = createSwarmTool({
|
|
|
60954
61149
|
});
|
|
60955
61150
|
// src/tools/update-task-status.ts
|
|
60956
61151
|
init_tool();
|
|
61152
|
+
init_schema();
|
|
60957
61153
|
init_manager2();
|
|
60958
61154
|
import * as fs35 from "fs";
|
|
60959
|
-
import * as
|
|
61155
|
+
import * as path48 from "path";
|
|
60960
61156
|
init_create_tool();
|
|
60961
61157
|
var VALID_STATUSES2 = [
|
|
60962
61158
|
"pending",
|
|
@@ -60979,6 +61175,23 @@ function validateTaskId(taskId) {
|
|
|
60979
61175
|
}
|
|
60980
61176
|
function checkReviewerGate(taskId, workingDirectory) {
|
|
60981
61177
|
try {
|
|
61178
|
+
const resolvedDir = workingDirectory ?? process.cwd();
|
|
61179
|
+
try {
|
|
61180
|
+
const evidencePath = path48.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
|
|
61181
|
+
const raw = fs35.readFileSync(evidencePath, "utf-8");
|
|
61182
|
+
const evidence = JSON.parse(raw);
|
|
61183
|
+
if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
|
|
61184
|
+
const allGatesMet = evidence.required_gates.every((gate) => evidence.gates[gate] != null);
|
|
61185
|
+
if (allGatesMet) {
|
|
61186
|
+
return { blocked: false, reason: "" };
|
|
61187
|
+
}
|
|
61188
|
+
const missingGates = evidence.required_gates.filter((gate) => evidence.gates[gate] == null);
|
|
61189
|
+
return {
|
|
61190
|
+
blocked: true,
|
|
61191
|
+
reason: `Task ${taskId} is missing required gates: [${missingGates.join(", ")}]. ` + `Required: [${evidence.required_gates.join(", ")}]. ` + `Completed: [${Object.keys(evidence.gates).join(", ")}]. ` + `Delegate the missing gate agents before marking task as completed.`
|
|
61192
|
+
};
|
|
61193
|
+
}
|
|
61194
|
+
} catch {}
|
|
60982
61195
|
if (swarmState.agentSessions.size === 0) {
|
|
60983
61196
|
return { blocked: false, reason: "" };
|
|
60984
61197
|
}
|
|
@@ -61003,13 +61216,9 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
61003
61216
|
const state = getTaskState(session, taskId);
|
|
61004
61217
|
stateEntries.push(`${sessionId}: ${state}`);
|
|
61005
61218
|
}
|
|
61006
|
-
const allIdle = stateEntries.length > 0 && stateEntries.every((e) => e.endsWith(": idle"));
|
|
61007
|
-
if (allIdle) {
|
|
61008
|
-
return { blocked: false, reason: "" };
|
|
61009
|
-
}
|
|
61010
61219
|
try {
|
|
61011
|
-
const
|
|
61012
|
-
const planPath =
|
|
61220
|
+
const resolvedDir2 = workingDirectory ?? process.cwd();
|
|
61221
|
+
const planPath = path48.join(resolvedDir2, ".swarm", "plan.json");
|
|
61013
61222
|
const planRaw = fs35.readFileSync(planPath, "utf-8");
|
|
61014
61223
|
const plan = JSON.parse(planRaw);
|
|
61015
61224
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -61029,6 +61238,52 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
61029
61238
|
return { blocked: false, reason: "" };
|
|
61030
61239
|
}
|
|
61031
61240
|
}
|
|
61241
|
+
function recoverTaskStateFromDelegations(taskId) {
|
|
61242
|
+
let hasReviewer = false;
|
|
61243
|
+
let hasTestEngineer = false;
|
|
61244
|
+
for (const [sessionId, chain] of swarmState.delegationChains) {
|
|
61245
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
61246
|
+
if (session && (session.currentTaskId === taskId || session.lastCoderDelegationTaskId === taskId)) {
|
|
61247
|
+
for (const delegation of chain) {
|
|
61248
|
+
const target = stripKnownSwarmPrefix(delegation.to);
|
|
61249
|
+
if (target === "reviewer")
|
|
61250
|
+
hasReviewer = true;
|
|
61251
|
+
if (target === "test_engineer")
|
|
61252
|
+
hasTestEngineer = true;
|
|
61253
|
+
}
|
|
61254
|
+
}
|
|
61255
|
+
}
|
|
61256
|
+
if (!hasReviewer && !hasTestEngineer)
|
|
61257
|
+
return;
|
|
61258
|
+
for (const [, session] of swarmState.agentSessions) {
|
|
61259
|
+
if (!(session.taskWorkflowStates instanceof Map))
|
|
61260
|
+
continue;
|
|
61261
|
+
const currentState = getTaskState(session, taskId);
|
|
61262
|
+
if (currentState === "tests_run" || currentState === "complete")
|
|
61263
|
+
continue;
|
|
61264
|
+
if (hasReviewer && currentState === "idle") {
|
|
61265
|
+
try {
|
|
61266
|
+
advanceTaskState(session, taskId, "coder_delegated");
|
|
61267
|
+
} catch {}
|
|
61268
|
+
}
|
|
61269
|
+
if (hasReviewer) {
|
|
61270
|
+
const stateNow = getTaskState(session, taskId);
|
|
61271
|
+
if (stateNow === "coder_delegated" || stateNow === "pre_check_passed") {
|
|
61272
|
+
try {
|
|
61273
|
+
advanceTaskState(session, taskId, "reviewer_run");
|
|
61274
|
+
} catch {}
|
|
61275
|
+
}
|
|
61276
|
+
}
|
|
61277
|
+
if (hasTestEngineer) {
|
|
61278
|
+
const stateNow = getTaskState(session, taskId);
|
|
61279
|
+
if (stateNow === "reviewer_run") {
|
|
61280
|
+
try {
|
|
61281
|
+
advanceTaskState(session, taskId, "tests_run");
|
|
61282
|
+
} catch {}
|
|
61283
|
+
}
|
|
61284
|
+
}
|
|
61285
|
+
}
|
|
61286
|
+
}
|
|
61032
61287
|
async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
61033
61288
|
const statusError = validateStatus(args2.status);
|
|
61034
61289
|
if (statusError) {
|
|
@@ -61074,8 +61329,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
61074
61329
|
};
|
|
61075
61330
|
}
|
|
61076
61331
|
}
|
|
61077
|
-
normalizedDir =
|
|
61078
|
-
const pathParts = normalizedDir.split(
|
|
61332
|
+
normalizedDir = path48.normalize(args2.working_directory);
|
|
61333
|
+
const pathParts = normalizedDir.split(path48.sep);
|
|
61079
61334
|
if (pathParts.includes("..")) {
|
|
61080
61335
|
return {
|
|
61081
61336
|
success: false,
|
|
@@ -61085,10 +61340,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
61085
61340
|
]
|
|
61086
61341
|
};
|
|
61087
61342
|
}
|
|
61088
|
-
const resolvedDir =
|
|
61343
|
+
const resolvedDir = path48.resolve(normalizedDir);
|
|
61089
61344
|
try {
|
|
61090
61345
|
const realPath = fs35.realpathSync(resolvedDir);
|
|
61091
|
-
const planPath =
|
|
61346
|
+
const planPath = path48.join(realPath, ".swarm", "plan.json");
|
|
61092
61347
|
if (!fs35.existsSync(planPath)) {
|
|
61093
61348
|
return {
|
|
61094
61349
|
success: false,
|
|
@@ -61112,6 +61367,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
61112
61367
|
directory = fallbackDir ?? process.cwd();
|
|
61113
61368
|
}
|
|
61114
61369
|
if (args2.status === "completed") {
|
|
61370
|
+
recoverTaskStateFromDelegations(args2.task_id);
|
|
61115
61371
|
const reviewerCheck = checkReviewerGate(args2.task_id, directory);
|
|
61116
61372
|
if (reviewerCheck.blocked) {
|
|
61117
61373
|
return {
|
|
@@ -61245,7 +61501,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
61245
61501
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
61246
61502
|
preflightTriggerManager = new PTM(automationConfig);
|
|
61247
61503
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
61248
|
-
const swarmDir =
|
|
61504
|
+
const swarmDir = path49.resolve(ctx.directory, ".swarm");
|
|
61249
61505
|
statusArtifact = new ASA(swarmDir);
|
|
61250
61506
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
61251
61507
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|