opencode-swarm 6.45.1 → 6.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -0
- package/dist/cli/index.js +353 -240
- package/dist/commands/close.d.ts +1 -1
- package/dist/config/evidence-schema.d.ts +2 -2
- package/dist/config/schema.d.ts +50 -0
- package/dist/hooks/guardrails.d.ts +12 -3
- package/dist/hooks/index.d.ts +1 -1
- package/dist/index.js +765 -587
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14573,7 +14573,7 @@ function resolveGuardrailsConfig(config2, agentName) {
|
|
|
14573
14573
|
};
|
|
14574
14574
|
return resolved;
|
|
14575
14575
|
}
|
|
14576
|
-
var KNOWN_SWARM_PREFIXES, SEPARATORS, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, CuratorConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PluginConfigSchema;
|
|
14576
|
+
var KNOWN_SWARM_PREFIXES, SEPARATORS, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, CuratorConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, PluginConfigSchema;
|
|
14577
14577
|
var init_schema = __esm(() => {
|
|
14578
14578
|
init_zod();
|
|
14579
14579
|
init_constants();
|
|
@@ -15047,6 +15047,17 @@ var init_schema = __esm(() => {
|
|
|
15047
15047
|
emergencyThreshold: exports_external.number().min(1).max(99).default(80),
|
|
15048
15048
|
preserveLastNTurns: exports_external.number().int().min(1).default(5)
|
|
15049
15049
|
});
|
|
15050
|
+
AgentAuthorityRuleSchema = exports_external.object({
|
|
15051
|
+
readOnly: exports_external.boolean().optional(),
|
|
15052
|
+
blockedExact: exports_external.array(exports_external.string()).optional(),
|
|
15053
|
+
blockedPrefix: exports_external.array(exports_external.string()).optional(),
|
|
15054
|
+
allowedPrefix: exports_external.array(exports_external.string()).optional(),
|
|
15055
|
+
blockedZones: exports_external.array(exports_external.enum(["production", "test", "config", "generated", "docs", "build"])).optional()
|
|
15056
|
+
});
|
|
15057
|
+
AuthorityConfigSchema = exports_external.object({
|
|
15058
|
+
enabled: exports_external.boolean().default(true),
|
|
15059
|
+
rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({})
|
|
15060
|
+
});
|
|
15050
15061
|
PluginConfigSchema = exports_external.object({
|
|
15051
15062
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
|
15052
15063
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
@@ -15063,6 +15074,7 @@ var init_schema = __esm(() => {
|
|
|
15063
15074
|
watchdog: WatchdogConfigSchema.optional(),
|
|
15064
15075
|
self_review: SelfReviewConfigSchema.optional(),
|
|
15065
15076
|
tool_filter: ToolFilterConfigSchema.optional(),
|
|
15077
|
+
authority: AuthorityConfigSchema.optional(),
|
|
15066
15078
|
plan_cursor: PlanCursorConfigSchema.optional(),
|
|
15067
15079
|
evidence: EvidenceConfigSchema.optional(),
|
|
15068
15080
|
summaries: SummaryConfigSchema.optional(),
|
|
@@ -32521,7 +32533,7 @@ __export(exports_co_change_analyzer, {
|
|
|
32521
32533
|
import * as child_process2 from "child_process";
|
|
32522
32534
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
32523
32535
|
import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
|
|
32524
|
-
import * as
|
|
32536
|
+
import * as path20 from "path";
|
|
32525
32537
|
import { promisify } from "util";
|
|
32526
32538
|
function getExecFileAsync() {
|
|
32527
32539
|
return promisify(child_process2.execFile);
|
|
@@ -32623,7 +32635,7 @@ async function scanSourceFiles(dir) {
|
|
|
32623
32635
|
try {
|
|
32624
32636
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
32625
32637
|
for (const entry of entries) {
|
|
32626
|
-
const fullPath =
|
|
32638
|
+
const fullPath = path20.join(dir, entry.name);
|
|
32627
32639
|
if (entry.isDirectory()) {
|
|
32628
32640
|
if (skipDirs.has(entry.name)) {
|
|
32629
32641
|
continue;
|
|
@@ -32631,7 +32643,7 @@ async function scanSourceFiles(dir) {
|
|
|
32631
32643
|
const subFiles = await scanSourceFiles(fullPath);
|
|
32632
32644
|
results.push(...subFiles);
|
|
32633
32645
|
} else if (entry.isFile()) {
|
|
32634
|
-
const ext =
|
|
32646
|
+
const ext = path20.extname(entry.name);
|
|
32635
32647
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
32636
32648
|
results.push(fullPath);
|
|
32637
32649
|
}
|
|
@@ -32653,8 +32665,8 @@ async function getStaticEdges(directory) {
|
|
|
32653
32665
|
continue;
|
|
32654
32666
|
}
|
|
32655
32667
|
try {
|
|
32656
|
-
const sourceDir =
|
|
32657
|
-
const resolvedPath =
|
|
32668
|
+
const sourceDir = path20.dirname(sourceFile);
|
|
32669
|
+
const resolvedPath = path20.resolve(sourceDir, importPath);
|
|
32658
32670
|
const extensions = [
|
|
32659
32671
|
"",
|
|
32660
32672
|
".ts",
|
|
@@ -32679,8 +32691,8 @@ async function getStaticEdges(directory) {
|
|
|
32679
32691
|
if (!targetFile) {
|
|
32680
32692
|
continue;
|
|
32681
32693
|
}
|
|
32682
|
-
const relSource =
|
|
32683
|
-
const relTarget =
|
|
32694
|
+
const relSource = path20.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
32695
|
+
const relTarget = path20.relative(directory, targetFile).replace(/\\/g, "/");
|
|
32684
32696
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
32685
32697
|
edges.add(key);
|
|
32686
32698
|
} catch {}
|
|
@@ -32692,7 +32704,7 @@ async function getStaticEdges(directory) {
|
|
|
32692
32704
|
function isTestImplementationPair(fileA, fileB) {
|
|
32693
32705
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
32694
32706
|
const getBaseName = (filePath) => {
|
|
32695
|
-
const base =
|
|
32707
|
+
const base = path20.basename(filePath);
|
|
32696
32708
|
for (const pattern of testPatterns) {
|
|
32697
32709
|
if (base.endsWith(pattern)) {
|
|
32698
32710
|
return base.slice(0, -pattern.length);
|
|
@@ -32702,16 +32714,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
32702
32714
|
};
|
|
32703
32715
|
const baseA = getBaseName(fileA);
|
|
32704
32716
|
const baseB = getBaseName(fileB);
|
|
32705
|
-
return baseA === baseB && baseA !==
|
|
32717
|
+
return baseA === baseB && baseA !== path20.basename(fileA) && baseA !== path20.basename(fileB);
|
|
32706
32718
|
}
|
|
32707
32719
|
function hasSharedPrefix(fileA, fileB) {
|
|
32708
|
-
const dirA =
|
|
32709
|
-
const dirB =
|
|
32720
|
+
const dirA = path20.dirname(fileA);
|
|
32721
|
+
const dirB = path20.dirname(fileB);
|
|
32710
32722
|
if (dirA !== dirB) {
|
|
32711
32723
|
return false;
|
|
32712
32724
|
}
|
|
32713
|
-
const baseA =
|
|
32714
|
-
const baseB =
|
|
32725
|
+
const baseA = path20.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
32726
|
+
const baseB = path20.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
32715
32727
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
32716
32728
|
return true;
|
|
32717
32729
|
}
|
|
@@ -32765,8 +32777,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
32765
32777
|
const entries = [];
|
|
32766
32778
|
const now = new Date().toISOString();
|
|
32767
32779
|
for (const pair of pairs.slice(0, 10)) {
|
|
32768
|
-
const baseA =
|
|
32769
|
-
const baseB =
|
|
32780
|
+
const baseA = path20.basename(pair.fileA);
|
|
32781
|
+
const baseB = path20.basename(pair.fileB);
|
|
32770
32782
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
32771
32783
|
if (lesson.length > 280) {
|
|
32772
32784
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
@@ -32875,13 +32887,13 @@ __export(exports_config_doctor, {
|
|
|
32875
32887
|
import * as crypto3 from "crypto";
|
|
32876
32888
|
import * as fs13 from "fs";
|
|
32877
32889
|
import * as os5 from "os";
|
|
32878
|
-
import * as
|
|
32890
|
+
import * as path23 from "path";
|
|
32879
32891
|
function getUserConfigDir3() {
|
|
32880
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
32892
|
+
return process.env.XDG_CONFIG_HOME || path23.join(os5.homedir(), ".config");
|
|
32881
32893
|
}
|
|
32882
32894
|
function getConfigPaths(directory) {
|
|
32883
|
-
const userConfigPath =
|
|
32884
|
-
const projectConfigPath =
|
|
32895
|
+
const userConfigPath = path23.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
32896
|
+
const projectConfigPath = path23.join(directory, ".opencode", "opencode-swarm.json");
|
|
32885
32897
|
return { userConfigPath, projectConfigPath };
|
|
32886
32898
|
}
|
|
32887
32899
|
function computeHash(content) {
|
|
@@ -32906,9 +32918,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
32906
32918
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
32907
32919
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
32908
32920
|
try {
|
|
32909
|
-
const resolvedConfig =
|
|
32910
|
-
const resolvedUser =
|
|
32911
|
-
const resolvedProject =
|
|
32921
|
+
const resolvedConfig = path23.resolve(configPath);
|
|
32922
|
+
const resolvedUser = path23.resolve(normalizedUser);
|
|
32923
|
+
const resolvedProject = path23.resolve(normalizedProject);
|
|
32912
32924
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
32913
32925
|
} catch {
|
|
32914
32926
|
return false;
|
|
@@ -32948,12 +32960,12 @@ function createConfigBackup(directory) {
|
|
|
32948
32960
|
};
|
|
32949
32961
|
}
|
|
32950
32962
|
function writeBackupArtifact(directory, backup) {
|
|
32951
|
-
const swarmDir =
|
|
32963
|
+
const swarmDir = path23.join(directory, ".swarm");
|
|
32952
32964
|
if (!fs13.existsSync(swarmDir)) {
|
|
32953
32965
|
fs13.mkdirSync(swarmDir, { recursive: true });
|
|
32954
32966
|
}
|
|
32955
32967
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
32956
|
-
const backupPath =
|
|
32968
|
+
const backupPath = path23.join(swarmDir, backupFilename);
|
|
32957
32969
|
const artifact = {
|
|
32958
32970
|
createdAt: backup.createdAt,
|
|
32959
32971
|
configPath: backup.configPath,
|
|
@@ -32983,7 +32995,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
32983
32995
|
return null;
|
|
32984
32996
|
}
|
|
32985
32997
|
const targetPath = artifact.configPath;
|
|
32986
|
-
const targetDir =
|
|
32998
|
+
const targetDir = path23.dirname(targetPath);
|
|
32987
32999
|
if (!fs13.existsSync(targetDir)) {
|
|
32988
33000
|
fs13.mkdirSync(targetDir, { recursive: true });
|
|
32989
33001
|
}
|
|
@@ -33014,9 +33026,9 @@ function readConfigFromFile(directory) {
|
|
|
33014
33026
|
return null;
|
|
33015
33027
|
}
|
|
33016
33028
|
}
|
|
33017
|
-
function validateConfigKey(
|
|
33029
|
+
function validateConfigKey(path24, value, _config) {
|
|
33018
33030
|
const findings = [];
|
|
33019
|
-
switch (
|
|
33031
|
+
switch (path24) {
|
|
33020
33032
|
case "agents": {
|
|
33021
33033
|
if (value !== undefined) {
|
|
33022
33034
|
findings.push({
|
|
@@ -33263,27 +33275,27 @@ function validateConfigKey(path23, value, _config) {
|
|
|
33263
33275
|
}
|
|
33264
33276
|
return findings;
|
|
33265
33277
|
}
|
|
33266
|
-
function walkConfigAndValidate(obj,
|
|
33278
|
+
function walkConfigAndValidate(obj, path24, config3, findings) {
|
|
33267
33279
|
if (obj === null || obj === undefined) {
|
|
33268
33280
|
return;
|
|
33269
33281
|
}
|
|
33270
|
-
if (
|
|
33271
|
-
const keyFindings = validateConfigKey(
|
|
33282
|
+
if (path24 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
33283
|
+
const keyFindings = validateConfigKey(path24, obj, config3);
|
|
33272
33284
|
findings.push(...keyFindings);
|
|
33273
33285
|
}
|
|
33274
33286
|
if (typeof obj !== "object") {
|
|
33275
|
-
const keyFindings = validateConfigKey(
|
|
33287
|
+
const keyFindings = validateConfigKey(path24, obj, config3);
|
|
33276
33288
|
findings.push(...keyFindings);
|
|
33277
33289
|
return;
|
|
33278
33290
|
}
|
|
33279
33291
|
if (Array.isArray(obj)) {
|
|
33280
33292
|
obj.forEach((item, index) => {
|
|
33281
|
-
walkConfigAndValidate(item, `${
|
|
33293
|
+
walkConfigAndValidate(item, `${path24}[${index}]`, config3, findings);
|
|
33282
33294
|
});
|
|
33283
33295
|
return;
|
|
33284
33296
|
}
|
|
33285
33297
|
for (const [key, value] of Object.entries(obj)) {
|
|
33286
|
-
const newPath =
|
|
33298
|
+
const newPath = path24 ? `${path24}.${key}` : key;
|
|
33287
33299
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
33288
33300
|
}
|
|
33289
33301
|
}
|
|
@@ -33403,7 +33415,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
33403
33415
|
}
|
|
33404
33416
|
}
|
|
33405
33417
|
if (appliedFixes.length > 0) {
|
|
33406
|
-
const configDir =
|
|
33418
|
+
const configDir = path23.dirname(configPath);
|
|
33407
33419
|
if (!fs13.existsSync(configDir)) {
|
|
33408
33420
|
fs13.mkdirSync(configDir, { recursive: true });
|
|
33409
33421
|
}
|
|
@@ -33413,12 +33425,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
33413
33425
|
return { appliedFixes, updatedConfigPath };
|
|
33414
33426
|
}
|
|
33415
33427
|
function writeDoctorArtifact(directory, result) {
|
|
33416
|
-
const swarmDir =
|
|
33428
|
+
const swarmDir = path23.join(directory, ".swarm");
|
|
33417
33429
|
if (!fs13.existsSync(swarmDir)) {
|
|
33418
33430
|
fs13.mkdirSync(swarmDir, { recursive: true });
|
|
33419
33431
|
}
|
|
33420
33432
|
const artifactFilename = "config-doctor.json";
|
|
33421
|
-
const artifactPath =
|
|
33433
|
+
const artifactPath = path23.join(swarmDir, artifactFilename);
|
|
33422
33434
|
const guiOutput = {
|
|
33423
33435
|
timestamp: result.timestamp,
|
|
33424
33436
|
summary: result.summary,
|
|
@@ -34472,7 +34484,7 @@ var init_detector = __esm(() => {
|
|
|
34472
34484
|
|
|
34473
34485
|
// src/build/discovery.ts
|
|
34474
34486
|
import * as fs14 from "fs";
|
|
34475
|
-
import * as
|
|
34487
|
+
import * as path25 from "path";
|
|
34476
34488
|
function isCommandAvailable(command) {
|
|
34477
34489
|
if (toolchainCache.has(command)) {
|
|
34478
34490
|
return toolchainCache.get(command);
|
|
@@ -34505,11 +34517,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
34505
34517
|
const regex = simpleGlobToRegex(pattern);
|
|
34506
34518
|
const matches = files.filter((f) => regex.test(f));
|
|
34507
34519
|
if (matches.length > 0) {
|
|
34508
|
-
return
|
|
34520
|
+
return path25.join(dir, matches[0]);
|
|
34509
34521
|
}
|
|
34510
34522
|
} catch {}
|
|
34511
34523
|
} else {
|
|
34512
|
-
const filePath =
|
|
34524
|
+
const filePath = path25.join(workingDir, pattern);
|
|
34513
34525
|
if (fs14.existsSync(filePath)) {
|
|
34514
34526
|
return filePath;
|
|
34515
34527
|
}
|
|
@@ -34518,7 +34530,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
34518
34530
|
return null;
|
|
34519
34531
|
}
|
|
34520
34532
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
34521
|
-
const packageJsonPath =
|
|
34533
|
+
const packageJsonPath = path25.join(workingDir, "package.json");
|
|
34522
34534
|
if (!fs14.existsSync(packageJsonPath)) {
|
|
34523
34535
|
return [];
|
|
34524
34536
|
}
|
|
@@ -34559,7 +34571,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
34559
34571
|
const regex = simpleGlobToRegex(pattern);
|
|
34560
34572
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
34561
34573
|
} else {
|
|
34562
|
-
const filePath =
|
|
34574
|
+
const filePath = path25.join(workingDir, pattern);
|
|
34563
34575
|
if (fs14.existsSync(filePath)) {
|
|
34564
34576
|
allBuildFiles.add(filePath);
|
|
34565
34577
|
}
|
|
@@ -34572,7 +34584,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
34572
34584
|
try {
|
|
34573
34585
|
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
34574
34586
|
for (const entry of entries) {
|
|
34575
|
-
const fullPath =
|
|
34587
|
+
const fullPath = path25.join(dir, entry.name);
|
|
34576
34588
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
34577
34589
|
findFilesRecursive(fullPath, regex, results);
|
|
34578
34590
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -34595,7 +34607,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
34595
34607
|
let foundCommand = false;
|
|
34596
34608
|
for (const cmd of sortedCommands) {
|
|
34597
34609
|
if (cmd.detectFile) {
|
|
34598
|
-
const detectFilePath =
|
|
34610
|
+
const detectFilePath = path25.join(workingDir, cmd.detectFile);
|
|
34599
34611
|
if (!fs14.existsSync(detectFilePath)) {
|
|
34600
34612
|
continue;
|
|
34601
34613
|
}
|
|
@@ -34852,7 +34864,7 @@ function validateDirectory(directory) {
|
|
|
34852
34864
|
|
|
34853
34865
|
// src/tools/lint.ts
|
|
34854
34866
|
import * as fs15 from "fs";
|
|
34855
|
-
import * as
|
|
34867
|
+
import * as path26 from "path";
|
|
34856
34868
|
function validateArgs(args2) {
|
|
34857
34869
|
if (typeof args2 !== "object" || args2 === null)
|
|
34858
34870
|
return false;
|
|
@@ -34863,9 +34875,9 @@ function validateArgs(args2) {
|
|
|
34863
34875
|
}
|
|
34864
34876
|
function getLinterCommand(linter, mode, projectDir) {
|
|
34865
34877
|
const isWindows = process.platform === "win32";
|
|
34866
|
-
const binDir =
|
|
34867
|
-
const biomeBin = isWindows ?
|
|
34868
|
-
const eslintBin = isWindows ?
|
|
34878
|
+
const binDir = path26.join(projectDir, "node_modules", ".bin");
|
|
34879
|
+
const biomeBin = isWindows ? path26.join(binDir, "biome.EXE") : path26.join(binDir, "biome");
|
|
34880
|
+
const eslintBin = isWindows ? path26.join(binDir, "eslint.cmd") : path26.join(binDir, "eslint");
|
|
34869
34881
|
switch (linter) {
|
|
34870
34882
|
case "biome":
|
|
34871
34883
|
if (mode === "fix") {
|
|
@@ -34881,7 +34893,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
34881
34893
|
}
|
|
34882
34894
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
34883
34895
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
34884
|
-
const gradlew = fs15.existsSync(
|
|
34896
|
+
const gradlew = fs15.existsSync(path26.join(cwd, gradlewName)) ? path26.join(cwd, gradlewName) : null;
|
|
34885
34897
|
switch (linter) {
|
|
34886
34898
|
case "ruff":
|
|
34887
34899
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -34915,10 +34927,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
34915
34927
|
}
|
|
34916
34928
|
}
|
|
34917
34929
|
function detectRuff(cwd) {
|
|
34918
|
-
if (fs15.existsSync(
|
|
34930
|
+
if (fs15.existsSync(path26.join(cwd, "ruff.toml")))
|
|
34919
34931
|
return isCommandAvailable("ruff");
|
|
34920
34932
|
try {
|
|
34921
|
-
const pyproject =
|
|
34933
|
+
const pyproject = path26.join(cwd, "pyproject.toml");
|
|
34922
34934
|
if (fs15.existsSync(pyproject)) {
|
|
34923
34935
|
const content = fs15.readFileSync(pyproject, "utf-8");
|
|
34924
34936
|
if (content.includes("[tool.ruff]"))
|
|
@@ -34928,19 +34940,19 @@ function detectRuff(cwd) {
|
|
|
34928
34940
|
return false;
|
|
34929
34941
|
}
|
|
34930
34942
|
function detectClippy(cwd) {
|
|
34931
|
-
return fs15.existsSync(
|
|
34943
|
+
return fs15.existsSync(path26.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
34932
34944
|
}
|
|
34933
34945
|
function detectGolangciLint(cwd) {
|
|
34934
|
-
return fs15.existsSync(
|
|
34946
|
+
return fs15.existsSync(path26.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
34935
34947
|
}
|
|
34936
34948
|
function detectCheckstyle(cwd) {
|
|
34937
|
-
const hasMaven = fs15.existsSync(
|
|
34938
|
-
const hasGradle = fs15.existsSync(
|
|
34939
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs15.existsSync(
|
|
34949
|
+
const hasMaven = fs15.existsSync(path26.join(cwd, "pom.xml"));
|
|
34950
|
+
const hasGradle = fs15.existsSync(path26.join(cwd, "build.gradle")) || fs15.existsSync(path26.join(cwd, "build.gradle.kts"));
|
|
34951
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs15.existsSync(path26.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
34940
34952
|
return (hasMaven || hasGradle) && hasBinary;
|
|
34941
34953
|
}
|
|
34942
34954
|
function detectKtlint(cwd) {
|
|
34943
|
-
const hasKotlin = fs15.existsSync(
|
|
34955
|
+
const hasKotlin = fs15.existsSync(path26.join(cwd, "build.gradle.kts")) || fs15.existsSync(path26.join(cwd, "build.gradle")) || (() => {
|
|
34944
34956
|
try {
|
|
34945
34957
|
return fs15.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
34946
34958
|
} catch {
|
|
@@ -34959,11 +34971,11 @@ function detectDotnetFormat(cwd) {
|
|
|
34959
34971
|
}
|
|
34960
34972
|
}
|
|
34961
34973
|
function detectCppcheck(cwd) {
|
|
34962
|
-
if (fs15.existsSync(
|
|
34974
|
+
if (fs15.existsSync(path26.join(cwd, "CMakeLists.txt"))) {
|
|
34963
34975
|
return isCommandAvailable("cppcheck");
|
|
34964
34976
|
}
|
|
34965
34977
|
try {
|
|
34966
|
-
const dirsToCheck = [cwd,
|
|
34978
|
+
const dirsToCheck = [cwd, path26.join(cwd, "src")];
|
|
34967
34979
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
34968
34980
|
try {
|
|
34969
34981
|
return fs15.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -34977,13 +34989,13 @@ function detectCppcheck(cwd) {
|
|
|
34977
34989
|
}
|
|
34978
34990
|
}
|
|
34979
34991
|
function detectSwiftlint(cwd) {
|
|
34980
|
-
return fs15.existsSync(
|
|
34992
|
+
return fs15.existsSync(path26.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
34981
34993
|
}
|
|
34982
34994
|
function detectDartAnalyze(cwd) {
|
|
34983
|
-
return fs15.existsSync(
|
|
34995
|
+
return fs15.existsSync(path26.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
34984
34996
|
}
|
|
34985
34997
|
function detectRubocop(cwd) {
|
|
34986
|
-
return (fs15.existsSync(
|
|
34998
|
+
return (fs15.existsSync(path26.join(cwd, "Gemfile")) || fs15.existsSync(path26.join(cwd, "gems.rb")) || fs15.existsSync(path26.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
34987
34999
|
}
|
|
34988
35000
|
function detectAdditionalLinter(cwd) {
|
|
34989
35001
|
if (detectRuff(cwd))
|
|
@@ -35011,10 +35023,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
35011
35023
|
function resolveLinterBinPath(linter, projectDir) {
|
|
35012
35024
|
const isWindows = process.platform === "win32";
|
|
35013
35025
|
const binName = linter === "biome" ? isWindows ? "biome.EXE" : "biome" : isWindows ? "eslint.cmd" : "eslint";
|
|
35014
|
-
const localBin =
|
|
35026
|
+
const localBin = path26.join(projectDir, "node_modules", ".bin", binName);
|
|
35015
35027
|
if (fs15.existsSync(localBin))
|
|
35016
35028
|
return localBin;
|
|
35017
|
-
const ancestor = findBinInAncestors(
|
|
35029
|
+
const ancestor = findBinInAncestors(path26.dirname(projectDir), binName);
|
|
35018
35030
|
if (ancestor)
|
|
35019
35031
|
return ancestor;
|
|
35020
35032
|
const fromPath = findBinInEnvPath(binName);
|
|
@@ -35025,10 +35037,10 @@ function resolveLinterBinPath(linter, projectDir) {
|
|
|
35025
35037
|
function findBinInAncestors(startDir, binName) {
|
|
35026
35038
|
let dir = startDir;
|
|
35027
35039
|
while (true) {
|
|
35028
|
-
const candidate =
|
|
35040
|
+
const candidate = path26.join(dir, "node_modules", ".bin", binName);
|
|
35029
35041
|
if (fs15.existsSync(candidate))
|
|
35030
35042
|
return candidate;
|
|
35031
|
-
const parent =
|
|
35043
|
+
const parent = path26.dirname(dir);
|
|
35032
35044
|
if (parent === dir)
|
|
35033
35045
|
break;
|
|
35034
35046
|
dir = parent;
|
|
@@ -35037,10 +35049,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
35037
35049
|
}
|
|
35038
35050
|
function findBinInEnvPath(binName) {
|
|
35039
35051
|
const searchPath = process.env.PATH ?? "";
|
|
35040
|
-
for (const dir of searchPath.split(
|
|
35052
|
+
for (const dir of searchPath.split(path26.delimiter)) {
|
|
35041
35053
|
if (!dir)
|
|
35042
35054
|
continue;
|
|
35043
|
-
const candidate =
|
|
35055
|
+
const candidate = path26.join(dir, binName);
|
|
35044
35056
|
if (fs15.existsSync(candidate))
|
|
35045
35057
|
return candidate;
|
|
35046
35058
|
}
|
|
@@ -35053,13 +35065,13 @@ async function detectAvailableLinter(directory) {
|
|
|
35053
35065
|
return null;
|
|
35054
35066
|
const projectDir = directory;
|
|
35055
35067
|
const isWindows = process.platform === "win32";
|
|
35056
|
-
const biomeBin = isWindows ?
|
|
35057
|
-
const eslintBin = isWindows ?
|
|
35068
|
+
const biomeBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "biome.EXE") : path26.join(projectDir, "node_modules", ".bin", "biome");
|
|
35069
|
+
const eslintBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path26.join(projectDir, "node_modules", ".bin", "eslint");
|
|
35058
35070
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
35059
35071
|
if (localResult)
|
|
35060
35072
|
return localResult;
|
|
35061
|
-
const biomeAncestor = findBinInAncestors(
|
|
35062
|
-
const eslintAncestor = findBinInAncestors(
|
|
35073
|
+
const biomeAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
35074
|
+
const eslintAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
35063
35075
|
if (biomeAncestor || eslintAncestor) {
|
|
35064
35076
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
35065
35077
|
}
|
|
@@ -35274,7 +35286,7 @@ For Rust: rustup component add clippy`
|
|
|
35274
35286
|
|
|
35275
35287
|
// src/tools/secretscan.ts
|
|
35276
35288
|
import * as fs16 from "fs";
|
|
35277
|
-
import * as
|
|
35289
|
+
import * as path27 from "path";
|
|
35278
35290
|
function calculateShannonEntropy(str) {
|
|
35279
35291
|
if (str.length === 0)
|
|
35280
35292
|
return 0;
|
|
@@ -35322,7 +35334,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
35322
35334
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
35323
35335
|
}
|
|
35324
35336
|
function loadSecretScanIgnore(scanDir) {
|
|
35325
|
-
const ignorePath =
|
|
35337
|
+
const ignorePath = path27.join(scanDir, ".secretscanignore");
|
|
35326
35338
|
try {
|
|
35327
35339
|
if (!fs16.existsSync(ignorePath))
|
|
35328
35340
|
return [];
|
|
@@ -35345,7 +35357,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
35345
35357
|
if (exactNames.has(entry))
|
|
35346
35358
|
return true;
|
|
35347
35359
|
for (const pattern of globPatterns) {
|
|
35348
|
-
if (
|
|
35360
|
+
if (path27.matchesGlob(relPath, pattern))
|
|
35349
35361
|
return true;
|
|
35350
35362
|
}
|
|
35351
35363
|
return false;
|
|
@@ -35366,7 +35378,7 @@ function validateDirectoryInput(dir) {
|
|
|
35366
35378
|
return null;
|
|
35367
35379
|
}
|
|
35368
35380
|
function isBinaryFile(filePath, buffer) {
|
|
35369
|
-
const ext =
|
|
35381
|
+
const ext = path27.extname(filePath).toLowerCase();
|
|
35370
35382
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
35371
35383
|
return true;
|
|
35372
35384
|
}
|
|
@@ -35502,9 +35514,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
35502
35514
|
return false;
|
|
35503
35515
|
}
|
|
35504
35516
|
function isPathWithinScope(realPath, scanDir) {
|
|
35505
|
-
const resolvedScanDir =
|
|
35506
|
-
const resolvedRealPath =
|
|
35507
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
35517
|
+
const resolvedScanDir = path27.resolve(scanDir);
|
|
35518
|
+
const resolvedRealPath = path27.resolve(realPath);
|
|
35519
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path27.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
35508
35520
|
}
|
|
35509
35521
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
35510
35522
|
skippedDirs: 0,
|
|
@@ -35530,8 +35542,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
35530
35542
|
return a.localeCompare(b);
|
|
35531
35543
|
});
|
|
35532
35544
|
for (const entry of entries) {
|
|
35533
|
-
const fullPath =
|
|
35534
|
-
const relPath =
|
|
35545
|
+
const fullPath = path27.join(dir, entry);
|
|
35546
|
+
const relPath = path27.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
35535
35547
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
35536
35548
|
stats.skippedDirs++;
|
|
35537
35549
|
continue;
|
|
@@ -35566,7 +35578,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
35566
35578
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
35567
35579
|
files.push(...subFiles);
|
|
35568
35580
|
} else if (lstat.isFile()) {
|
|
35569
|
-
const ext =
|
|
35581
|
+
const ext = path27.extname(fullPath).toLowerCase();
|
|
35570
35582
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
35571
35583
|
files.push(fullPath);
|
|
35572
35584
|
} else {
|
|
@@ -35824,7 +35836,7 @@ var init_secretscan = __esm(() => {
|
|
|
35824
35836
|
}
|
|
35825
35837
|
}
|
|
35826
35838
|
try {
|
|
35827
|
-
const _scanDirRaw =
|
|
35839
|
+
const _scanDirRaw = path27.resolve(directory);
|
|
35828
35840
|
const scanDir = (() => {
|
|
35829
35841
|
try {
|
|
35830
35842
|
return fs16.realpathSync(_scanDirRaw);
|
|
@@ -35967,7 +35979,7 @@ var init_secretscan = __esm(() => {
|
|
|
35967
35979
|
|
|
35968
35980
|
// src/tools/resolve-working-directory.ts
|
|
35969
35981
|
import * as fs17 from "fs";
|
|
35970
|
-
import * as
|
|
35982
|
+
import * as path28 from "path";
|
|
35971
35983
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
35972
35984
|
if (workingDirectory == null || workingDirectory === "") {
|
|
35973
35985
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -35987,15 +35999,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
35987
35999
|
};
|
|
35988
36000
|
}
|
|
35989
36001
|
}
|
|
35990
|
-
const normalizedDir =
|
|
35991
|
-
const pathParts = normalizedDir.split(
|
|
36002
|
+
const normalizedDir = path28.normalize(workingDirectory);
|
|
36003
|
+
const pathParts = normalizedDir.split(path28.sep);
|
|
35992
36004
|
if (pathParts.includes("..")) {
|
|
35993
36005
|
return {
|
|
35994
36006
|
success: false,
|
|
35995
36007
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
35996
36008
|
};
|
|
35997
36009
|
}
|
|
35998
|
-
const resolvedDir =
|
|
36010
|
+
const resolvedDir = path28.resolve(normalizedDir);
|
|
35999
36011
|
try {
|
|
36000
36012
|
const realPath = fs17.realpathSync(resolvedDir);
|
|
36001
36013
|
return { success: true, directory: realPath };
|
|
@@ -36010,7 +36022,7 @@ var init_resolve_working_directory = () => {};
|
|
|
36010
36022
|
|
|
36011
36023
|
// src/tools/test-runner.ts
|
|
36012
36024
|
import * as fs18 from "fs";
|
|
36013
|
-
import * as
|
|
36025
|
+
import * as path29 from "path";
|
|
36014
36026
|
function isAbsolutePath(str) {
|
|
36015
36027
|
if (str.startsWith("/"))
|
|
36016
36028
|
return true;
|
|
@@ -36075,14 +36087,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
36075
36087
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
36076
36088
|
}
|
|
36077
36089
|
function detectGoTest(cwd) {
|
|
36078
|
-
return fs18.existsSync(
|
|
36090
|
+
return fs18.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
36079
36091
|
}
|
|
36080
36092
|
function detectJavaMaven(cwd) {
|
|
36081
|
-
return fs18.existsSync(
|
|
36093
|
+
return fs18.existsSync(path29.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
36082
36094
|
}
|
|
36083
36095
|
function detectGradle(cwd) {
|
|
36084
|
-
const hasBuildFile = fs18.existsSync(
|
|
36085
|
-
const hasGradlew = fs18.existsSync(
|
|
36096
|
+
const hasBuildFile = fs18.existsSync(path29.join(cwd, "build.gradle")) || fs18.existsSync(path29.join(cwd, "build.gradle.kts"));
|
|
36097
|
+
const hasGradlew = fs18.existsSync(path29.join(cwd, "gradlew")) || fs18.existsSync(path29.join(cwd, "gradlew.bat"));
|
|
36086
36098
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
36087
36099
|
}
|
|
36088
36100
|
function detectDotnetTest(cwd) {
|
|
@@ -36095,30 +36107,30 @@ function detectDotnetTest(cwd) {
|
|
|
36095
36107
|
}
|
|
36096
36108
|
}
|
|
36097
36109
|
function detectCTest(cwd) {
|
|
36098
|
-
const hasSource = fs18.existsSync(
|
|
36099
|
-
const hasBuildCache = fs18.existsSync(
|
|
36110
|
+
const hasSource = fs18.existsSync(path29.join(cwd, "CMakeLists.txt"));
|
|
36111
|
+
const hasBuildCache = fs18.existsSync(path29.join(cwd, "CMakeCache.txt")) || fs18.existsSync(path29.join(cwd, "build", "CMakeCache.txt"));
|
|
36100
36112
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
36101
36113
|
}
|
|
36102
36114
|
function detectSwiftTest(cwd) {
|
|
36103
|
-
return fs18.existsSync(
|
|
36115
|
+
return fs18.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
36104
36116
|
}
|
|
36105
36117
|
function detectDartTest(cwd) {
|
|
36106
|
-
return fs18.existsSync(
|
|
36118
|
+
return fs18.existsSync(path29.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
36107
36119
|
}
|
|
36108
36120
|
function detectRSpec(cwd) {
|
|
36109
|
-
const hasRSpecFile = fs18.existsSync(
|
|
36110
|
-
const hasGemfile = fs18.existsSync(
|
|
36111
|
-
const hasSpecDir = fs18.existsSync(
|
|
36121
|
+
const hasRSpecFile = fs18.existsSync(path29.join(cwd, ".rspec"));
|
|
36122
|
+
const hasGemfile = fs18.existsSync(path29.join(cwd, "Gemfile"));
|
|
36123
|
+
const hasSpecDir = fs18.existsSync(path29.join(cwd, "spec"));
|
|
36112
36124
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
36113
36125
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
36114
36126
|
}
|
|
36115
36127
|
function detectMinitest(cwd) {
|
|
36116
|
-
return fs18.existsSync(
|
|
36128
|
+
return fs18.existsSync(path29.join(cwd, "test")) && (fs18.existsSync(path29.join(cwd, "Gemfile")) || fs18.existsSync(path29.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
36117
36129
|
}
|
|
36118
36130
|
async function detectTestFramework(cwd) {
|
|
36119
36131
|
const baseDir = cwd;
|
|
36120
36132
|
try {
|
|
36121
|
-
const packageJsonPath =
|
|
36133
|
+
const packageJsonPath = path29.join(baseDir, "package.json");
|
|
36122
36134
|
if (fs18.existsSync(packageJsonPath)) {
|
|
36123
36135
|
const content = fs18.readFileSync(packageJsonPath, "utf-8");
|
|
36124
36136
|
const pkg = JSON.parse(content);
|
|
@@ -36139,16 +36151,16 @@ async function detectTestFramework(cwd) {
|
|
|
36139
36151
|
return "jest";
|
|
36140
36152
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
36141
36153
|
return "mocha";
|
|
36142
|
-
if (fs18.existsSync(
|
|
36154
|
+
if (fs18.existsSync(path29.join(baseDir, "bun.lockb")) || fs18.existsSync(path29.join(baseDir, "bun.lock"))) {
|
|
36143
36155
|
if (scripts.test?.includes("bun"))
|
|
36144
36156
|
return "bun";
|
|
36145
36157
|
}
|
|
36146
36158
|
}
|
|
36147
36159
|
} catch {}
|
|
36148
36160
|
try {
|
|
36149
|
-
const pyprojectTomlPath =
|
|
36150
|
-
const setupCfgPath =
|
|
36151
|
-
const requirementsTxtPath =
|
|
36161
|
+
const pyprojectTomlPath = path29.join(baseDir, "pyproject.toml");
|
|
36162
|
+
const setupCfgPath = path29.join(baseDir, "setup.cfg");
|
|
36163
|
+
const requirementsTxtPath = path29.join(baseDir, "requirements.txt");
|
|
36152
36164
|
if (fs18.existsSync(pyprojectTomlPath)) {
|
|
36153
36165
|
const content = fs18.readFileSync(pyprojectTomlPath, "utf-8");
|
|
36154
36166
|
if (content.includes("[tool.pytest"))
|
|
@@ -36168,7 +36180,7 @@ async function detectTestFramework(cwd) {
|
|
|
36168
36180
|
}
|
|
36169
36181
|
} catch {}
|
|
36170
36182
|
try {
|
|
36171
|
-
const cargoTomlPath =
|
|
36183
|
+
const cargoTomlPath = path29.join(baseDir, "Cargo.toml");
|
|
36172
36184
|
if (fs18.existsSync(cargoTomlPath)) {
|
|
36173
36185
|
const content = fs18.readFileSync(cargoTomlPath, "utf-8");
|
|
36174
36186
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -36179,9 +36191,9 @@ async function detectTestFramework(cwd) {
|
|
|
36179
36191
|
}
|
|
36180
36192
|
} catch {}
|
|
36181
36193
|
try {
|
|
36182
|
-
const pesterConfigPath =
|
|
36183
|
-
const pesterConfigJsonPath =
|
|
36184
|
-
const pesterPs1Path =
|
|
36194
|
+
const pesterConfigPath = path29.join(baseDir, "pester.config.ps1");
|
|
36195
|
+
const pesterConfigJsonPath = path29.join(baseDir, "pester.config.ps1.json");
|
|
36196
|
+
const pesterPs1Path = path29.join(baseDir, "tests.ps1");
|
|
36185
36197
|
if (fs18.existsSync(pesterConfigPath) || fs18.existsSync(pesterConfigJsonPath) || fs18.existsSync(pesterPs1Path)) {
|
|
36186
36198
|
return "pester";
|
|
36187
36199
|
}
|
|
@@ -36214,8 +36226,8 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
36214
36226
|
const testFiles = [];
|
|
36215
36227
|
for (const file3 of sourceFiles) {
|
|
36216
36228
|
const normalizedPath = file3.replace(/\\/g, "/");
|
|
36217
|
-
const basename5 =
|
|
36218
|
-
const dirname12 =
|
|
36229
|
+
const basename5 = path29.basename(file3);
|
|
36230
|
+
const dirname12 = path29.dirname(file3);
|
|
36219
36231
|
if (hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
|
|
36220
36232
|
if (!testFiles.includes(file3)) {
|
|
36221
36233
|
testFiles.push(file3);
|
|
@@ -36224,13 +36236,13 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
36224
36236
|
}
|
|
36225
36237
|
for (const _pattern of TEST_PATTERNS) {
|
|
36226
36238
|
const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
|
|
36227
|
-
const ext =
|
|
36239
|
+
const ext = path29.extname(basename5);
|
|
36228
36240
|
const possibleTestFiles = [
|
|
36229
|
-
|
|
36230
|
-
|
|
36231
|
-
|
|
36232
|
-
|
|
36233
|
-
|
|
36241
|
+
path29.join(dirname12, `${nameWithoutExt}.spec${ext}`),
|
|
36242
|
+
path29.join(dirname12, `${nameWithoutExt}.test${ext}`),
|
|
36243
|
+
path29.join(dirname12, "__tests__", `${nameWithoutExt}${ext}`),
|
|
36244
|
+
path29.join(dirname12, "tests", `${nameWithoutExt}${ext}`),
|
|
36245
|
+
path29.join(dirname12, "test", `${nameWithoutExt}${ext}`)
|
|
36234
36246
|
];
|
|
36235
36247
|
for (const testFile of possibleTestFiles) {
|
|
36236
36248
|
if (fs18.existsSync(testFile) && !testFiles.includes(testFile)) {
|
|
@@ -36250,7 +36262,7 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36250
36262
|
for (const testFile of candidateTestFiles) {
|
|
36251
36263
|
try {
|
|
36252
36264
|
const content = fs18.readFileSync(testFile, "utf-8");
|
|
36253
|
-
const testDir =
|
|
36265
|
+
const testDir = path29.dirname(testFile);
|
|
36254
36266
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
36255
36267
|
let match;
|
|
36256
36268
|
match = importRegex.exec(content);
|
|
@@ -36258,8 +36270,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36258
36270
|
const importPath = match[1];
|
|
36259
36271
|
let resolvedImport;
|
|
36260
36272
|
if (importPath.startsWith(".")) {
|
|
36261
|
-
resolvedImport =
|
|
36262
|
-
const existingExt =
|
|
36273
|
+
resolvedImport = path29.resolve(testDir, importPath);
|
|
36274
|
+
const existingExt = path29.extname(resolvedImport);
|
|
36263
36275
|
if (!existingExt) {
|
|
36264
36276
|
for (const extToTry of [
|
|
36265
36277
|
".ts",
|
|
@@ -36279,12 +36291,12 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36279
36291
|
} else {
|
|
36280
36292
|
continue;
|
|
36281
36293
|
}
|
|
36282
|
-
const importBasename =
|
|
36283
|
-
const importDir =
|
|
36294
|
+
const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
|
|
36295
|
+
const importDir = path29.dirname(resolvedImport);
|
|
36284
36296
|
for (const sourceFile of sourceFiles) {
|
|
36285
|
-
const sourceDir =
|
|
36286
|
-
const sourceBasename =
|
|
36287
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
36297
|
+
const sourceDir = path29.dirname(sourceFile);
|
|
36298
|
+
const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
|
|
36299
|
+
const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test");
|
|
36288
36300
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
36289
36301
|
if (!testFiles.includes(testFile)) {
|
|
36290
36302
|
testFiles.push(testFile);
|
|
@@ -36299,8 +36311,8 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36299
36311
|
while (match !== null) {
|
|
36300
36312
|
const importPath = match[1];
|
|
36301
36313
|
if (importPath.startsWith(".")) {
|
|
36302
|
-
let resolvedImport =
|
|
36303
|
-
const existingExt =
|
|
36314
|
+
let resolvedImport = path29.resolve(testDir, importPath);
|
|
36315
|
+
const existingExt = path29.extname(resolvedImport);
|
|
36304
36316
|
if (!existingExt) {
|
|
36305
36317
|
for (const extToTry of [
|
|
36306
36318
|
".ts",
|
|
@@ -36317,12 +36329,12 @@ async function getTestFilesFromGraph(sourceFiles) {
|
|
|
36317
36329
|
}
|
|
36318
36330
|
}
|
|
36319
36331
|
}
|
|
36320
|
-
const importDir =
|
|
36321
|
-
const importBasename =
|
|
36332
|
+
const importDir = path29.dirname(resolvedImport);
|
|
36333
|
+
const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
|
|
36322
36334
|
for (const sourceFile of sourceFiles) {
|
|
36323
|
-
const sourceDir =
|
|
36324
|
-
const sourceBasename =
|
|
36325
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
36335
|
+
const sourceDir = path29.dirname(sourceFile);
|
|
36336
|
+
const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
|
|
36337
|
+
const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test");
|
|
36326
36338
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
36327
36339
|
if (!testFiles.includes(testFile)) {
|
|
36328
36340
|
testFiles.push(testFile);
|
|
@@ -36407,8 +36419,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
36407
36419
|
return ["mvn", "test"];
|
|
36408
36420
|
case "gradle": {
|
|
36409
36421
|
const isWindows = process.platform === "win32";
|
|
36410
|
-
const hasGradlewBat = fs18.existsSync(
|
|
36411
|
-
const hasGradlew = fs18.existsSync(
|
|
36422
|
+
const hasGradlewBat = fs18.existsSync(path29.join(baseDir, "gradlew.bat"));
|
|
36423
|
+
const hasGradlew = fs18.existsSync(path29.join(baseDir, "gradlew"));
|
|
36412
36424
|
if (hasGradlewBat && isWindows)
|
|
36413
36425
|
return ["gradlew.bat", "test"];
|
|
36414
36426
|
if (hasGradlew)
|
|
@@ -36425,7 +36437,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
36425
36437
|
"cmake-build-release",
|
|
36426
36438
|
"out"
|
|
36427
36439
|
];
|
|
36428
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs18.existsSync(
|
|
36440
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs18.existsSync(path29.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
36429
36441
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
36430
36442
|
}
|
|
36431
36443
|
case "swift-test":
|
|
@@ -36993,7 +37005,7 @@ var init_test_runner = __esm(() => {
|
|
|
36993
37005
|
let effectiveScope = scope;
|
|
36994
37006
|
if (scope === "all") {} else if (scope === "convention") {
|
|
36995
37007
|
const sourceFiles = args2.files.filter((f) => {
|
|
36996
|
-
const ext =
|
|
37008
|
+
const ext = path29.extname(f).toLowerCase();
|
|
36997
37009
|
return SOURCE_EXTENSIONS.has(ext);
|
|
36998
37010
|
});
|
|
36999
37011
|
if (sourceFiles.length === 0) {
|
|
@@ -37009,7 +37021,7 @@ var init_test_runner = __esm(() => {
|
|
|
37009
37021
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
37010
37022
|
} else if (scope === "graph") {
|
|
37011
37023
|
const sourceFiles = args2.files.filter((f) => {
|
|
37012
|
-
const ext =
|
|
37024
|
+
const ext = path29.extname(f).toLowerCase();
|
|
37013
37025
|
return SOURCE_EXTENSIONS.has(ext);
|
|
37014
37026
|
});
|
|
37015
37027
|
if (sourceFiles.length === 0) {
|
|
@@ -37063,7 +37075,7 @@ var init_test_runner = __esm(() => {
|
|
|
37063
37075
|
|
|
37064
37076
|
// src/services/preflight-service.ts
|
|
37065
37077
|
import * as fs19 from "fs";
|
|
37066
|
-
import * as
|
|
37078
|
+
import * as path30 from "path";
|
|
37067
37079
|
function validateDirectoryPath(dir) {
|
|
37068
37080
|
if (!dir || typeof dir !== "string") {
|
|
37069
37081
|
throw new Error("Directory path is required");
|
|
@@ -37071,8 +37083,8 @@ function validateDirectoryPath(dir) {
|
|
|
37071
37083
|
if (dir.includes("..")) {
|
|
37072
37084
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
37073
37085
|
}
|
|
37074
|
-
const normalized =
|
|
37075
|
-
const absolutePath =
|
|
37086
|
+
const normalized = path30.normalize(dir);
|
|
37087
|
+
const absolutePath = path30.isAbsolute(normalized) ? normalized : path30.resolve(normalized);
|
|
37076
37088
|
return absolutePath;
|
|
37077
37089
|
}
|
|
37078
37090
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -37095,7 +37107,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
37095
37107
|
}
|
|
37096
37108
|
function getPackageVersion(dir) {
|
|
37097
37109
|
try {
|
|
37098
|
-
const packagePath =
|
|
37110
|
+
const packagePath = path30.join(dir, "package.json");
|
|
37099
37111
|
if (fs19.existsSync(packagePath)) {
|
|
37100
37112
|
const content = fs19.readFileSync(packagePath, "utf-8");
|
|
37101
37113
|
const pkg = JSON.parse(content);
|
|
@@ -37106,7 +37118,7 @@ function getPackageVersion(dir) {
|
|
|
37106
37118
|
}
|
|
37107
37119
|
function getChangelogVersion(dir) {
|
|
37108
37120
|
try {
|
|
37109
|
-
const changelogPath =
|
|
37121
|
+
const changelogPath = path30.join(dir, "CHANGELOG.md");
|
|
37110
37122
|
if (fs19.existsSync(changelogPath)) {
|
|
37111
37123
|
const content = fs19.readFileSync(changelogPath, "utf-8");
|
|
37112
37124
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -37120,7 +37132,7 @@ function getChangelogVersion(dir) {
|
|
|
37120
37132
|
function getVersionFileVersion(dir) {
|
|
37121
37133
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
37122
37134
|
for (const file3 of possibleFiles) {
|
|
37123
|
-
const filePath =
|
|
37135
|
+
const filePath = path30.join(dir, file3);
|
|
37124
37136
|
if (fs19.existsSync(filePath)) {
|
|
37125
37137
|
try {
|
|
37126
37138
|
const content = fs19.readFileSync(filePath, "utf-8").trim();
|
|
@@ -37648,7 +37660,7 @@ __export(exports_gate_evidence, {
|
|
|
37648
37660
|
DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
|
|
37649
37661
|
});
|
|
37650
37662
|
import { mkdirSync as mkdirSync12, readFileSync as readFileSync17, renameSync as renameSync10, unlinkSync as unlinkSync5 } from "fs";
|
|
37651
|
-
import * as
|
|
37663
|
+
import * as path37 from "path";
|
|
37652
37664
|
function isValidTaskId2(taskId) {
|
|
37653
37665
|
if (!taskId)
|
|
37654
37666
|
return false;
|
|
@@ -37695,10 +37707,10 @@ function expandRequiredGates(existingGates, newAgentType) {
|
|
|
37695
37707
|
return combined.sort();
|
|
37696
37708
|
}
|
|
37697
37709
|
function getEvidenceDir(directory) {
|
|
37698
|
-
return
|
|
37710
|
+
return path37.join(directory, ".swarm", "evidence");
|
|
37699
37711
|
}
|
|
37700
37712
|
function getEvidencePath(directory, taskId) {
|
|
37701
|
-
return
|
|
37713
|
+
return path37.join(getEvidenceDir(directory), `${taskId}.json`);
|
|
37702
37714
|
}
|
|
37703
37715
|
function readExisting(evidencePath) {
|
|
37704
37716
|
try {
|
|
@@ -37809,12 +37821,12 @@ __export(exports_review_receipt, {
|
|
|
37809
37821
|
});
|
|
37810
37822
|
import * as crypto5 from "crypto";
|
|
37811
37823
|
import * as fs28 from "fs";
|
|
37812
|
-
import * as
|
|
37824
|
+
import * as path39 from "path";
|
|
37813
37825
|
function resolveReceiptsDir(directory) {
|
|
37814
|
-
return
|
|
37826
|
+
return path39.join(directory, ".swarm", "review-receipts");
|
|
37815
37827
|
}
|
|
37816
37828
|
function resolveReceiptIndexPath(directory) {
|
|
37817
|
-
return
|
|
37829
|
+
return path39.join(resolveReceiptsDir(directory), "index.json");
|
|
37818
37830
|
}
|
|
37819
37831
|
function buildReceiptFilename(id, date9) {
|
|
37820
37832
|
const dateStr = date9.toISOString().slice(0, 10);
|
|
@@ -37853,7 +37865,7 @@ async function readReceiptIndex(directory) {
|
|
|
37853
37865
|
}
|
|
37854
37866
|
async function writeReceiptIndex(directory, index) {
|
|
37855
37867
|
const indexPath = resolveReceiptIndexPath(directory);
|
|
37856
|
-
const dir =
|
|
37868
|
+
const dir = path39.dirname(indexPath);
|
|
37857
37869
|
await fs28.promises.mkdir(dir, { recursive: true });
|
|
37858
37870
|
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37859
37871
|
await fs28.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
@@ -37864,7 +37876,7 @@ async function persistReviewReceipt(directory, receipt) {
|
|
|
37864
37876
|
await fs28.promises.mkdir(receiptsDir, { recursive: true });
|
|
37865
37877
|
const now = new Date(receipt.reviewed_at);
|
|
37866
37878
|
const filename = buildReceiptFilename(receipt.id, now);
|
|
37867
|
-
const receiptPath =
|
|
37879
|
+
const receiptPath = path39.join(receiptsDir, filename);
|
|
37868
37880
|
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
37869
37881
|
await fs28.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
37870
37882
|
fs28.renameSync(tmpPath, receiptPath);
|
|
@@ -37886,7 +37898,7 @@ async function readReceiptById(directory, receiptId) {
|
|
|
37886
37898
|
const entry = index.entries.find((e) => e.id === receiptId);
|
|
37887
37899
|
if (!entry)
|
|
37888
37900
|
return null;
|
|
37889
|
-
const receiptPath =
|
|
37901
|
+
const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
|
|
37890
37902
|
try {
|
|
37891
37903
|
const content = await fs28.promises.readFile(receiptPath, "utf-8");
|
|
37892
37904
|
return JSON.parse(content);
|
|
@@ -37899,7 +37911,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
|
37899
37911
|
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37900
37912
|
const receipts = [];
|
|
37901
37913
|
for (const entry of matching) {
|
|
37902
|
-
const receiptPath =
|
|
37914
|
+
const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
|
|
37903
37915
|
try {
|
|
37904
37916
|
const content = await fs28.promises.readFile(receiptPath, "utf-8");
|
|
37905
37917
|
receipts.push(JSON.parse(content));
|
|
@@ -37912,7 +37924,7 @@ async function readAllReceipts(directory) {
|
|
|
37912
37924
|
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
37913
37925
|
const receipts = [];
|
|
37914
37926
|
for (const entry of sorted) {
|
|
37915
|
-
const receiptPath =
|
|
37927
|
+
const receiptPath = path39.join(resolveReceiptsDir(directory), entry.filename);
|
|
37916
37928
|
try {
|
|
37917
37929
|
const content = await fs28.promises.readFile(receiptPath, "utf-8");
|
|
37918
37930
|
receipts.push(JSON.parse(content));
|
|
@@ -38048,13 +38060,13 @@ __export(exports_doc_scan, {
|
|
|
38048
38060
|
import * as crypto6 from "crypto";
|
|
38049
38061
|
import * as fs31 from "fs";
|
|
38050
38062
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
38051
|
-
import * as
|
|
38063
|
+
import * as path43 from "path";
|
|
38052
38064
|
function normalizeSeparators(filePath) {
|
|
38053
38065
|
return filePath.replace(/\\/g, "/");
|
|
38054
38066
|
}
|
|
38055
38067
|
function matchesDocPattern(filePath, patterns) {
|
|
38056
38068
|
const normalizedPath = normalizeSeparators(filePath);
|
|
38057
|
-
const basename6 =
|
|
38069
|
+
const basename6 = path43.basename(filePath);
|
|
38058
38070
|
for (const pattern of patterns) {
|
|
38059
38071
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
38060
38072
|
if (basename6 === pattern) {
|
|
@@ -38110,7 +38122,7 @@ function stripMarkdown(text) {
|
|
|
38110
38122
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
38111
38123
|
}
|
|
38112
38124
|
async function scanDocIndex(directory) {
|
|
38113
|
-
const manifestPath =
|
|
38125
|
+
const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
|
|
38114
38126
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
38115
38127
|
const extraPatterns = [
|
|
38116
38128
|
"ARCHITECTURE.md",
|
|
@@ -38127,7 +38139,7 @@ async function scanDocIndex(directory) {
|
|
|
38127
38139
|
let cacheValid = true;
|
|
38128
38140
|
for (const file3 of existingManifest.files) {
|
|
38129
38141
|
try {
|
|
38130
|
-
const fullPath =
|
|
38142
|
+
const fullPath = path43.join(directory, file3.path);
|
|
38131
38143
|
const stat2 = fs31.statSync(fullPath);
|
|
38132
38144
|
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
38133
38145
|
cacheValid = false;
|
|
@@ -38157,7 +38169,7 @@ async function scanDocIndex(directory) {
|
|
|
38157
38169
|
}
|
|
38158
38170
|
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
38159
38171
|
for (const entry of entries) {
|
|
38160
|
-
const fullPath =
|
|
38172
|
+
const fullPath = path43.join(directory, entry);
|
|
38161
38173
|
let stat2;
|
|
38162
38174
|
try {
|
|
38163
38175
|
stat2 = fs31.statSync(fullPath);
|
|
@@ -38193,7 +38205,7 @@ async function scanDocIndex(directory) {
|
|
|
38193
38205
|
} catch {
|
|
38194
38206
|
continue;
|
|
38195
38207
|
}
|
|
38196
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
38208
|
+
const { title, summary } = extractTitleAndSummary(content, path43.basename(entry));
|
|
38197
38209
|
const lineCount = content.split(`
|
|
38198
38210
|
`).length;
|
|
38199
38211
|
discoveredFiles.push({
|
|
@@ -38219,7 +38231,7 @@ async function scanDocIndex(directory) {
|
|
|
38219
38231
|
files: discoveredFiles
|
|
38220
38232
|
};
|
|
38221
38233
|
try {
|
|
38222
|
-
await mkdir6(
|
|
38234
|
+
await mkdir6(path43.dirname(manifestPath), { recursive: true });
|
|
38223
38235
|
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
38224
38236
|
} catch {}
|
|
38225
38237
|
return { manifest, cached: false };
|
|
@@ -38258,7 +38270,7 @@ function extractConstraintsFromContent(content) {
|
|
|
38258
38270
|
return constraints;
|
|
38259
38271
|
}
|
|
38260
38272
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
38261
|
-
const manifestPath =
|
|
38273
|
+
const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
|
|
38262
38274
|
let manifest;
|
|
38263
38275
|
try {
|
|
38264
38276
|
const content = await readFile6(manifestPath, "utf-8");
|
|
@@ -38284,7 +38296,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
38284
38296
|
}
|
|
38285
38297
|
let fullContent;
|
|
38286
38298
|
try {
|
|
38287
|
-
fullContent = await readFile6(
|
|
38299
|
+
fullContent = await readFile6(path43.join(directory, docFile.path), "utf-8");
|
|
38288
38300
|
} catch {
|
|
38289
38301
|
skippedCount++;
|
|
38290
38302
|
continue;
|
|
@@ -38307,7 +38319,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
38307
38319
|
tier: "swarm",
|
|
38308
38320
|
lesson: constraint,
|
|
38309
38321
|
category: "architecture",
|
|
38310
|
-
tags: ["doc-scan",
|
|
38322
|
+
tags: ["doc-scan", path43.basename(docFile.path)],
|
|
38311
38323
|
scope: "global",
|
|
38312
38324
|
confidence: 0.5,
|
|
38313
38325
|
status: "candidate",
|
|
@@ -38380,7 +38392,7 @@ var init_doc_scan = __esm(() => {
|
|
|
38380
38392
|
}
|
|
38381
38393
|
} catch {}
|
|
38382
38394
|
if (force) {
|
|
38383
|
-
const manifestPath =
|
|
38395
|
+
const manifestPath = path43.join(directory, ".swarm", "doc-manifest.json");
|
|
38384
38396
|
try {
|
|
38385
38397
|
fs31.unlinkSync(manifestPath);
|
|
38386
38398
|
} catch {}
|
|
@@ -38435,9 +38447,9 @@ __export(exports_curator_drift, {
|
|
|
38435
38447
|
buildDriftInjectionText: () => buildDriftInjectionText
|
|
38436
38448
|
});
|
|
38437
38449
|
import * as fs34 from "fs";
|
|
38438
|
-
import * as
|
|
38450
|
+
import * as path46 from "path";
|
|
38439
38451
|
async function readPriorDriftReports(directory) {
|
|
38440
|
-
const swarmDir =
|
|
38452
|
+
const swarmDir = path46.join(directory, ".swarm");
|
|
38441
38453
|
const entries = await fs34.promises.readdir(swarmDir).catch(() => null);
|
|
38442
38454
|
if (entries === null)
|
|
38443
38455
|
return [];
|
|
@@ -38464,7 +38476,7 @@ async function readPriorDriftReports(directory) {
|
|
|
38464
38476
|
async function writeDriftReport(directory, report) {
|
|
38465
38477
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
38466
38478
|
const filePath = validateSwarmPath(directory, filename);
|
|
38467
|
-
const swarmDir =
|
|
38479
|
+
const swarmDir = path46.dirname(filePath);
|
|
38468
38480
|
await fs34.promises.mkdir(swarmDir, { recursive: true });
|
|
38469
38481
|
try {
|
|
38470
38482
|
await fs34.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
@@ -40057,11 +40069,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
40057
40069
|
throw toThrow;
|
|
40058
40070
|
}, "quit_");
|
|
40059
40071
|
var scriptDirectory = "";
|
|
40060
|
-
function locateFile(
|
|
40072
|
+
function locateFile(path56) {
|
|
40061
40073
|
if (Module["locateFile"]) {
|
|
40062
|
-
return Module["locateFile"](
|
|
40074
|
+
return Module["locateFile"](path56, scriptDirectory);
|
|
40063
40075
|
}
|
|
40064
|
-
return scriptDirectory +
|
|
40076
|
+
return scriptDirectory + path56;
|
|
40065
40077
|
}
|
|
40066
40078
|
__name(locateFile, "locateFile");
|
|
40067
40079
|
var readAsync, readBinary;
|
|
@@ -41801,13 +41813,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
41801
41813
|
});
|
|
41802
41814
|
|
|
41803
41815
|
// src/lang/runtime.ts
|
|
41804
|
-
import * as
|
|
41816
|
+
import * as path56 from "path";
|
|
41805
41817
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
41806
41818
|
async function initTreeSitter() {
|
|
41807
41819
|
if (treeSitterInitialized) {
|
|
41808
41820
|
return;
|
|
41809
41821
|
}
|
|
41810
|
-
const thisDir =
|
|
41822
|
+
const thisDir = path56.dirname(fileURLToPath2(import.meta.url));
|
|
41811
41823
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41812
41824
|
if (isSource) {
|
|
41813
41825
|
await Parser.init();
|
|
@@ -41815,7 +41827,7 @@ async function initTreeSitter() {
|
|
|
41815
41827
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
41816
41828
|
await Parser.init({
|
|
41817
41829
|
locateFile(scriptName) {
|
|
41818
|
-
return
|
|
41830
|
+
return path56.join(grammarsDir, scriptName);
|
|
41819
41831
|
}
|
|
41820
41832
|
});
|
|
41821
41833
|
}
|
|
@@ -41836,9 +41848,9 @@ function getWasmFileName(languageId) {
|
|
|
41836
41848
|
return `tree-sitter-${sanitized}.wasm`;
|
|
41837
41849
|
}
|
|
41838
41850
|
function getGrammarsDirAbsolute() {
|
|
41839
|
-
const thisDir =
|
|
41851
|
+
const thisDir = path56.dirname(fileURLToPath2(import.meta.url));
|
|
41840
41852
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41841
|
-
return isSource ?
|
|
41853
|
+
return isSource ? path56.join(thisDir, "grammars") : path56.join(thisDir, "lang", "grammars");
|
|
41842
41854
|
}
|
|
41843
41855
|
async function loadGrammar(languageId) {
|
|
41844
41856
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -41854,7 +41866,7 @@ async function loadGrammar(languageId) {
|
|
|
41854
41866
|
await initTreeSitter();
|
|
41855
41867
|
const parser = new Parser;
|
|
41856
41868
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
41857
|
-
const wasmPath =
|
|
41869
|
+
const wasmPath = path56.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
41858
41870
|
const { existsSync: existsSync33 } = await import("fs");
|
|
41859
41871
|
if (!existsSync33(wasmPath)) {
|
|
41860
41872
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
@@ -41901,7 +41913,7 @@ var init_runtime = __esm(() => {
|
|
|
41901
41913
|
});
|
|
41902
41914
|
|
|
41903
41915
|
// src/index.ts
|
|
41904
|
-
import * as
|
|
41916
|
+
import * as path74 from "path";
|
|
41905
41917
|
|
|
41906
41918
|
// src/agents/index.ts
|
|
41907
41919
|
init_config();
|
|
@@ -46668,7 +46680,9 @@ async function handleClarifyCommand(_directory, args2) {
|
|
|
46668
46680
|
// src/commands/close.ts
|
|
46669
46681
|
init_schema();
|
|
46670
46682
|
init_manager();
|
|
46683
|
+
import { execFileSync } from "child_process";
|
|
46671
46684
|
import { promises as fs11 } from "fs";
|
|
46685
|
+
import path17 from "path";
|
|
46672
46686
|
|
|
46673
46687
|
// src/hooks/knowledge-reader.ts
|
|
46674
46688
|
init_knowledge_store();
|
|
@@ -48053,87 +48067,183 @@ var write_retro = createSwarmTool({
|
|
|
48053
48067
|
});
|
|
48054
48068
|
|
|
48055
48069
|
// src/commands/close.ts
|
|
48056
|
-
async function handleCloseCommand(directory,
|
|
48070
|
+
async function handleCloseCommand(directory, args2) {
|
|
48057
48071
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
48058
|
-
let
|
|
48072
|
+
let planExists = false;
|
|
48073
|
+
let planData = {
|
|
48074
|
+
title: path17.basename(directory) || "Ad-hoc session",
|
|
48075
|
+
phases: []
|
|
48076
|
+
};
|
|
48059
48077
|
try {
|
|
48060
48078
|
const content = await fs11.readFile(planPath, "utf-8");
|
|
48061
48079
|
planData = JSON.parse(content);
|
|
48080
|
+
planExists = true;
|
|
48062
48081
|
} catch (error93) {
|
|
48063
|
-
|
|
48082
|
+
if (error93?.code !== "ENOENT") {
|
|
48083
|
+
return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
48084
|
+
}
|
|
48085
|
+
const swarmDirExists = await fs11.access(path17.join(directory, ".swarm")).then(() => true).catch(() => false);
|
|
48086
|
+
if (!swarmDirExists) {
|
|
48087
|
+
return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
|
|
48088
|
+
}
|
|
48064
48089
|
}
|
|
48065
48090
|
const phases = planData.phases ?? [];
|
|
48066
48091
|
const inProgressPhases = phases.filter((p) => p.status === "in_progress");
|
|
48067
|
-
|
|
48068
|
-
if (
|
|
48069
|
-
|
|
48070
|
-
const blockedCount = phases.filter((p) => p.status === "blocked").length;
|
|
48071
|
-
const completeCount = phases.filter((p) => p.status === "complete" || p.status === "completed").length;
|
|
48072
|
-
return `\u2139\uFE0F Swarm already closed. ${completeCount} phases complete, ${closedCount} phases closed, ${blockedCount} phases blocked. No action taken.`;
|
|
48092
|
+
let planAlreadyDone = false;
|
|
48093
|
+
if (planExists) {
|
|
48094
|
+
planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
|
|
48073
48095
|
}
|
|
48074
48096
|
const config3 = KnowledgeConfigSchema.parse({});
|
|
48075
48097
|
const projectName = planData.title ?? "Unknown Project";
|
|
48076
48098
|
const closedPhases = [];
|
|
48077
48099
|
const closedTasks = [];
|
|
48078
48100
|
const warnings = [];
|
|
48079
|
-
|
|
48080
|
-
|
|
48081
|
-
|
|
48082
|
-
|
|
48083
|
-
|
|
48084
|
-
|
|
48085
|
-
|
|
48086
|
-
|
|
48087
|
-
|
|
48088
|
-
|
|
48089
|
-
|
|
48090
|
-
|
|
48091
|
-
|
|
48092
|
-
|
|
48093
|
-
|
|
48094
|
-
|
|
48095
|
-
|
|
48096
|
-
|
|
48101
|
+
if (!planAlreadyDone) {
|
|
48102
|
+
for (const phase of inProgressPhases) {
|
|
48103
|
+
closedPhases.push(phase.id);
|
|
48104
|
+
let retroResult;
|
|
48105
|
+
try {
|
|
48106
|
+
retroResult = await executeWriteRetro({
|
|
48107
|
+
phase: phase.id,
|
|
48108
|
+
summary: "Phase closed via /swarm close",
|
|
48109
|
+
task_count: Math.max(1, (phase.tasks ?? []).length),
|
|
48110
|
+
task_complexity: "simple",
|
|
48111
|
+
total_tool_calls: 0,
|
|
48112
|
+
coder_revisions: 0,
|
|
48113
|
+
reviewer_rejections: 0,
|
|
48114
|
+
test_failures: 0,
|
|
48115
|
+
security_findings: 0,
|
|
48116
|
+
integration_issues: 0
|
|
48117
|
+
}, directory);
|
|
48118
|
+
} catch (retroError) {
|
|
48119
|
+
warnings.push(`Retrospective write threw for phase ${phase.id}: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
48120
|
+
}
|
|
48121
|
+
if (retroResult !== undefined) {
|
|
48122
|
+
try {
|
|
48123
|
+
const parsed = JSON.parse(retroResult);
|
|
48124
|
+
if (parsed.success !== true) {
|
|
48125
|
+
warnings.push(`Retrospective write failed for phase ${phase.id}`);
|
|
48126
|
+
}
|
|
48127
|
+
} catch {}
|
|
48097
48128
|
}
|
|
48098
|
-
|
|
48099
|
-
|
|
48100
|
-
|
|
48101
|
-
|
|
48129
|
+
for (const task of phase.tasks ?? []) {
|
|
48130
|
+
if (task.status !== "completed" && task.status !== "complete") {
|
|
48131
|
+
closedTasks.push(task.id);
|
|
48132
|
+
}
|
|
48102
48133
|
}
|
|
48103
48134
|
}
|
|
48104
48135
|
}
|
|
48136
|
+
const lessonsFilePath = path17.join(directory, ".swarm", "close-lessons.md");
|
|
48137
|
+
let explicitLessons = [];
|
|
48105
48138
|
try {
|
|
48106
|
-
|
|
48139
|
+
const lessonsText = await fs11.readFile(lessonsFilePath, "utf-8");
|
|
48140
|
+
explicitLessons = lessonsText.split(`
|
|
48141
|
+
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
48142
|
+
} catch {}
|
|
48143
|
+
let curationSucceeded = false;
|
|
48144
|
+
try {
|
|
48145
|
+
await curateAndStoreSwarm(explicitLessons, projectName, { phase_number: 0 }, directory, config3);
|
|
48146
|
+
curationSucceeded = true;
|
|
48107
48147
|
} catch (error93) {
|
|
48108
48148
|
console.warn("[close-command] curateAndStoreSwarm error:", error93);
|
|
48109
48149
|
}
|
|
48110
|
-
|
|
48111
|
-
|
|
48112
|
-
|
|
48113
|
-
|
|
48114
|
-
|
|
48150
|
+
if (curationSucceeded && explicitLessons.length > 0) {
|
|
48151
|
+
await fs11.unlink(lessonsFilePath).catch(() => {});
|
|
48152
|
+
}
|
|
48153
|
+
if (planExists && !planAlreadyDone) {
|
|
48154
|
+
for (const phase of phases) {
|
|
48155
|
+
if (phase.status !== "complete" && phase.status !== "completed") {
|
|
48156
|
+
phase.status = "closed";
|
|
48157
|
+
if (!closedPhases.includes(phase.id)) {
|
|
48158
|
+
closedPhases.push(phase.id);
|
|
48159
|
+
}
|
|
48115
48160
|
}
|
|
48116
|
-
|
|
48117
|
-
|
|
48118
|
-
|
|
48119
|
-
|
|
48120
|
-
|
|
48121
|
-
|
|
48161
|
+
for (const task of phase.tasks ?? []) {
|
|
48162
|
+
if (task.status !== "completed" && task.status !== "complete") {
|
|
48163
|
+
task.status = "closed";
|
|
48164
|
+
if (!closedTasks.includes(task.id)) {
|
|
48165
|
+
closedTasks.push(task.id);
|
|
48166
|
+
}
|
|
48122
48167
|
}
|
|
48123
48168
|
}
|
|
48124
48169
|
}
|
|
48170
|
+
try {
|
|
48171
|
+
await fs11.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
|
|
48172
|
+
} catch (error93) {
|
|
48173
|
+
console.warn("[close-command] Failed to write plan.json:", error93);
|
|
48174
|
+
}
|
|
48125
48175
|
}
|
|
48126
48176
|
try {
|
|
48127
|
-
await
|
|
48177
|
+
await archiveEvidence(directory, 30, 10);
|
|
48128
48178
|
} catch (error93) {
|
|
48129
|
-
console.warn("[close-command]
|
|
48179
|
+
console.warn("[close-command] archiveEvidence error:", error93);
|
|
48130
48180
|
}
|
|
48181
|
+
const swarmDir = path17.join(directory, ".swarm");
|
|
48182
|
+
let configBackupsRemoved = 0;
|
|
48131
48183
|
try {
|
|
48132
|
-
await
|
|
48184
|
+
const swarmFiles = await fs11.readdir(swarmDir);
|
|
48185
|
+
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
48186
|
+
for (const backup of configBackups) {
|
|
48187
|
+
try {
|
|
48188
|
+
await fs11.unlink(path17.join(swarmDir, backup));
|
|
48189
|
+
configBackupsRemoved++;
|
|
48190
|
+
} catch {}
|
|
48191
|
+
}
|
|
48192
|
+
} catch {}
|
|
48193
|
+
const contextPath = path17.join(directory, ".swarm", "context.md");
|
|
48194
|
+
const contextContent = [
|
|
48195
|
+
"# Context",
|
|
48196
|
+
"",
|
|
48197
|
+
"## Status",
|
|
48198
|
+
`Session closed after: ${projectName}`,
|
|
48199
|
+
`Closed: ${new Date().toISOString()}`,
|
|
48200
|
+
"No active plan. Next session starts fresh.",
|
|
48201
|
+
""
|
|
48202
|
+
].join(`
|
|
48203
|
+
`);
|
|
48204
|
+
try {
|
|
48205
|
+
await fs11.writeFile(contextPath, contextContent, "utf-8");
|
|
48133
48206
|
} catch (error93) {
|
|
48134
|
-
console.warn("[close-command]
|
|
48207
|
+
console.warn("[close-command] Failed to write context.md:", error93);
|
|
48208
|
+
}
|
|
48209
|
+
const pruneBranches = args2.includes("--prune-branches");
|
|
48210
|
+
const prunedBranches = [];
|
|
48211
|
+
const pruneErrors = [];
|
|
48212
|
+
if (pruneBranches) {
|
|
48213
|
+
try {
|
|
48214
|
+
const branchOutput = execFileSync("git", ["branch", "-vv"], {
|
|
48215
|
+
cwd: directory,
|
|
48216
|
+
encoding: "utf-8",
|
|
48217
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
48218
|
+
});
|
|
48219
|
+
const goneBranches = branchOutput.split(`
|
|
48220
|
+
`).filter((line) => line.includes(": gone]")).map((line) => line.trim().replace(/^[*+]\s+/, "").split(/\s+/)[0]).filter(Boolean);
|
|
48221
|
+
for (const branch of goneBranches) {
|
|
48222
|
+
try {
|
|
48223
|
+
execFileSync("git", ["branch", "-d", branch], {
|
|
48224
|
+
cwd: directory,
|
|
48225
|
+
encoding: "utf-8",
|
|
48226
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
48227
|
+
});
|
|
48228
|
+
prunedBranches.push(branch);
|
|
48229
|
+
} catch {
|
|
48230
|
+
pruneErrors.push(branch);
|
|
48231
|
+
}
|
|
48232
|
+
}
|
|
48233
|
+
} catch {}
|
|
48135
48234
|
}
|
|
48136
48235
|
const closeSummaryPath = validateSwarmPath(directory, "close-summary.md");
|
|
48236
|
+
const actionsPerformed = [
|
|
48237
|
+
...!planAlreadyDone && inProgressPhases.length > 0 ? ["- Wrote retrospectives for in-progress phases"] : [],
|
|
48238
|
+
"- Archived evidence bundles",
|
|
48239
|
+
"- Reset context.md for next session",
|
|
48240
|
+
...configBackupsRemoved > 0 ? [`- Removed ${configBackupsRemoved} stale config backup file(s)`] : [],
|
|
48241
|
+
...prunedBranches.length > 0 ? [
|
|
48242
|
+
`- Pruned ${prunedBranches.length} stale local git branch(es): ${prunedBranches.join(", ")}`
|
|
48243
|
+
] : [],
|
|
48244
|
+
"- Cleared agent sessions and delegation chains",
|
|
48245
|
+
...planExists && !planAlreadyDone ? ["- Set non-completed phases/tasks to closed status"] : []
|
|
48246
|
+
];
|
|
48137
48247
|
const summaryContent = [
|
|
48138
48248
|
"# Swarm Close Summary",
|
|
48139
48249
|
"",
|
|
@@ -48141,18 +48251,15 @@ async function handleCloseCommand(directory, _args) {
|
|
|
48141
48251
|
`**Closed:** ${new Date().toISOString()}`,
|
|
48142
48252
|
"",
|
|
48143
48253
|
`## Phases Closed: ${closedPhases.length}`,
|
|
48144
|
-
closedPhases.map((id) => `- Phase ${id}`).join(`
|
|
48145
|
-
`),
|
|
48254
|
+
!planExists ? "_No plan \u2014 ad-hoc session_" : closedPhases.length > 0 ? closedPhases.map((id) => `- Phase ${id}`).join(`
|
|
48255
|
+
`) : "_No phases to close_",
|
|
48146
48256
|
"",
|
|
48147
48257
|
`## Tasks Closed: ${closedTasks.length}`,
|
|
48148
48258
|
closedTasks.length > 0 ? closedTasks.map((id) => `- ${id}`).join(`
|
|
48149
48259
|
`) : "_No incomplete tasks_",
|
|
48150
48260
|
"",
|
|
48151
48261
|
"## Actions Performed",
|
|
48152
|
-
|
|
48153
|
-
"- Archived evidence bundles",
|
|
48154
|
-
"- Cleared agent sessions and delegation chains",
|
|
48155
|
-
"- Set non-completed phases/tasks to closed status"
|
|
48262
|
+
...actionsPerformed
|
|
48156
48263
|
].join(`
|
|
48157
48264
|
`);
|
|
48158
48265
|
try {
|
|
@@ -48168,21 +48275,27 @@ async function handleCloseCommand(directory, _args) {
|
|
|
48168
48275
|
await writeCheckpoint(directory).catch(() => {});
|
|
48169
48276
|
swarmState.agentSessions.clear();
|
|
48170
48277
|
swarmState.delegationChains.clear();
|
|
48278
|
+
if (pruneErrors.length > 0) {
|
|
48279
|
+
warnings.push(`Could not prune ${pruneErrors.length} branch(es) (unmerged or checked out): ${pruneErrors.join(", ")}`);
|
|
48280
|
+
}
|
|
48171
48281
|
const warningMsg = warnings.length > 0 ? ` Warnings: ${warnings.join("; ")}.` : "";
|
|
48282
|
+
if (planAlreadyDone) {
|
|
48283
|
+
return `\u2705 Session closed. Plan was already in a terminal state \u2014 cleanup steps applied.${warningMsg}`;
|
|
48284
|
+
}
|
|
48172
48285
|
return `\u2705 Swarm closed successfully. ${closedPhases.length} phase(s) closed, ${closedTasks.length} incomplete task(s) marked closed.${warningMsg}`;
|
|
48173
48286
|
}
|
|
48174
48287
|
|
|
48175
48288
|
// src/commands/config.ts
|
|
48176
48289
|
init_loader();
|
|
48177
48290
|
import * as os4 from "os";
|
|
48178
|
-
import * as
|
|
48291
|
+
import * as path18 from "path";
|
|
48179
48292
|
function getUserConfigDir2() {
|
|
48180
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
48293
|
+
return process.env.XDG_CONFIG_HOME || path18.join(os4.homedir(), ".config");
|
|
48181
48294
|
}
|
|
48182
48295
|
async function handleConfigCommand(directory, _args) {
|
|
48183
48296
|
const config3 = loadPluginConfig(directory);
|
|
48184
|
-
const userConfigPath =
|
|
48185
|
-
const projectConfigPath =
|
|
48297
|
+
const userConfigPath = path18.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
48298
|
+
const projectConfigPath = path18.join(directory, ".opencode", "opencode-swarm.json");
|
|
48186
48299
|
const lines = [
|
|
48187
48300
|
"## Swarm Configuration",
|
|
48188
48301
|
"",
|
|
@@ -48205,7 +48318,7 @@ init_schema();
|
|
|
48205
48318
|
// src/hooks/curator.ts
|
|
48206
48319
|
import { randomUUID } from "crypto";
|
|
48207
48320
|
import * as fs12 from "fs";
|
|
48208
|
-
import * as
|
|
48321
|
+
import * as path19 from "path";
|
|
48209
48322
|
init_event_bus();
|
|
48210
48323
|
init_manager2();
|
|
48211
48324
|
init_knowledge_store();
|
|
@@ -48259,7 +48372,7 @@ async function readCuratorSummary(directory) {
|
|
|
48259
48372
|
}
|
|
48260
48373
|
async function writeCuratorSummary(directory, summary) {
|
|
48261
48374
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
48262
|
-
fs12.mkdirSync(
|
|
48375
|
+
fs12.mkdirSync(path19.dirname(resolvedPath), { recursive: true });
|
|
48263
48376
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
48264
48377
|
await Bun.write(tempPath, JSON.stringify(summary, null, 2));
|
|
48265
48378
|
fs12.renameSync(tempPath, resolvedPath);
|
|
@@ -48630,7 +48743,7 @@ ${phaseDigest.summary}`,
|
|
|
48630
48743
|
};
|
|
48631
48744
|
}
|
|
48632
48745
|
await writeCuratorSummary(directory, updatedSummary);
|
|
48633
|
-
const eventsPath =
|
|
48746
|
+
const eventsPath = path19.join(directory, ".swarm", "events.jsonl");
|
|
48634
48747
|
for (const obs of complianceObservations) {
|
|
48635
48748
|
await appendKnowledge(eventsPath, {
|
|
48636
48749
|
type: "curator_compliance",
|
|
@@ -48772,7 +48885,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, _knowled
|
|
|
48772
48885
|
created_at: now,
|
|
48773
48886
|
updated_at: now,
|
|
48774
48887
|
auto_generated: true,
|
|
48775
|
-
project_name:
|
|
48888
|
+
project_name: path19.basename(directory)
|
|
48776
48889
|
};
|
|
48777
48890
|
await appendKnowledge(knowledgePath, newEntry);
|
|
48778
48891
|
applied++;
|
|
@@ -48990,7 +49103,7 @@ function formatCurationSummary(summary) {
|
|
|
48990
49103
|
// src/commands/dark-matter.ts
|
|
48991
49104
|
init_knowledge_store();
|
|
48992
49105
|
init_co_change_analyzer();
|
|
48993
|
-
import
|
|
49106
|
+
import path21 from "path";
|
|
48994
49107
|
async function handleDarkMatterCommand(directory, args2) {
|
|
48995
49108
|
const options = {};
|
|
48996
49109
|
for (let i2 = 0;i2 < args2.length; i2++) {
|
|
@@ -49012,7 +49125,7 @@ async function handleDarkMatterCommand(directory, args2) {
|
|
|
49012
49125
|
const output = formatDarkMatterOutput(pairs);
|
|
49013
49126
|
if (pairs.length > 0) {
|
|
49014
49127
|
try {
|
|
49015
|
-
const projectName =
|
|
49128
|
+
const projectName = path21.basename(path21.resolve(directory));
|
|
49016
49129
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
49017
49130
|
if (entries.length > 0) {
|
|
49018
49131
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -49038,7 +49151,7 @@ init_utils2();
|
|
|
49038
49151
|
init_manager2();
|
|
49039
49152
|
import * as child_process3 from "child_process";
|
|
49040
49153
|
import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
|
|
49041
|
-
import
|
|
49154
|
+
import path22 from "path";
|
|
49042
49155
|
import { fileURLToPath } from "url";
|
|
49043
49156
|
function validateTaskDag(plan) {
|
|
49044
49157
|
const allTaskIds = new Set;
|
|
@@ -49335,7 +49448,7 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
49335
49448
|
};
|
|
49336
49449
|
}
|
|
49337
49450
|
async function checkConfigParseability(directory) {
|
|
49338
|
-
const configPath =
|
|
49451
|
+
const configPath = path22.join(directory, ".opencode/opencode-swarm.json");
|
|
49339
49452
|
if (!existsSync10(configPath)) {
|
|
49340
49453
|
return {
|
|
49341
49454
|
name: "Config Parseability",
|
|
@@ -49382,15 +49495,15 @@ async function checkGrammarWasmFiles() {
|
|
|
49382
49495
|
"tree-sitter-ini.wasm",
|
|
49383
49496
|
"tree-sitter-regex.wasm"
|
|
49384
49497
|
];
|
|
49385
|
-
const thisDir =
|
|
49498
|
+
const thisDir = path22.dirname(fileURLToPath(import.meta.url));
|
|
49386
49499
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
|
|
49387
|
-
const grammarDir = isSource ?
|
|
49500
|
+
const grammarDir = isSource ? path22.join(thisDir, "..", "lang", "grammars") : path22.join(thisDir, "lang", "grammars");
|
|
49388
49501
|
const missing = [];
|
|
49389
|
-
if (!existsSync10(
|
|
49502
|
+
if (!existsSync10(path22.join(grammarDir, "tree-sitter.wasm"))) {
|
|
49390
49503
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
49391
49504
|
}
|
|
49392
49505
|
for (const file3 of grammarFiles) {
|
|
49393
|
-
if (!existsSync10(
|
|
49506
|
+
if (!existsSync10(path22.join(grammarDir, file3))) {
|
|
49394
49507
|
missing.push(file3);
|
|
49395
49508
|
}
|
|
49396
49509
|
}
|
|
@@ -49408,7 +49521,7 @@ async function checkGrammarWasmFiles() {
|
|
|
49408
49521
|
};
|
|
49409
49522
|
}
|
|
49410
49523
|
async function checkCheckpointManifest(directory) {
|
|
49411
|
-
const manifestPath =
|
|
49524
|
+
const manifestPath = path22.join(directory, ".swarm/checkpoints.json");
|
|
49412
49525
|
if (!existsSync10(manifestPath)) {
|
|
49413
49526
|
return {
|
|
49414
49527
|
name: "Checkpoint Manifest",
|
|
@@ -49460,7 +49573,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
49460
49573
|
}
|
|
49461
49574
|
}
|
|
49462
49575
|
async function checkEventStreamIntegrity(directory) {
|
|
49463
|
-
const eventsPath =
|
|
49576
|
+
const eventsPath = path22.join(directory, ".swarm/events.jsonl");
|
|
49464
49577
|
if (!existsSync10(eventsPath)) {
|
|
49465
49578
|
return {
|
|
49466
49579
|
name: "Event Stream",
|
|
@@ -49501,7 +49614,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
49501
49614
|
}
|
|
49502
49615
|
}
|
|
49503
49616
|
async function checkSteeringDirectives(directory) {
|
|
49504
|
-
const eventsPath =
|
|
49617
|
+
const eventsPath = path22.join(directory, ".swarm/events.jsonl");
|
|
49505
49618
|
if (!existsSync10(eventsPath)) {
|
|
49506
49619
|
return {
|
|
49507
49620
|
name: "Steering Directives",
|
|
@@ -49557,7 +49670,7 @@ async function checkCurator(directory) {
|
|
|
49557
49670
|
detail: "Disabled (enable via curator.enabled)"
|
|
49558
49671
|
};
|
|
49559
49672
|
}
|
|
49560
|
-
const summaryPath =
|
|
49673
|
+
const summaryPath = path22.join(directory, ".swarm/curator-summary.json");
|
|
49561
49674
|
if (!existsSync10(summaryPath)) {
|
|
49562
49675
|
return {
|
|
49563
49676
|
name: "Curator",
|
|
@@ -50459,10 +50572,10 @@ init_knowledge_store();
|
|
|
50459
50572
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
50460
50573
|
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
50461
50574
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
50462
|
-
import * as
|
|
50575
|
+
import * as path24 from "path";
|
|
50463
50576
|
async function migrateContextToKnowledge(directory, config3) {
|
|
50464
|
-
const sentinelPath =
|
|
50465
|
-
const contextPath =
|
|
50577
|
+
const sentinelPath = path24.join(directory, ".swarm", ".knowledge-migrated");
|
|
50578
|
+
const contextPath = path24.join(directory, ".swarm", "context.md");
|
|
50466
50579
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
50467
50580
|
if (existsSync12(sentinelPath)) {
|
|
50468
50581
|
return {
|
|
@@ -50658,7 +50771,7 @@ function truncateLesson(text) {
|
|
|
50658
50771
|
return `${text.slice(0, 277)}...`;
|
|
50659
50772
|
}
|
|
50660
50773
|
function inferProjectName(directory) {
|
|
50661
|
-
const packageJsonPath =
|
|
50774
|
+
const packageJsonPath = path24.join(directory, "package.json");
|
|
50662
50775
|
if (existsSync12(packageJsonPath)) {
|
|
50663
50776
|
try {
|
|
50664
50777
|
const pkg = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
|
|
@@ -50667,7 +50780,7 @@ function inferProjectName(directory) {
|
|
|
50667
50780
|
}
|
|
50668
50781
|
} catch {}
|
|
50669
50782
|
}
|
|
50670
|
-
return
|
|
50783
|
+
return path24.basename(directory);
|
|
50671
50784
|
}
|
|
50672
50785
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
50673
50786
|
const sentinel = {
|
|
@@ -50679,7 +50792,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
50679
50792
|
schema_version: 1,
|
|
50680
50793
|
migration_tool: "knowledge-migrator.ts"
|
|
50681
50794
|
};
|
|
50682
|
-
await mkdir4(
|
|
50795
|
+
await mkdir4(path24.dirname(sentinelPath), { recursive: true });
|
|
50683
50796
|
await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
50684
50797
|
}
|
|
50685
50798
|
|
|
@@ -50919,7 +51032,7 @@ init_preflight_service();
|
|
|
50919
51032
|
// src/knowledge/hive-promoter.ts
|
|
50920
51033
|
import * as fs20 from "fs";
|
|
50921
51034
|
import * as os6 from "os";
|
|
50922
|
-
import * as
|
|
51035
|
+
import * as path31 from "path";
|
|
50923
51036
|
var DANGEROUS_PATTERNS = [
|
|
50924
51037
|
[/rm\s+-rf/, "rm\\s+-rf"],
|
|
50925
51038
|
[/:\s*!\s*\|/, ":\\s*!\\s*\\|"],
|
|
@@ -50965,13 +51078,13 @@ function getHiveFilePath() {
|
|
|
50965
51078
|
const home = os6.homedir();
|
|
50966
51079
|
let dataDir;
|
|
50967
51080
|
if (platform === "win32") {
|
|
50968
|
-
dataDir =
|
|
51081
|
+
dataDir = path31.join(process.env.LOCALAPPDATA || path31.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
50969
51082
|
} else if (platform === "darwin") {
|
|
50970
|
-
dataDir =
|
|
51083
|
+
dataDir = path31.join(home, "Library", "Application Support", "opencode-swarm");
|
|
50971
51084
|
} else {
|
|
50972
|
-
dataDir =
|
|
51085
|
+
dataDir = path31.join(process.env.XDG_DATA_HOME || path31.join(home, ".local", "share"), "opencode-swarm");
|
|
50973
51086
|
}
|
|
50974
|
-
return
|
|
51087
|
+
return path31.join(dataDir, "hive-knowledge.jsonl");
|
|
50975
51088
|
}
|
|
50976
51089
|
async function promoteToHive(_directory, lesson, category) {
|
|
50977
51090
|
const trimmed = (lesson ?? "").trim();
|
|
@@ -50983,7 +51096,7 @@ async function promoteToHive(_directory, lesson, category) {
|
|
|
50983
51096
|
throw new Error(`Lesson rejected by validator: ${validation.reason}`);
|
|
50984
51097
|
}
|
|
50985
51098
|
const hivePath = getHiveFilePath();
|
|
50986
|
-
const hiveDir =
|
|
51099
|
+
const hiveDir = path31.dirname(hivePath);
|
|
50987
51100
|
if (!fs20.existsSync(hiveDir)) {
|
|
50988
51101
|
fs20.mkdirSync(hiveDir, { recursive: true });
|
|
50989
51102
|
}
|
|
@@ -51005,7 +51118,7 @@ async function promoteToHive(_directory, lesson, category) {
|
|
|
51005
51118
|
return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
|
|
51006
51119
|
}
|
|
51007
51120
|
async function promoteFromSwarm(directory, lessonId) {
|
|
51008
|
-
const knowledgePath =
|
|
51121
|
+
const knowledgePath = path31.join(directory, ".swarm", "knowledge.jsonl");
|
|
51009
51122
|
const entries = [];
|
|
51010
51123
|
if (fs20.existsSync(knowledgePath)) {
|
|
51011
51124
|
const content = fs20.readFileSync(knowledgePath, "utf-8");
|
|
@@ -51032,7 +51145,7 @@ async function promoteFromSwarm(directory, lessonId) {
|
|
|
51032
51145
|
throw new Error(`Lesson rejected by validator: ${validation.reason}`);
|
|
51033
51146
|
}
|
|
51034
51147
|
const hivePath = getHiveFilePath();
|
|
51035
|
-
const hiveDir =
|
|
51148
|
+
const hiveDir = path31.dirname(hivePath);
|
|
51036
51149
|
if (!fs20.existsSync(hiveDir)) {
|
|
51037
51150
|
fs20.mkdirSync(hiveDir, { recursive: true });
|
|
51038
51151
|
}
|
|
@@ -51163,7 +51276,7 @@ async function handleResetCommand(directory, args2) {
|
|
|
51163
51276
|
// src/commands/reset-session.ts
|
|
51164
51277
|
init_utils2();
|
|
51165
51278
|
import * as fs22 from "fs";
|
|
51166
|
-
import * as
|
|
51279
|
+
import * as path32 from "path";
|
|
51167
51280
|
async function handleResetSessionCommand(directory, _args) {
|
|
51168
51281
|
const results = [];
|
|
51169
51282
|
try {
|
|
@@ -51178,13 +51291,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
51178
51291
|
results.push("\u274C Failed to delete state.json");
|
|
51179
51292
|
}
|
|
51180
51293
|
try {
|
|
51181
|
-
const sessionDir =
|
|
51294
|
+
const sessionDir = path32.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
51182
51295
|
if (fs22.existsSync(sessionDir)) {
|
|
51183
51296
|
const files = fs22.readdirSync(sessionDir);
|
|
51184
51297
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
51185
51298
|
let deletedCount = 0;
|
|
51186
51299
|
for (const file3 of otherFiles) {
|
|
51187
|
-
const filePath =
|
|
51300
|
+
const filePath = path32.join(sessionDir, file3);
|
|
51188
51301
|
if (fs22.lstatSync(filePath).isFile()) {
|
|
51189
51302
|
fs22.unlinkSync(filePath);
|
|
51190
51303
|
deletedCount++;
|
|
@@ -51215,7 +51328,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
51215
51328
|
init_utils2();
|
|
51216
51329
|
init_utils();
|
|
51217
51330
|
import { mkdirSync as mkdirSync11, readdirSync as readdirSync8, renameSync as renameSync8, rmSync as rmSync3, statSync as statSync8 } from "fs";
|
|
51218
|
-
import * as
|
|
51331
|
+
import * as path33 from "path";
|
|
51219
51332
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
51220
51333
|
function sanitizeSummaryId(id) {
|
|
51221
51334
|
if (!id || id.length === 0) {
|
|
@@ -51250,9 +51363,9 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
51250
51363
|
if (serializedSize > maxStoredBytes) {
|
|
51251
51364
|
throw new Error(`Summary entry size (${serializedSize} bytes) exceeds maximum (${maxStoredBytes} bytes)`);
|
|
51252
51365
|
}
|
|
51253
|
-
const relativePath =
|
|
51366
|
+
const relativePath = path33.join("summaries", `${sanitizedId}.json`);
|
|
51254
51367
|
const summaryPath = validateSwarmPath(directory, relativePath);
|
|
51255
|
-
const summaryDir =
|
|
51368
|
+
const summaryDir = path33.dirname(summaryPath);
|
|
51256
51369
|
const entry = {
|
|
51257
51370
|
id: sanitizedId,
|
|
51258
51371
|
summaryText,
|
|
@@ -51262,7 +51375,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
51262
51375
|
};
|
|
51263
51376
|
const entryJson = JSON.stringify(entry);
|
|
51264
51377
|
mkdirSync11(summaryDir, { recursive: true });
|
|
51265
|
-
const tempPath =
|
|
51378
|
+
const tempPath = path33.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
|
|
51266
51379
|
try {
|
|
51267
51380
|
await Bun.write(tempPath, entryJson);
|
|
51268
51381
|
renameSync8(tempPath, summaryPath);
|
|
@@ -51275,7 +51388,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
51275
51388
|
}
|
|
51276
51389
|
async function loadFullOutput(directory, id) {
|
|
51277
51390
|
const sanitizedId = sanitizeSummaryId(id);
|
|
51278
|
-
const relativePath =
|
|
51391
|
+
const relativePath = path33.join("summaries", `${sanitizedId}.json`);
|
|
51279
51392
|
validateSwarmPath(directory, relativePath);
|
|
51280
51393
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
51281
51394
|
if (content === null) {
|
|
@@ -51329,7 +51442,7 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
|
51329
51442
|
// src/commands/rollback.ts
|
|
51330
51443
|
init_utils2();
|
|
51331
51444
|
import * as fs23 from "fs";
|
|
51332
|
-
import * as
|
|
51445
|
+
import * as path34 from "path";
|
|
51333
51446
|
async function handleRollbackCommand(directory, args2) {
|
|
51334
51447
|
const phaseArg = args2[0];
|
|
51335
51448
|
if (!phaseArg) {
|
|
@@ -51387,8 +51500,8 @@ async function handleRollbackCommand(directory, args2) {
|
|
|
51387
51500
|
const successes = [];
|
|
51388
51501
|
const failures = [];
|
|
51389
51502
|
for (const file3 of checkpointFiles) {
|
|
51390
|
-
const src =
|
|
51391
|
-
const dest =
|
|
51503
|
+
const src = path34.join(checkpointDir, file3);
|
|
51504
|
+
const dest = path34.join(swarmDir, file3);
|
|
51392
51505
|
try {
|
|
51393
51506
|
fs23.cpSync(src, dest, { recursive: true, force: true });
|
|
51394
51507
|
successes.push(file3);
|
|
@@ -51452,9 +51565,9 @@ async function handleSimulateCommand(directory, args2) {
|
|
|
51452
51565
|
const report = reportLines.filter(Boolean).join(`
|
|
51453
51566
|
`);
|
|
51454
51567
|
const fs24 = await import("fs/promises");
|
|
51455
|
-
const
|
|
51456
|
-
const reportPath =
|
|
51457
|
-
await fs24.mkdir(
|
|
51568
|
+
const path35 = await import("path");
|
|
51569
|
+
const reportPath = path35.join(directory, ".swarm", "simulate-report.md");
|
|
51570
|
+
await fs24.mkdir(path35.dirname(reportPath), { recursive: true });
|
|
51458
51571
|
await fs24.writeFile(reportPath, report, "utf-8");
|
|
51459
51572
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
51460
51573
|
}
|
|
@@ -51813,7 +51926,7 @@ init_manager2();
|
|
|
51813
51926
|
|
|
51814
51927
|
// src/services/compaction-service.ts
|
|
51815
51928
|
import * as fs24 from "fs";
|
|
51816
|
-
import * as
|
|
51929
|
+
import * as path35 from "path";
|
|
51817
51930
|
function makeInitialState() {
|
|
51818
51931
|
return {
|
|
51819
51932
|
lastObservationAt: 0,
|
|
@@ -51836,7 +51949,7 @@ function getSessionState(sessionId) {
|
|
|
51836
51949
|
}
|
|
51837
51950
|
function appendSnapshot(directory, tier, budgetPct, message) {
|
|
51838
51951
|
try {
|
|
51839
|
-
const snapshotPath =
|
|
51952
|
+
const snapshotPath = path35.join(directory, ".swarm", "context-snapshot.md");
|
|
51840
51953
|
const timestamp = new Date().toISOString();
|
|
51841
51954
|
const entry = `
|
|
51842
51955
|
## [${tier.toUpperCase()}] ${timestamp} \u2014 ${budgetPct.toFixed(1)}% used
|
|
@@ -52567,11 +52680,11 @@ async function doFlush(directory) {
|
|
|
52567
52680
|
const activitySection = renderActivitySection();
|
|
52568
52681
|
const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
|
|
52569
52682
|
const flushedCount = swarmState.pendingEvents;
|
|
52570
|
-
const
|
|
52571
|
-
const tempPath = `${
|
|
52683
|
+
const path36 = nodePath2.join(directory, ".swarm", "context.md");
|
|
52684
|
+
const tempPath = `${path36}.tmp`;
|
|
52572
52685
|
try {
|
|
52573
52686
|
await Bun.write(tempPath, updated);
|
|
52574
|
-
renameSync9(tempPath,
|
|
52687
|
+
renameSync9(tempPath, path36);
|
|
52575
52688
|
} catch (writeError) {
|
|
52576
52689
|
try {
|
|
52577
52690
|
unlinkSync4(tempPath);
|
|
@@ -53248,7 +53361,7 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
|
|
|
53248
53361
|
// src/hooks/delegation-gate.ts
|
|
53249
53362
|
init_schema();
|
|
53250
53363
|
import * as fs26 from "fs";
|
|
53251
|
-
import * as
|
|
53364
|
+
import * as path38 from "path";
|
|
53252
53365
|
|
|
53253
53366
|
// src/parallel/review-router.ts
|
|
53254
53367
|
async function computeComplexity(directory, changedFiles) {
|
|
@@ -53261,8 +53374,8 @@ async function computeComplexity(directory, changedFiles) {
|
|
|
53261
53374
|
}
|
|
53262
53375
|
try {
|
|
53263
53376
|
const fs26 = await import("fs");
|
|
53264
|
-
const
|
|
53265
|
-
const filePath =
|
|
53377
|
+
const path36 = await import("path");
|
|
53378
|
+
const filePath = path36.join(directory, file3);
|
|
53266
53379
|
if (!fs26.existsSync(filePath)) {
|
|
53267
53380
|
continue;
|
|
53268
53381
|
}
|
|
@@ -53314,7 +53427,7 @@ function shouldParallelizeReview(routing) {
|
|
|
53314
53427
|
init_telemetry();
|
|
53315
53428
|
|
|
53316
53429
|
// src/hooks/guardrails.ts
|
|
53317
|
-
import * as
|
|
53430
|
+
import * as path36 from "path";
|
|
53318
53431
|
init_constants();
|
|
53319
53432
|
init_schema();
|
|
53320
53433
|
|
|
@@ -53478,10 +53591,10 @@ function isArchitect(sessionId) {
|
|
|
53478
53591
|
function isOutsideSwarmDir(filePath, directory) {
|
|
53479
53592
|
if (!filePath)
|
|
53480
53593
|
return false;
|
|
53481
|
-
const swarmDir =
|
|
53482
|
-
const resolved =
|
|
53483
|
-
const relative5 =
|
|
53484
|
-
return relative5.startsWith("..") ||
|
|
53594
|
+
const swarmDir = path36.resolve(directory, ".swarm");
|
|
53595
|
+
const resolved = path36.resolve(directory, filePath);
|
|
53596
|
+
const relative5 = path36.relative(swarmDir, resolved);
|
|
53597
|
+
return relative5.startsWith("..") || path36.isAbsolute(relative5);
|
|
53485
53598
|
}
|
|
53486
53599
|
function isSourceCodePath(filePath) {
|
|
53487
53600
|
if (!filePath)
|
|
@@ -53549,16 +53662,16 @@ function getCurrentTaskId(sessionId) {
|
|
|
53549
53662
|
}
|
|
53550
53663
|
function isInDeclaredScope(filePath, scopeEntries, cwd) {
|
|
53551
53664
|
const dir = cwd ?? process.cwd();
|
|
53552
|
-
const resolvedFile =
|
|
53665
|
+
const resolvedFile = path36.resolve(dir, filePath);
|
|
53553
53666
|
return scopeEntries.some((scope) => {
|
|
53554
|
-
const resolvedScope =
|
|
53667
|
+
const resolvedScope = path36.resolve(dir, scope);
|
|
53555
53668
|
if (resolvedFile === resolvedScope)
|
|
53556
53669
|
return true;
|
|
53557
|
-
const rel =
|
|
53558
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
53670
|
+
const rel = path36.relative(resolvedScope, resolvedFile);
|
|
53671
|
+
return rel.length > 0 && !rel.startsWith("..") && !path36.isAbsolute(rel);
|
|
53559
53672
|
});
|
|
53560
53673
|
}
|
|
53561
|
-
function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
53674
|
+
function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityConfig) {
|
|
53562
53675
|
let guardrailsConfig;
|
|
53563
53676
|
if (directory && typeof directory === "object" && "enabled" in directory) {
|
|
53564
53677
|
console.warn("[guardrails] Legacy call without directory, falling back to process.cwd()");
|
|
@@ -53576,6 +53689,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
53576
53689
|
messagesTransform: async () => {}
|
|
53577
53690
|
};
|
|
53578
53691
|
}
|
|
53692
|
+
const precomputedAuthorityRules = buildEffectiveRules(authorityConfig);
|
|
53579
53693
|
const cfg = guardrailsConfig;
|
|
53580
53694
|
const requiredQaGates = cfg.qa_gates?.required_tools ?? [
|
|
53581
53695
|
"diff",
|
|
@@ -53670,7 +53784,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
53670
53784
|
if (typeof delegTargetPath === "string" && delegTargetPath.length > 0) {
|
|
53671
53785
|
const agentName = swarmState.activeAgent.get(sessionID) ?? "unknown";
|
|
53672
53786
|
const cwd = effectiveDirectory;
|
|
53673
|
-
const authorityCheck =
|
|
53787
|
+
const authorityCheck = checkFileAuthorityWithRules(agentName, delegTargetPath, cwd, precomputedAuthorityRules);
|
|
53674
53788
|
if (!authorityCheck.allowed) {
|
|
53675
53789
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${delegTargetPath}". Reason: ${authorityCheck.reason}`);
|
|
53676
53790
|
}
|
|
@@ -53679,6 +53793,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
53679
53793
|
}
|
|
53680
53794
|
}
|
|
53681
53795
|
}
|
|
53796
|
+
if (tool3 === "apply_patch" || tool3 === "patch") {
|
|
53797
|
+
const agentName = swarmState.activeAgent.get(sessionID) ?? "unknown";
|
|
53798
|
+
const cwd = effectiveDirectory;
|
|
53799
|
+
for (const p of extractPatchTargetPaths(tool3, args2)) {
|
|
53800
|
+
const authorityCheck = checkFileAuthorityWithRules(agentName, p, cwd, precomputedAuthorityRules);
|
|
53801
|
+
if (!authorityCheck.allowed) {
|
|
53802
|
+
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${p}" (via patch). Reason: ${authorityCheck.reason}`);
|
|
53803
|
+
}
|
|
53804
|
+
if (!currentSession.modifiedFilesThisCoderTask.includes(p)) {
|
|
53805
|
+
currentSession.modifiedFilesThisCoderTask.push(p);
|
|
53806
|
+
}
|
|
53807
|
+
}
|
|
53808
|
+
}
|
|
53682
53809
|
} else if (isArchitect(sessionID)) {
|
|
53683
53810
|
const coderDelegArgs = args2;
|
|
53684
53811
|
const rawSubagentType = coderDelegArgs?.subagent_type;
|
|
@@ -53747,84 +53874,90 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
53747
53874
|
}
|
|
53748
53875
|
}
|
|
53749
53876
|
}
|
|
53877
|
+
function extractPatchTargetPaths(tool3, args2) {
|
|
53878
|
+
if (tool3 !== "apply_patch" && tool3 !== "patch")
|
|
53879
|
+
return [];
|
|
53880
|
+
const toolArgs = args2;
|
|
53881
|
+
const patchText = toolArgs?.input ?? toolArgs?.patch ?? (Array.isArray(toolArgs?.cmd) ? toolArgs.cmd[1] : undefined);
|
|
53882
|
+
if (typeof patchText !== "string")
|
|
53883
|
+
return [];
|
|
53884
|
+
if (patchText.length > 1e6) {
|
|
53885
|
+
throw new Error("WRITE BLOCKED: Patch payload exceeds 1 MB \u2014 authority cannot be verified for all modified paths. Split into smaller patches.");
|
|
53886
|
+
}
|
|
53887
|
+
const paths = new Set;
|
|
53888
|
+
const patchPathPattern = /\*\*\*\s+(?:Update|Add|Delete)\s+File:\s*(.+)/gi;
|
|
53889
|
+
const diffPathPattern = /\+\+\+\s+b\/(.+)/gm;
|
|
53890
|
+
const gitDiffPathPattern = /^diff --git a\/(.+?) b\/(.+?)$/gm;
|
|
53891
|
+
const minusPathPattern = /^---\s+a\/(.+)$/gm;
|
|
53892
|
+
const traditionalMinusPattern = /^---\s+([^\s].+?)(?:\t.*)?$/gm;
|
|
53893
|
+
const traditionalPlusPattern = /^\+\+\+\s+([^\s].+?)(?:\t.*)?$/gm;
|
|
53894
|
+
for (const match of patchText.matchAll(patchPathPattern))
|
|
53895
|
+
paths.add(match[1].trim());
|
|
53896
|
+
for (const match of patchText.matchAll(diffPathPattern)) {
|
|
53897
|
+
const p = match[1].trim();
|
|
53898
|
+
if (p !== "/dev/null")
|
|
53899
|
+
paths.add(p);
|
|
53900
|
+
}
|
|
53901
|
+
for (const match of patchText.matchAll(gitDiffPathPattern)) {
|
|
53902
|
+
const aPath = match[1].trim();
|
|
53903
|
+
const bPath = match[2].trim();
|
|
53904
|
+
if (aPath !== "/dev/null")
|
|
53905
|
+
paths.add(aPath);
|
|
53906
|
+
if (bPath !== "/dev/null")
|
|
53907
|
+
paths.add(bPath);
|
|
53908
|
+
}
|
|
53909
|
+
for (const match of patchText.matchAll(minusPathPattern)) {
|
|
53910
|
+
const p = match[1].trim();
|
|
53911
|
+
if (p !== "/dev/null")
|
|
53912
|
+
paths.add(p);
|
|
53913
|
+
}
|
|
53914
|
+
for (const match of patchText.matchAll(traditionalMinusPattern)) {
|
|
53915
|
+
const p = match[1].trim();
|
|
53916
|
+
if (p !== "/dev/null" && !p.startsWith("a/") && !p.startsWith("b/"))
|
|
53917
|
+
paths.add(p);
|
|
53918
|
+
}
|
|
53919
|
+
for (const match of patchText.matchAll(traditionalPlusPattern)) {
|
|
53920
|
+
const p = match[1].trim();
|
|
53921
|
+
if (p !== "/dev/null" && !p.startsWith("a/") && !p.startsWith("b/"))
|
|
53922
|
+
paths.add(p);
|
|
53923
|
+
}
|
|
53924
|
+
return Array.from(paths);
|
|
53925
|
+
}
|
|
53750
53926
|
function handlePlanAndScopeProtection(sessionID, tool3, args2) {
|
|
53751
53927
|
const toolArgs = args2;
|
|
53752
53928
|
const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
|
|
53753
53929
|
if (typeof targetPath === "string" && targetPath.length > 0) {
|
|
53754
|
-
const resolvedTarget =
|
|
53755
|
-
const planMdPath =
|
|
53756
|
-
const planJsonPath =
|
|
53930
|
+
const resolvedTarget = path36.resolve(effectiveDirectory, targetPath).toLowerCase();
|
|
53931
|
+
const planMdPath = path36.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
|
|
53932
|
+
const planJsonPath = path36.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
|
|
53757
53933
|
if (resolvedTarget === planMdPath || resolvedTarget === planJsonPath) {
|
|
53758
53934
|
throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
|
|
53759
53935
|
}
|
|
53760
53936
|
}
|
|
53761
53937
|
if (!targetPath && (tool3 === "apply_patch" || tool3 === "patch")) {
|
|
53762
|
-
const
|
|
53763
|
-
|
|
53764
|
-
const
|
|
53765
|
-
const
|
|
53766
|
-
|
|
53767
|
-
|
|
53768
|
-
|
|
53769
|
-
|
|
53770
|
-
|
|
53771
|
-
|
|
53772
|
-
|
|
53773
|
-
|
|
53774
|
-
|
|
53775
|
-
|
|
53776
|
-
|
|
53777
|
-
|
|
53778
|
-
|
|
53779
|
-
if (aPath !== "/dev/null")
|
|
53780
|
-
paths.add(aPath);
|
|
53781
|
-
if (bPath !== "/dev/null")
|
|
53782
|
-
paths.add(bPath);
|
|
53783
|
-
}
|
|
53784
|
-
const minusPathPattern = /^---\s+a\/(.+)$/gm;
|
|
53785
|
-
for (const match of patchText.matchAll(minusPathPattern)) {
|
|
53786
|
-
const p = match[1].trim();
|
|
53787
|
-
if (p !== "/dev/null")
|
|
53788
|
-
paths.add(p);
|
|
53789
|
-
}
|
|
53790
|
-
const traditionalMinusPattern = /^---\s+([^\s].+?)(?:\t.*)?$/gm;
|
|
53791
|
-
const traditionalPlusPattern = /^\+\+\+\s+([^\s].+?)(?:\t.*)?$/gm;
|
|
53792
|
-
for (const match of patchText.matchAll(traditionalMinusPattern)) {
|
|
53793
|
-
const p = match[1].trim();
|
|
53794
|
-
if (p !== "/dev/null" && !p.startsWith("a/") && !p.startsWith("b/")) {
|
|
53795
|
-
paths.add(p);
|
|
53796
|
-
}
|
|
53797
|
-
}
|
|
53798
|
-
for (const match of patchText.matchAll(traditionalPlusPattern)) {
|
|
53799
|
-
const p = match[1].trim();
|
|
53800
|
-
if (p !== "/dev/null" && !p.startsWith("a/") && !p.startsWith("b/")) {
|
|
53801
|
-
paths.add(p);
|
|
53802
|
-
}
|
|
53803
|
-
}
|
|
53804
|
-
for (const p of paths) {
|
|
53805
|
-
const resolvedP = path35.resolve(effectiveDirectory, p);
|
|
53806
|
-
const planMdPath = path35.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
|
|
53807
|
-
const planJsonPath = path35.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
|
|
53808
|
-
if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
|
|
53809
|
-
throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
|
|
53810
|
-
}
|
|
53811
|
-
if (isOutsideSwarmDir(p, effectiveDirectory) && (isSourceCodePath(p) || hasTraversalSegments(p))) {
|
|
53812
|
-
const session = swarmState.agentSessions.get(sessionID);
|
|
53813
|
-
if (session) {
|
|
53814
|
-
session.architectWriteCount++;
|
|
53815
|
-
warn("Architect direct code edit detected via apply_patch", {
|
|
53816
|
-
tool: tool3,
|
|
53817
|
-
sessionID,
|
|
53818
|
-
targetPath: p,
|
|
53819
|
-
writeCount: session.architectWriteCount
|
|
53820
|
-
});
|
|
53821
|
-
}
|
|
53822
|
-
break;
|
|
53938
|
+
for (const p of extractPatchTargetPaths(tool3, args2)) {
|
|
53939
|
+
const resolvedP = path36.resolve(effectiveDirectory, p);
|
|
53940
|
+
const planMdPath = path36.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
|
|
53941
|
+
const planJsonPath = path36.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
|
|
53942
|
+
if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
|
|
53943
|
+
throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
|
|
53944
|
+
}
|
|
53945
|
+
if (isOutsideSwarmDir(p, effectiveDirectory) && (isSourceCodePath(p) || hasTraversalSegments(p))) {
|
|
53946
|
+
const session = swarmState.agentSessions.get(sessionID);
|
|
53947
|
+
if (session) {
|
|
53948
|
+
session.architectWriteCount++;
|
|
53949
|
+
warn("Architect direct code edit detected via apply_patch", {
|
|
53950
|
+
tool: tool3,
|
|
53951
|
+
sessionID,
|
|
53952
|
+
targetPath: p,
|
|
53953
|
+
writeCount: session.architectWriteCount
|
|
53954
|
+
});
|
|
53823
53955
|
}
|
|
53956
|
+
break;
|
|
53824
53957
|
}
|
|
53825
53958
|
}
|
|
53826
53959
|
}
|
|
53827
|
-
if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(
|
|
53960
|
+
if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(path36.relative(effectiveDirectory, path36.resolve(effectiveDirectory, targetPath)))) {
|
|
53828
53961
|
const session = swarmState.agentSessions.get(sessionID);
|
|
53829
53962
|
if (session) {
|
|
53830
53963
|
session.architectWriteCount++;
|
|
@@ -53917,6 +54050,24 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
53917
54050
|
handleTestSuiteBlocking(input.tool, output.args);
|
|
53918
54051
|
if (isArchitect(input.sessionID) && isWriteTool(input.tool)) {
|
|
53919
54052
|
handlePlanAndScopeProtection(input.sessionID, input.tool, output.args);
|
|
54053
|
+
const toolArgs = output.args;
|
|
54054
|
+
const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
|
|
54055
|
+
if (typeof targetPath === "string" && targetPath.length > 0) {
|
|
54056
|
+
const agentName = swarmState.activeAgent.get(input.sessionID) ?? "architect";
|
|
54057
|
+
const authorityCheck = checkFileAuthorityWithRules(agentName, targetPath, effectiveDirectory, precomputedAuthorityRules);
|
|
54058
|
+
if (!authorityCheck.allowed) {
|
|
54059
|
+
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${targetPath}". Reason: ${authorityCheck.reason}`);
|
|
54060
|
+
}
|
|
54061
|
+
}
|
|
54062
|
+
}
|
|
54063
|
+
if (input.tool === "apply_patch" || input.tool === "patch") {
|
|
54064
|
+
const agentName = swarmState.activeAgent.get(input.sessionID) ?? "architect";
|
|
54065
|
+
for (const p of extractPatchTargetPaths(input.tool, output.args)) {
|
|
54066
|
+
const authorityCheck = checkFileAuthorityWithRules(agentName, p, effectiveDirectory, precomputedAuthorityRules);
|
|
54067
|
+
if (!authorityCheck.allowed) {
|
|
54068
|
+
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${p}" (via patch). Reason: ${authorityCheck.reason}`);
|
|
54069
|
+
}
|
|
54070
|
+
}
|
|
53920
54071
|
}
|
|
53921
54072
|
const resolved = resolveSessionAndWindow(input.sessionID);
|
|
53922
54073
|
if (!resolved)
|
|
@@ -54411,7 +54562,7 @@ function hashArgs(args2) {
|
|
|
54411
54562
|
return 0;
|
|
54412
54563
|
}
|
|
54413
54564
|
}
|
|
54414
|
-
var
|
|
54565
|
+
var DEFAULT_AGENT_AUTHORITY_RULES = {
|
|
54415
54566
|
architect: {
|
|
54416
54567
|
blockedExact: [".swarm/plan.md", ".swarm/plan.json"],
|
|
54417
54568
|
blockedZones: ["generated"]
|
|
@@ -54452,12 +54603,38 @@ var AGENT_AUTHORITY_RULES = {
|
|
|
54452
54603
|
blockedZones: ["generated"]
|
|
54453
54604
|
}
|
|
54454
54605
|
};
|
|
54455
|
-
function
|
|
54606
|
+
function buildEffectiveRules(authorityConfig) {
|
|
54607
|
+
if (authorityConfig?.enabled === false || !authorityConfig?.rules) {
|
|
54608
|
+
return DEFAULT_AGENT_AUTHORITY_RULES;
|
|
54609
|
+
}
|
|
54610
|
+
const entries = Object.entries(authorityConfig.rules);
|
|
54611
|
+
if (entries.length === 0) {
|
|
54612
|
+
return DEFAULT_AGENT_AUTHORITY_RULES;
|
|
54613
|
+
}
|
|
54614
|
+
const merged = {
|
|
54615
|
+
...DEFAULT_AGENT_AUTHORITY_RULES
|
|
54616
|
+
};
|
|
54617
|
+
for (const [agent, userRule] of entries) {
|
|
54618
|
+
const normalizedRuleKey = agent.toLowerCase();
|
|
54619
|
+
const existing = merged[normalizedRuleKey] ?? {};
|
|
54620
|
+
merged[normalizedRuleKey] = {
|
|
54621
|
+
...existing,
|
|
54622
|
+
...userRule,
|
|
54623
|
+
blockedExact: userRule.blockedExact ?? existing.blockedExact,
|
|
54624
|
+
blockedPrefix: userRule.blockedPrefix ?? existing.blockedPrefix,
|
|
54625
|
+
allowedPrefix: userRule.allowedPrefix ?? existing.allowedPrefix,
|
|
54626
|
+
blockedZones: userRule.blockedZones ?? existing.blockedZones
|
|
54627
|
+
};
|
|
54628
|
+
}
|
|
54629
|
+
return merged;
|
|
54630
|
+
}
|
|
54631
|
+
function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules) {
|
|
54456
54632
|
const normalizedAgent = agentName.toLowerCase();
|
|
54633
|
+
const strippedAgent = stripKnownSwarmPrefix(agentName).toLowerCase();
|
|
54457
54634
|
const dir = cwd || process.cwd();
|
|
54458
|
-
const resolved =
|
|
54459
|
-
const normalizedPath =
|
|
54460
|
-
const rules =
|
|
54635
|
+
const resolved = path36.resolve(dir, filePath);
|
|
54636
|
+
const normalizedPath = path36.relative(dir, resolved).replace(/\\/g, "/");
|
|
54637
|
+
const rules = effectiveRules[normalizedAgent] ?? effectiveRules[strippedAgent];
|
|
54461
54638
|
if (!rules) {
|
|
54462
54639
|
return { allowed: false, reason: `Unknown agent: ${agentName}` };
|
|
54463
54640
|
}
|
|
@@ -54484,8 +54661,8 @@ function checkFileAuthority(agentName, filePath, cwd) {
|
|
|
54484
54661
|
}
|
|
54485
54662
|
}
|
|
54486
54663
|
}
|
|
54487
|
-
if (rules.allowedPrefix
|
|
54488
|
-
const isAllowed = rules.allowedPrefix.some((prefix) => normalizedPath.startsWith(prefix));
|
|
54664
|
+
if (rules.allowedPrefix != null) {
|
|
54665
|
+
const isAllowed = rules.allowedPrefix.length > 0 ? rules.allowedPrefix.some((prefix) => normalizedPath.startsWith(prefix)) : false;
|
|
54489
54666
|
if (!isAllowed) {
|
|
54490
54667
|
return {
|
|
54491
54668
|
allowed: false,
|
|
@@ -54538,10 +54715,10 @@ async function getEvidenceTaskId(session, directory) {
|
|
|
54538
54715
|
if (typeof directory !== "string" || directory.length === 0) {
|
|
54539
54716
|
return null;
|
|
54540
54717
|
}
|
|
54541
|
-
const resolvedDirectory =
|
|
54542
|
-
const planPath =
|
|
54543
|
-
const resolvedPlanPath =
|
|
54544
|
-
if (!resolvedPlanPath.startsWith(resolvedDirectory +
|
|
54718
|
+
const resolvedDirectory = path38.resolve(directory);
|
|
54719
|
+
const planPath = path38.join(resolvedDirectory, ".swarm", "plan.json");
|
|
54720
|
+
const resolvedPlanPath = path38.resolve(planPath);
|
|
54721
|
+
if (!resolvedPlanPath.startsWith(resolvedDirectory + path38.sep) && resolvedPlanPath !== resolvedDirectory) {
|
|
54545
54722
|
return null;
|
|
54546
54723
|
}
|
|
54547
54724
|
const planContent = await fs26.promises.readFile(resolvedPlanPath, "utf-8");
|
|
@@ -55269,7 +55446,7 @@ function consolidateSystemMessages(messages) {
|
|
|
55269
55446
|
// src/hooks/phase-monitor.ts
|
|
55270
55447
|
init_schema();
|
|
55271
55448
|
init_manager2();
|
|
55272
|
-
import * as
|
|
55449
|
+
import * as path40 from "path";
|
|
55273
55450
|
init_utils2();
|
|
55274
55451
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
55275
55452
|
let lastKnownPhase = null;
|
|
@@ -55290,9 +55467,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
|
|
|
55290
55467
|
const llmDelegate = delegateFactory?.(sessionId);
|
|
55291
55468
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
55292
55469
|
if (initResult.briefing) {
|
|
55293
|
-
const briefingPath =
|
|
55470
|
+
const briefingPath = path40.join(directory, ".swarm", "curator-briefing.md");
|
|
55294
55471
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
55295
|
-
await mkdir5(
|
|
55472
|
+
await mkdir5(path40.dirname(briefingPath), { recursive: true });
|
|
55296
55473
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
55297
55474
|
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
55298
55475
|
const initReceipt = buildApprovedReceipt2({
|
|
@@ -55426,14 +55603,14 @@ init_manager();
|
|
|
55426
55603
|
init_detector();
|
|
55427
55604
|
init_manager2();
|
|
55428
55605
|
import * as fs32 from "fs";
|
|
55429
|
-
import * as
|
|
55606
|
+
import * as path44 from "path";
|
|
55430
55607
|
|
|
55431
55608
|
// src/services/decision-drift-analyzer.ts
|
|
55432
55609
|
init_utils2();
|
|
55433
55610
|
init_manager2();
|
|
55434
55611
|
init_utils();
|
|
55435
55612
|
import * as fs29 from "fs";
|
|
55436
|
-
import * as
|
|
55613
|
+
import * as path41 from "path";
|
|
55437
55614
|
var DEFAULT_DRIFT_CONFIG = {
|
|
55438
55615
|
staleThresholdPhases: 1,
|
|
55439
55616
|
detectContradictions: true,
|
|
@@ -55587,7 +55764,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
55587
55764
|
currentPhase = legacyPhase;
|
|
55588
55765
|
}
|
|
55589
55766
|
}
|
|
55590
|
-
const contextPath =
|
|
55767
|
+
const contextPath = path41.join(directory, ".swarm", "context.md");
|
|
55591
55768
|
let contextContent = "";
|
|
55592
55769
|
try {
|
|
55593
55770
|
if (fs29.existsSync(contextPath)) {
|
|
@@ -55717,7 +55894,7 @@ init_utils();
|
|
|
55717
55894
|
init_constants();
|
|
55718
55895
|
init_schema();
|
|
55719
55896
|
import * as fs30 from "fs/promises";
|
|
55720
|
-
import * as
|
|
55897
|
+
import * as path42 from "path";
|
|
55721
55898
|
function safeGet(obj, key) {
|
|
55722
55899
|
if (!obj || !Object.hasOwn(obj, key))
|
|
55723
55900
|
return;
|
|
@@ -55931,9 +56108,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
55931
56108
|
let eventLogged = false;
|
|
55932
56109
|
let checkpointCreated = false;
|
|
55933
56110
|
try {
|
|
55934
|
-
const swarmDir =
|
|
56111
|
+
const swarmDir = path42.join(directory, ".swarm");
|
|
55935
56112
|
await fs30.mkdir(swarmDir, { recursive: true });
|
|
55936
|
-
const eventsPath =
|
|
56113
|
+
const eventsPath = path42.join(swarmDir, "events.jsonl");
|
|
55937
56114
|
await fs30.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
55938
56115
|
`);
|
|
55939
56116
|
eventLogged = true;
|
|
@@ -56330,7 +56507,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
56330
56507
|
await fs32.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
56331
56508
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
56332
56509
|
try {
|
|
56333
|
-
const projectName =
|
|
56510
|
+
const projectName = path44.basename(path44.resolve(directory));
|
|
56334
56511
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
56335
56512
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
56336
56513
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -57454,7 +57631,7 @@ function isReadTool(toolName) {
|
|
|
57454
57631
|
|
|
57455
57632
|
// src/hooks/incremental-verify.ts
|
|
57456
57633
|
import * as fs33 from "fs";
|
|
57457
|
-
import * as
|
|
57634
|
+
import * as path45 from "path";
|
|
57458
57635
|
|
|
57459
57636
|
// src/hooks/spawn-helper.ts
|
|
57460
57637
|
import * as child_process4 from "child_process";
|
|
@@ -57532,18 +57709,18 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
57532
57709
|
// src/hooks/incremental-verify.ts
|
|
57533
57710
|
var emittedSkipAdvisories = new Set;
|
|
57534
57711
|
function detectPackageManager(projectDir) {
|
|
57535
|
-
if (fs33.existsSync(
|
|
57712
|
+
if (fs33.existsSync(path45.join(projectDir, "bun.lockb")))
|
|
57536
57713
|
return "bun";
|
|
57537
|
-
if (fs33.existsSync(
|
|
57714
|
+
if (fs33.existsSync(path45.join(projectDir, "pnpm-lock.yaml")))
|
|
57538
57715
|
return "pnpm";
|
|
57539
|
-
if (fs33.existsSync(
|
|
57716
|
+
if (fs33.existsSync(path45.join(projectDir, "yarn.lock")))
|
|
57540
57717
|
return "yarn";
|
|
57541
|
-
if (fs33.existsSync(
|
|
57718
|
+
if (fs33.existsSync(path45.join(projectDir, "package-lock.json")))
|
|
57542
57719
|
return "npm";
|
|
57543
57720
|
return "bun";
|
|
57544
57721
|
}
|
|
57545
57722
|
function detectTypecheckCommand(projectDir) {
|
|
57546
|
-
const pkgPath =
|
|
57723
|
+
const pkgPath = path45.join(projectDir, "package.json");
|
|
57547
57724
|
if (fs33.existsSync(pkgPath)) {
|
|
57548
57725
|
try {
|
|
57549
57726
|
const pkg = JSON.parse(fs33.readFileSync(pkgPath, "utf8"));
|
|
@@ -57560,8 +57737,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
57560
57737
|
...pkg.dependencies,
|
|
57561
57738
|
...pkg.devDependencies
|
|
57562
57739
|
};
|
|
57563
|
-
if (!deps?.typescript && !fs33.existsSync(
|
|
57564
|
-
const hasTSMarkers = deps?.typescript || fs33.existsSync(
|
|
57740
|
+
if (!deps?.typescript && !fs33.existsSync(path45.join(projectDir, "tsconfig.json"))) {}
|
|
57741
|
+
const hasTSMarkers = deps?.typescript || fs33.existsSync(path45.join(projectDir, "tsconfig.json"));
|
|
57565
57742
|
if (hasTSMarkers) {
|
|
57566
57743
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
57567
57744
|
}
|
|
@@ -57569,13 +57746,13 @@ function detectTypecheckCommand(projectDir) {
|
|
|
57569
57746
|
return null;
|
|
57570
57747
|
}
|
|
57571
57748
|
}
|
|
57572
|
-
if (fs33.existsSync(
|
|
57749
|
+
if (fs33.existsSync(path45.join(projectDir, "go.mod"))) {
|
|
57573
57750
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
57574
57751
|
}
|
|
57575
|
-
if (fs33.existsSync(
|
|
57752
|
+
if (fs33.existsSync(path45.join(projectDir, "Cargo.toml"))) {
|
|
57576
57753
|
return { command: ["cargo", "check"], language: "rust" };
|
|
57577
57754
|
}
|
|
57578
|
-
if (fs33.existsSync(
|
|
57755
|
+
if (fs33.existsSync(path45.join(projectDir, "pyproject.toml")) || fs33.existsSync(path45.join(projectDir, "requirements.txt")) || fs33.existsSync(path45.join(projectDir, "setup.py"))) {
|
|
57579
57756
|
return { command: null, language: "python" };
|
|
57580
57757
|
}
|
|
57581
57758
|
try {
|
|
@@ -57876,7 +58053,7 @@ ${injectionText}`;
|
|
|
57876
58053
|
// src/hooks/scope-guard.ts
|
|
57877
58054
|
init_constants();
|
|
57878
58055
|
init_schema();
|
|
57879
|
-
import * as
|
|
58056
|
+
import * as path47 from "path";
|
|
57880
58057
|
var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
|
|
57881
58058
|
function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
57882
58059
|
const enabled = config3.enabled ?? true;
|
|
@@ -57928,13 +58105,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
57928
58105
|
}
|
|
57929
58106
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
57930
58107
|
const dir = directory ?? process.cwd();
|
|
57931
|
-
const resolvedFile =
|
|
58108
|
+
const resolvedFile = path47.resolve(dir, filePath);
|
|
57932
58109
|
return scopeEntries.some((scope) => {
|
|
57933
|
-
const resolvedScope =
|
|
58110
|
+
const resolvedScope = path47.resolve(dir, scope);
|
|
57934
58111
|
if (resolvedFile === resolvedScope)
|
|
57935
58112
|
return true;
|
|
57936
|
-
const rel =
|
|
57937
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
58113
|
+
const rel = path47.relative(resolvedScope, resolvedFile);
|
|
58114
|
+
return rel.length > 0 && !rel.startsWith("..") && !path47.isAbsolute(rel);
|
|
57938
58115
|
});
|
|
57939
58116
|
}
|
|
57940
58117
|
|
|
@@ -57984,7 +58161,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
57984
58161
|
|
|
57985
58162
|
// src/hooks/slop-detector.ts
|
|
57986
58163
|
import * as fs35 from "fs";
|
|
57987
|
-
import * as
|
|
58164
|
+
import * as path48 from "path";
|
|
57988
58165
|
var WRITE_EDIT_TOOLS = new Set([
|
|
57989
58166
|
"write",
|
|
57990
58167
|
"edit",
|
|
@@ -58034,7 +58211,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
58034
58211
|
break;
|
|
58035
58212
|
if (entry.isSymbolicLink())
|
|
58036
58213
|
continue;
|
|
58037
|
-
const full =
|
|
58214
|
+
const full = path48.join(dir, entry.name);
|
|
58038
58215
|
if (entry.isDirectory()) {
|
|
58039
58216
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
58040
58217
|
continue;
|
|
@@ -58049,7 +58226,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
58049
58226
|
return results;
|
|
58050
58227
|
}
|
|
58051
58228
|
function checkDeadExports(content, projectDir, startTime) {
|
|
58052
|
-
const hasPackageJson = fs35.existsSync(
|
|
58229
|
+
const hasPackageJson = fs35.existsSync(path48.join(projectDir, "package.json"));
|
|
58053
58230
|
if (!hasPackageJson)
|
|
58054
58231
|
return null;
|
|
58055
58232
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -58452,13 +58629,13 @@ init_telemetry();
|
|
|
58452
58629
|
init_tool();
|
|
58453
58630
|
init_create_tool();
|
|
58454
58631
|
import * as fs38 from "fs";
|
|
58455
|
-
import * as
|
|
58632
|
+
import * as path50 from "path";
|
|
58456
58633
|
|
|
58457
58634
|
// src/tools/symbols.ts
|
|
58458
58635
|
init_tool();
|
|
58459
58636
|
init_create_tool();
|
|
58460
58637
|
import * as fs37 from "fs";
|
|
58461
|
-
import * as
|
|
58638
|
+
import * as path49 from "path";
|
|
58462
58639
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
58463
58640
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
58464
58641
|
function containsWindowsAttacks(str) {
|
|
@@ -58475,11 +58652,11 @@ function containsWindowsAttacks(str) {
|
|
|
58475
58652
|
}
|
|
58476
58653
|
function isPathInWorkspace(filePath, workspace) {
|
|
58477
58654
|
try {
|
|
58478
|
-
const resolvedPath =
|
|
58655
|
+
const resolvedPath = path49.resolve(workspace, filePath);
|
|
58479
58656
|
const realWorkspace = fs37.realpathSync(workspace);
|
|
58480
58657
|
const realResolvedPath = fs37.realpathSync(resolvedPath);
|
|
58481
|
-
const relativePath =
|
|
58482
|
-
if (relativePath.startsWith("..") ||
|
|
58658
|
+
const relativePath = path49.relative(realWorkspace, realResolvedPath);
|
|
58659
|
+
if (relativePath.startsWith("..") || path49.isAbsolute(relativePath)) {
|
|
58483
58660
|
return false;
|
|
58484
58661
|
}
|
|
58485
58662
|
return true;
|
|
@@ -58491,7 +58668,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
58491
58668
|
return isPathInWorkspace(filePath, workspace);
|
|
58492
58669
|
}
|
|
58493
58670
|
function extractTSSymbols(filePath, cwd) {
|
|
58494
|
-
const fullPath =
|
|
58671
|
+
const fullPath = path49.join(cwd, filePath);
|
|
58495
58672
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
58496
58673
|
return [];
|
|
58497
58674
|
}
|
|
@@ -58643,7 +58820,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
58643
58820
|
});
|
|
58644
58821
|
}
|
|
58645
58822
|
function extractPythonSymbols(filePath, cwd) {
|
|
58646
|
-
const fullPath =
|
|
58823
|
+
const fullPath = path49.join(cwd, filePath);
|
|
58647
58824
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
58648
58825
|
return [];
|
|
58649
58826
|
}
|
|
@@ -58726,7 +58903,7 @@ var symbols = createSwarmTool({
|
|
|
58726
58903
|
}, null, 2);
|
|
58727
58904
|
}
|
|
58728
58905
|
const cwd = directory;
|
|
58729
|
-
const ext =
|
|
58906
|
+
const ext = path49.extname(file3);
|
|
58730
58907
|
if (containsControlChars(file3)) {
|
|
58731
58908
|
return JSON.stringify({
|
|
58732
58909
|
file: file3,
|
|
@@ -58802,14 +58979,14 @@ function containsWindowsAttacks2(str) {
|
|
|
58802
58979
|
}
|
|
58803
58980
|
function isPathInWorkspace2(filePath, workspace) {
|
|
58804
58981
|
try {
|
|
58805
|
-
const resolvedPath =
|
|
58982
|
+
const resolvedPath = path50.resolve(workspace, filePath);
|
|
58806
58983
|
if (!fs38.existsSync(resolvedPath)) {
|
|
58807
58984
|
return true;
|
|
58808
58985
|
}
|
|
58809
58986
|
const realWorkspace = fs38.realpathSync(workspace);
|
|
58810
58987
|
const realResolvedPath = fs38.realpathSync(resolvedPath);
|
|
58811
|
-
const relativePath =
|
|
58812
|
-
if (relativePath.startsWith("..") ||
|
|
58988
|
+
const relativePath = path50.relative(realWorkspace, realResolvedPath);
|
|
58989
|
+
if (relativePath.startsWith("..") || path50.isAbsolute(relativePath)) {
|
|
58813
58990
|
return false;
|
|
58814
58991
|
}
|
|
58815
58992
|
return true;
|
|
@@ -58818,7 +58995,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
58818
58995
|
}
|
|
58819
58996
|
}
|
|
58820
58997
|
function processFile(file3, cwd, exportedOnly) {
|
|
58821
|
-
const ext =
|
|
58998
|
+
const ext = path50.extname(file3);
|
|
58822
58999
|
if (containsControlChars(file3)) {
|
|
58823
59000
|
return {
|
|
58824
59001
|
file: file3,
|
|
@@ -58851,7 +59028,7 @@ function processFile(file3, cwd, exportedOnly) {
|
|
|
58851
59028
|
errorType: "path-outside-workspace"
|
|
58852
59029
|
};
|
|
58853
59030
|
}
|
|
58854
|
-
const fullPath =
|
|
59031
|
+
const fullPath = path50.join(cwd, file3);
|
|
58855
59032
|
if (!fs38.existsSync(fullPath)) {
|
|
58856
59033
|
return {
|
|
58857
59034
|
file: file3,
|
|
@@ -59142,7 +59319,7 @@ init_manager();
|
|
|
59142
59319
|
init_create_tool();
|
|
59143
59320
|
init_resolve_working_directory();
|
|
59144
59321
|
import * as fs39 from "fs";
|
|
59145
|
-
import * as
|
|
59322
|
+
import * as path51 from "path";
|
|
59146
59323
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
59147
59324
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
59148
59325
|
function isValidTaskId3(taskId) {
|
|
@@ -59159,9 +59336,9 @@ function isValidTaskId3(taskId) {
|
|
|
59159
59336
|
return TASK_ID_PATTERN2.test(taskId);
|
|
59160
59337
|
}
|
|
59161
59338
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
59162
|
-
const normalizedWorkspace =
|
|
59163
|
-
const swarmPath =
|
|
59164
|
-
const normalizedPath =
|
|
59339
|
+
const normalizedWorkspace = path51.resolve(workspaceRoot);
|
|
59340
|
+
const swarmPath = path51.join(normalizedWorkspace, ".swarm", "evidence");
|
|
59341
|
+
const normalizedPath = path51.resolve(filePath);
|
|
59165
59342
|
return normalizedPath.startsWith(swarmPath);
|
|
59166
59343
|
}
|
|
59167
59344
|
function readEvidenceFile(evidencePath) {
|
|
@@ -59242,7 +59419,7 @@ var check_gate_status = createSwarmTool({
|
|
|
59242
59419
|
};
|
|
59243
59420
|
return JSON.stringify(errorResult, null, 2);
|
|
59244
59421
|
}
|
|
59245
|
-
const evidencePath =
|
|
59422
|
+
const evidencePath = path51.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
59246
59423
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
59247
59424
|
const errorResult = {
|
|
59248
59425
|
taskId: taskIdInput,
|
|
@@ -59336,7 +59513,7 @@ init_co_change_analyzer();
|
|
|
59336
59513
|
init_dist();
|
|
59337
59514
|
init_utils2();
|
|
59338
59515
|
import * as fs40 from "fs";
|
|
59339
|
-
import * as
|
|
59516
|
+
import * as path52 from "path";
|
|
59340
59517
|
init_create_tool();
|
|
59341
59518
|
init_resolve_working_directory();
|
|
59342
59519
|
function extractMatches(regex, text) {
|
|
@@ -59490,10 +59667,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
59490
59667
|
let hasFileReadFailure = false;
|
|
59491
59668
|
for (const filePath of fileTargets) {
|
|
59492
59669
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
59493
|
-
const resolvedPath =
|
|
59494
|
-
const projectRoot =
|
|
59495
|
-
const relative9 =
|
|
59496
|
-
const withinProject = relative9 === "" || !relative9.startsWith("..") && !
|
|
59670
|
+
const resolvedPath = path52.resolve(directory, normalizedPath);
|
|
59671
|
+
const projectRoot = path52.resolve(directory);
|
|
59672
|
+
const relative9 = path52.relative(projectRoot, resolvedPath);
|
|
59673
|
+
const withinProject = relative9 === "" || !relative9.startsWith("..") && !path52.isAbsolute(relative9);
|
|
59497
59674
|
if (!withinProject) {
|
|
59498
59675
|
blockedTasks.push({
|
|
59499
59676
|
task_id: task.id,
|
|
@@ -59548,8 +59725,8 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
59548
59725
|
blockedTasks
|
|
59549
59726
|
};
|
|
59550
59727
|
try {
|
|
59551
|
-
const evidenceDir =
|
|
59552
|
-
const evidencePath =
|
|
59728
|
+
const evidenceDir = path52.join(directory, ".swarm", "evidence", `${phase}`);
|
|
59729
|
+
const evidencePath = path52.join(evidenceDir, "completion-verify.json");
|
|
59553
59730
|
fs40.mkdirSync(evidenceDir, { recursive: true });
|
|
59554
59731
|
const evidenceBundle = {
|
|
59555
59732
|
schema_version: "1.0.0",
|
|
@@ -59626,11 +59803,11 @@ var completion_verify = createSwarmTool({
|
|
|
59626
59803
|
// src/tools/complexity-hotspots.ts
|
|
59627
59804
|
init_dist();
|
|
59628
59805
|
import * as fs42 from "fs";
|
|
59629
|
-
import * as
|
|
59806
|
+
import * as path54 from "path";
|
|
59630
59807
|
|
|
59631
59808
|
// src/quality/metrics.ts
|
|
59632
59809
|
import * as fs41 from "fs";
|
|
59633
|
-
import * as
|
|
59810
|
+
import * as path53 from "path";
|
|
59634
59811
|
var MAX_FILE_SIZE_BYTES3 = 256 * 1024;
|
|
59635
59812
|
var MIN_DUPLICATION_LINES = 10;
|
|
59636
59813
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -59682,7 +59859,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
59682
59859
|
let totalComplexity = 0;
|
|
59683
59860
|
const analyzedFiles = [];
|
|
59684
59861
|
for (const file3 of files) {
|
|
59685
|
-
const fullPath =
|
|
59862
|
+
const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
|
|
59686
59863
|
if (!fs41.existsSync(fullPath)) {
|
|
59687
59864
|
continue;
|
|
59688
59865
|
}
|
|
@@ -59805,7 +59982,7 @@ function countGoExports(content) {
|
|
|
59805
59982
|
function getExportCountForFile(filePath) {
|
|
59806
59983
|
try {
|
|
59807
59984
|
const content = fs41.readFileSync(filePath, "utf-8");
|
|
59808
|
-
const ext =
|
|
59985
|
+
const ext = path53.extname(filePath).toLowerCase();
|
|
59809
59986
|
switch (ext) {
|
|
59810
59987
|
case ".ts":
|
|
59811
59988
|
case ".tsx":
|
|
@@ -59831,7 +60008,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
59831
60008
|
let totalExports = 0;
|
|
59832
60009
|
const analyzedFiles = [];
|
|
59833
60010
|
for (const file3 of files) {
|
|
59834
|
-
const fullPath =
|
|
60011
|
+
const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
|
|
59835
60012
|
if (!fs41.existsSync(fullPath)) {
|
|
59836
60013
|
continue;
|
|
59837
60014
|
}
|
|
@@ -59865,7 +60042,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
59865
60042
|
let duplicateLines = 0;
|
|
59866
60043
|
const analyzedFiles = [];
|
|
59867
60044
|
for (const file3 of files) {
|
|
59868
|
-
const fullPath =
|
|
60045
|
+
const fullPath = path53.isAbsolute(file3) ? file3 : path53.join(workingDir, file3);
|
|
59869
60046
|
if (!fs41.existsSync(fullPath)) {
|
|
59870
60047
|
continue;
|
|
59871
60048
|
}
|
|
@@ -59898,8 +60075,8 @@ function countCodeLines(content) {
|
|
|
59898
60075
|
return lines.length;
|
|
59899
60076
|
}
|
|
59900
60077
|
function isTestFile(filePath) {
|
|
59901
|
-
const basename8 =
|
|
59902
|
-
const _ext =
|
|
60078
|
+
const basename8 = path53.basename(filePath);
|
|
60079
|
+
const _ext = path53.extname(filePath).toLowerCase();
|
|
59903
60080
|
const testPatterns = [
|
|
59904
60081
|
".test.",
|
|
59905
60082
|
".spec.",
|
|
@@ -59980,8 +60157,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
59980
60157
|
}
|
|
59981
60158
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
59982
60159
|
}
|
|
59983
|
-
function matchesGlobSegment(
|
|
59984
|
-
const normalizedPath =
|
|
60160
|
+
function matchesGlobSegment(path54, glob) {
|
|
60161
|
+
const normalizedPath = path54.replace(/\\/g, "/");
|
|
59985
60162
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
59986
60163
|
if (normalizedPath.includes("//")) {
|
|
59987
60164
|
return false;
|
|
@@ -60012,8 +60189,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
60012
60189
|
function hasGlobstar(glob) {
|
|
60013
60190
|
return glob.includes("**");
|
|
60014
60191
|
}
|
|
60015
|
-
function globMatches(
|
|
60016
|
-
const normalizedPath =
|
|
60192
|
+
function globMatches(path54, glob) {
|
|
60193
|
+
const normalizedPath = path54.replace(/\\/g, "/");
|
|
60017
60194
|
if (!glob || glob === "") {
|
|
60018
60195
|
if (normalizedPath.includes("//")) {
|
|
60019
60196
|
return false;
|
|
@@ -60049,7 +60226,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
60049
60226
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
60050
60227
|
let testLines = 0;
|
|
60051
60228
|
let codeLines = 0;
|
|
60052
|
-
const srcDir =
|
|
60229
|
+
const srcDir = path53.join(workingDir, "src");
|
|
60053
60230
|
if (fs41.existsSync(srcDir)) {
|
|
60054
60231
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60055
60232
|
codeLines += lines;
|
|
@@ -60057,14 +60234,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
60057
60234
|
}
|
|
60058
60235
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
60059
60236
|
for (const dir of possibleSrcDirs) {
|
|
60060
|
-
const dirPath =
|
|
60237
|
+
const dirPath = path53.join(workingDir, dir);
|
|
60061
60238
|
if (fs41.existsSync(dirPath)) {
|
|
60062
60239
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60063
60240
|
codeLines += lines;
|
|
60064
60241
|
});
|
|
60065
60242
|
}
|
|
60066
60243
|
}
|
|
60067
|
-
const testsDir =
|
|
60244
|
+
const testsDir = path53.join(workingDir, "tests");
|
|
60068
60245
|
if (fs41.existsSync(testsDir)) {
|
|
60069
60246
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60070
60247
|
testLines += lines;
|
|
@@ -60072,7 +60249,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
60072
60249
|
}
|
|
60073
60250
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
60074
60251
|
for (const dir of possibleTestDirs) {
|
|
60075
|
-
const dirPath =
|
|
60252
|
+
const dirPath = path53.join(workingDir, dir);
|
|
60076
60253
|
if (fs41.existsSync(dirPath) && dirPath !== testsDir) {
|
|
60077
60254
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60078
60255
|
testLines += lines;
|
|
@@ -60087,7 +60264,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60087
60264
|
try {
|
|
60088
60265
|
const entries = fs41.readdirSync(dirPath, { withFileTypes: true });
|
|
60089
60266
|
for (const entry of entries) {
|
|
60090
|
-
const fullPath =
|
|
60267
|
+
const fullPath = path53.join(dirPath, entry.name);
|
|
60091
60268
|
if (entry.isDirectory()) {
|
|
60092
60269
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
60093
60270
|
continue;
|
|
@@ -60095,7 +60272,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60095
60272
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
60096
60273
|
} else if (entry.isFile()) {
|
|
60097
60274
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
60098
|
-
const ext =
|
|
60275
|
+
const ext = path53.extname(entry.name).toLowerCase();
|
|
60099
60276
|
const validExts = [
|
|
60100
60277
|
".ts",
|
|
60101
60278
|
".tsx",
|
|
@@ -60347,7 +60524,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
60347
60524
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
60348
60525
|
const filteredChurn = new Map;
|
|
60349
60526
|
for (const [file3, count] of churnMap) {
|
|
60350
|
-
const ext =
|
|
60527
|
+
const ext = path54.extname(file3).toLowerCase();
|
|
60351
60528
|
if (extSet.has(ext)) {
|
|
60352
60529
|
filteredChurn.set(file3, count);
|
|
60353
60530
|
}
|
|
@@ -60358,7 +60535,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
60358
60535
|
for (const [file3, churnCount] of filteredChurn) {
|
|
60359
60536
|
let fullPath = file3;
|
|
60360
60537
|
if (!fs42.existsSync(fullPath)) {
|
|
60361
|
-
fullPath =
|
|
60538
|
+
fullPath = path54.join(cwd, file3);
|
|
60362
60539
|
}
|
|
60363
60540
|
const complexity = getComplexityForFile2(fullPath);
|
|
60364
60541
|
if (complexity !== null) {
|
|
@@ -60606,7 +60783,7 @@ var curator_analyze = createSwarmTool({
|
|
|
60606
60783
|
// src/tools/declare-scope.ts
|
|
60607
60784
|
init_tool();
|
|
60608
60785
|
import * as fs43 from "fs";
|
|
60609
|
-
import * as
|
|
60786
|
+
import * as path55 from "path";
|
|
60610
60787
|
init_create_tool();
|
|
60611
60788
|
function validateTaskIdFormat(taskId) {
|
|
60612
60789
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -60685,8 +60862,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60685
60862
|
};
|
|
60686
60863
|
}
|
|
60687
60864
|
}
|
|
60688
|
-
normalizedDir =
|
|
60689
|
-
const pathParts = normalizedDir.split(
|
|
60865
|
+
normalizedDir = path55.normalize(args2.working_directory);
|
|
60866
|
+
const pathParts = normalizedDir.split(path55.sep);
|
|
60690
60867
|
if (pathParts.includes("..")) {
|
|
60691
60868
|
return {
|
|
60692
60869
|
success: false,
|
|
@@ -60696,10 +60873,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60696
60873
|
]
|
|
60697
60874
|
};
|
|
60698
60875
|
}
|
|
60699
|
-
const resolvedDir =
|
|
60876
|
+
const resolvedDir = path55.resolve(normalizedDir);
|
|
60700
60877
|
try {
|
|
60701
60878
|
const realPath = fs43.realpathSync(resolvedDir);
|
|
60702
|
-
const planPath2 =
|
|
60879
|
+
const planPath2 = path55.join(realPath, ".swarm", "plan.json");
|
|
60703
60880
|
if (!fs43.existsSync(planPath2)) {
|
|
60704
60881
|
return {
|
|
60705
60882
|
success: false,
|
|
@@ -60723,7 +60900,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60723
60900
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
60724
60901
|
}
|
|
60725
60902
|
const directory = normalizedDir || fallbackDir;
|
|
60726
|
-
const planPath =
|
|
60903
|
+
const planPath = path55.resolve(directory, ".swarm", "plan.json");
|
|
60727
60904
|
if (!fs43.existsSync(planPath)) {
|
|
60728
60905
|
return {
|
|
60729
60906
|
success: false,
|
|
@@ -60765,8 +60942,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
60765
60942
|
const normalizeErrors = [];
|
|
60766
60943
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
60767
60944
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
60768
|
-
if (
|
|
60769
|
-
const relativePath =
|
|
60945
|
+
if (path55.isAbsolute(file3)) {
|
|
60946
|
+
const relativePath = path55.relative(dir, file3).replace(/\\/g, "/");
|
|
60770
60947
|
if (relativePath.startsWith("..")) {
|
|
60771
60948
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
60772
60949
|
return file3;
|
|
@@ -61092,20 +61269,20 @@ function validateBase(base) {
|
|
|
61092
61269
|
function validatePaths(paths) {
|
|
61093
61270
|
if (!paths)
|
|
61094
61271
|
return null;
|
|
61095
|
-
for (const
|
|
61096
|
-
if (!
|
|
61272
|
+
for (const path57 of paths) {
|
|
61273
|
+
if (!path57 || path57.length === 0) {
|
|
61097
61274
|
return "empty path not allowed";
|
|
61098
61275
|
}
|
|
61099
|
-
if (
|
|
61276
|
+
if (path57.length > MAX_PATH_LENGTH) {
|
|
61100
61277
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
61101
61278
|
}
|
|
61102
|
-
if (SHELL_METACHARACTERS2.test(
|
|
61279
|
+
if (SHELL_METACHARACTERS2.test(path57)) {
|
|
61103
61280
|
return "path contains shell metacharacters";
|
|
61104
61281
|
}
|
|
61105
|
-
if (
|
|
61282
|
+
if (path57.startsWith("-")) {
|
|
61106
61283
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
61107
61284
|
}
|
|
61108
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
61285
|
+
if (CONTROL_CHAR_PATTERN2.test(path57)) {
|
|
61109
61286
|
return "path contains control characters";
|
|
61110
61287
|
}
|
|
61111
61288
|
}
|
|
@@ -61186,8 +61363,8 @@ var diff = createSwarmTool({
|
|
|
61186
61363
|
if (parts2.length >= 3) {
|
|
61187
61364
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
61188
61365
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
61189
|
-
const
|
|
61190
|
-
files.push({ path:
|
|
61366
|
+
const path57 = parts2[2];
|
|
61367
|
+
files.push({ path: path57, additions, deletions });
|
|
61191
61368
|
}
|
|
61192
61369
|
}
|
|
61193
61370
|
const contractChanges = [];
|
|
@@ -61470,7 +61647,7 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
61470
61647
|
init_dist();
|
|
61471
61648
|
init_create_tool();
|
|
61472
61649
|
import * as fs44 from "fs";
|
|
61473
|
-
import * as
|
|
61650
|
+
import * as path57 from "path";
|
|
61474
61651
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
61475
61652
|
var MAX_EVIDENCE_FILES = 1000;
|
|
61476
61653
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -61497,9 +61674,9 @@ function validateRequiredTypes(input) {
|
|
|
61497
61674
|
return null;
|
|
61498
61675
|
}
|
|
61499
61676
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
61500
|
-
const normalizedCwd =
|
|
61501
|
-
const swarmPath =
|
|
61502
|
-
const normalizedPath =
|
|
61677
|
+
const normalizedCwd = path57.resolve(cwd);
|
|
61678
|
+
const swarmPath = path57.join(normalizedCwd, ".swarm");
|
|
61679
|
+
const normalizedPath = path57.resolve(filePath);
|
|
61503
61680
|
return normalizedPath.startsWith(swarmPath);
|
|
61504
61681
|
}
|
|
61505
61682
|
function parseCompletedTasks(planContent) {
|
|
@@ -61529,10 +61706,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
61529
61706
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
61530
61707
|
continue;
|
|
61531
61708
|
}
|
|
61532
|
-
const filePath =
|
|
61709
|
+
const filePath = path57.join(evidenceDir, filename);
|
|
61533
61710
|
try {
|
|
61534
|
-
const resolvedPath =
|
|
61535
|
-
const evidenceDirResolved =
|
|
61711
|
+
const resolvedPath = path57.resolve(filePath);
|
|
61712
|
+
const evidenceDirResolved = path57.resolve(evidenceDir);
|
|
61536
61713
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
61537
61714
|
continue;
|
|
61538
61715
|
}
|
|
@@ -61650,7 +61827,7 @@ var evidence_check = createSwarmTool({
|
|
|
61650
61827
|
return JSON.stringify(errorResult, null, 2);
|
|
61651
61828
|
}
|
|
61652
61829
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
61653
|
-
const planPath =
|
|
61830
|
+
const planPath = path57.join(cwd, PLAN_FILE);
|
|
61654
61831
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
61655
61832
|
const errorResult = {
|
|
61656
61833
|
error: "plan file path validation failed",
|
|
@@ -61682,7 +61859,7 @@ var evidence_check = createSwarmTool({
|
|
|
61682
61859
|
};
|
|
61683
61860
|
return JSON.stringify(result2, null, 2);
|
|
61684
61861
|
}
|
|
61685
|
-
const evidenceDir =
|
|
61862
|
+
const evidenceDir = path57.join(cwd, EVIDENCE_DIR2);
|
|
61686
61863
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
61687
61864
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
61688
61865
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -61700,7 +61877,7 @@ var evidence_check = createSwarmTool({
|
|
|
61700
61877
|
init_tool();
|
|
61701
61878
|
init_create_tool();
|
|
61702
61879
|
import * as fs45 from "fs";
|
|
61703
|
-
import * as
|
|
61880
|
+
import * as path58 from "path";
|
|
61704
61881
|
var EXT_MAP = {
|
|
61705
61882
|
python: ".py",
|
|
61706
61883
|
py: ".py",
|
|
@@ -61781,12 +61958,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
61781
61958
|
if (prefix) {
|
|
61782
61959
|
filename = `${prefix}_${filename}`;
|
|
61783
61960
|
}
|
|
61784
|
-
let filepath =
|
|
61785
|
-
const base =
|
|
61786
|
-
const ext =
|
|
61961
|
+
let filepath = path58.join(targetDir, filename);
|
|
61962
|
+
const base = path58.basename(filepath, path58.extname(filepath));
|
|
61963
|
+
const ext = path58.extname(filepath);
|
|
61787
61964
|
let counter = 1;
|
|
61788
61965
|
while (fs45.existsSync(filepath)) {
|
|
61789
|
-
filepath =
|
|
61966
|
+
filepath = path58.join(targetDir, `${base}_${counter}${ext}`);
|
|
61790
61967
|
counter++;
|
|
61791
61968
|
}
|
|
61792
61969
|
try {
|
|
@@ -61907,7 +62084,7 @@ var gitingest = createSwarmTool({
|
|
|
61907
62084
|
init_dist();
|
|
61908
62085
|
init_create_tool();
|
|
61909
62086
|
import * as fs46 from "fs";
|
|
61910
|
-
import * as
|
|
62087
|
+
import * as path59 from "path";
|
|
61911
62088
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
61912
62089
|
var MAX_SYMBOL_LENGTH = 256;
|
|
61913
62090
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
@@ -61955,7 +62132,7 @@ function validateSymbolInput(symbol3) {
|
|
|
61955
62132
|
return null;
|
|
61956
62133
|
}
|
|
61957
62134
|
function isBinaryFile2(filePath, buffer) {
|
|
61958
|
-
const ext =
|
|
62135
|
+
const ext = path59.extname(filePath).toLowerCase();
|
|
61959
62136
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
61960
62137
|
return false;
|
|
61961
62138
|
}
|
|
@@ -61979,15 +62156,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
61979
62156
|
const imports = [];
|
|
61980
62157
|
let _resolvedTarget;
|
|
61981
62158
|
try {
|
|
61982
|
-
_resolvedTarget =
|
|
62159
|
+
_resolvedTarget = path59.resolve(targetFile);
|
|
61983
62160
|
} catch {
|
|
61984
62161
|
_resolvedTarget = targetFile;
|
|
61985
62162
|
}
|
|
61986
|
-
const targetBasename =
|
|
62163
|
+
const targetBasename = path59.basename(targetFile, path59.extname(targetFile));
|
|
61987
62164
|
const targetWithExt = targetFile;
|
|
61988
62165
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
61989
|
-
const normalizedTargetWithExt =
|
|
61990
|
-
const normalizedTargetWithoutExt =
|
|
62166
|
+
const normalizedTargetWithExt = path59.normalize(targetWithExt).replace(/\\/g, "/");
|
|
62167
|
+
const normalizedTargetWithoutExt = path59.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
61991
62168
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
61992
62169
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
61993
62170
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -62010,9 +62187,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
62010
62187
|
}
|
|
62011
62188
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
62012
62189
|
let isMatch = false;
|
|
62013
|
-
const _targetDir =
|
|
62014
|
-
const targetExt =
|
|
62015
|
-
const targetBasenameNoExt =
|
|
62190
|
+
const _targetDir = path59.dirname(targetFile);
|
|
62191
|
+
const targetExt = path59.extname(targetFile);
|
|
62192
|
+
const targetBasenameNoExt = path59.basename(targetFile, targetExt);
|
|
62016
62193
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
62017
62194
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
62018
62195
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -62080,10 +62257,10 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62080
62257
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
62081
62258
|
for (const entry of entries) {
|
|
62082
62259
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
62083
|
-
stats.skippedDirs.push(
|
|
62260
|
+
stats.skippedDirs.push(path59.join(dir, entry));
|
|
62084
62261
|
continue;
|
|
62085
62262
|
}
|
|
62086
|
-
const fullPath =
|
|
62263
|
+
const fullPath = path59.join(dir, entry);
|
|
62087
62264
|
let stat2;
|
|
62088
62265
|
try {
|
|
62089
62266
|
stat2 = fs46.statSync(fullPath);
|
|
@@ -62097,7 +62274,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62097
62274
|
if (stat2.isDirectory()) {
|
|
62098
62275
|
findSourceFiles(fullPath, files, stats);
|
|
62099
62276
|
} else if (stat2.isFile()) {
|
|
62100
|
-
const ext =
|
|
62277
|
+
const ext = path59.extname(fullPath).toLowerCase();
|
|
62101
62278
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
62102
62279
|
files.push(fullPath);
|
|
62103
62280
|
}
|
|
@@ -62154,7 +62331,7 @@ var imports = createSwarmTool({
|
|
|
62154
62331
|
return JSON.stringify(errorResult, null, 2);
|
|
62155
62332
|
}
|
|
62156
62333
|
try {
|
|
62157
|
-
const targetFile =
|
|
62334
|
+
const targetFile = path59.resolve(file3);
|
|
62158
62335
|
if (!fs46.existsSync(targetFile)) {
|
|
62159
62336
|
const errorResult = {
|
|
62160
62337
|
error: `target file not found: ${file3}`,
|
|
@@ -62176,7 +62353,7 @@ var imports = createSwarmTool({
|
|
|
62176
62353
|
};
|
|
62177
62354
|
return JSON.stringify(errorResult, null, 2);
|
|
62178
62355
|
}
|
|
62179
|
-
const baseDir =
|
|
62356
|
+
const baseDir = path59.dirname(targetFile);
|
|
62180
62357
|
const scanStats = {
|
|
62181
62358
|
skippedDirs: [],
|
|
62182
62359
|
skippedFiles: 0,
|
|
@@ -62786,7 +62963,7 @@ init_config();
|
|
|
62786
62963
|
init_schema();
|
|
62787
62964
|
init_manager();
|
|
62788
62965
|
import * as fs47 from "fs";
|
|
62789
|
-
import * as
|
|
62966
|
+
import * as path60 from "path";
|
|
62790
62967
|
init_review_receipt();
|
|
62791
62968
|
init_utils2();
|
|
62792
62969
|
init_ledger();
|
|
@@ -63010,7 +63187,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63010
63187
|
safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
|
|
63011
63188
|
}
|
|
63012
63189
|
try {
|
|
63013
|
-
const driftEvidencePath =
|
|
63190
|
+
const driftEvidencePath = path60.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
63014
63191
|
let driftVerdictFound = false;
|
|
63015
63192
|
let driftVerdictApproved = false;
|
|
63016
63193
|
try {
|
|
@@ -63044,7 +63221,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63044
63221
|
driftVerdictFound = false;
|
|
63045
63222
|
}
|
|
63046
63223
|
if (!driftVerdictFound) {
|
|
63047
|
-
const specPath =
|
|
63224
|
+
const specPath = path60.join(dir, ".swarm", "spec.md");
|
|
63048
63225
|
const specExists = fs47.existsSync(specPath);
|
|
63049
63226
|
if (!specExists) {
|
|
63050
63227
|
let incompleteTaskCount = 0;
|
|
@@ -63096,7 +63273,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63096
63273
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
63097
63274
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
63098
63275
|
try {
|
|
63099
|
-
const projectName =
|
|
63276
|
+
const projectName = path60.basename(dir);
|
|
63100
63277
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
63101
63278
|
if (curationResult) {
|
|
63102
63279
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -63416,7 +63593,7 @@ init_discovery();
|
|
|
63416
63593
|
init_utils();
|
|
63417
63594
|
init_create_tool();
|
|
63418
63595
|
import * as fs48 from "fs";
|
|
63419
|
-
import * as
|
|
63596
|
+
import * as path61 from "path";
|
|
63420
63597
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
63421
63598
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
63422
63599
|
function isValidEcosystem(value) {
|
|
@@ -63434,16 +63611,16 @@ function validateArgs3(args2) {
|
|
|
63434
63611
|
function detectEcosystems(directory) {
|
|
63435
63612
|
const ecosystems = [];
|
|
63436
63613
|
const cwd = directory;
|
|
63437
|
-
if (fs48.existsSync(
|
|
63614
|
+
if (fs48.existsSync(path61.join(cwd, "package.json"))) {
|
|
63438
63615
|
ecosystems.push("npm");
|
|
63439
63616
|
}
|
|
63440
|
-
if (fs48.existsSync(
|
|
63617
|
+
if (fs48.existsSync(path61.join(cwd, "pyproject.toml")) || fs48.existsSync(path61.join(cwd, "requirements.txt"))) {
|
|
63441
63618
|
ecosystems.push("pip");
|
|
63442
63619
|
}
|
|
63443
|
-
if (fs48.existsSync(
|
|
63620
|
+
if (fs48.existsSync(path61.join(cwd, "Cargo.toml"))) {
|
|
63444
63621
|
ecosystems.push("cargo");
|
|
63445
63622
|
}
|
|
63446
|
-
if (fs48.existsSync(
|
|
63623
|
+
if (fs48.existsSync(path61.join(cwd, "go.mod"))) {
|
|
63447
63624
|
ecosystems.push("go");
|
|
63448
63625
|
}
|
|
63449
63626
|
try {
|
|
@@ -63452,10 +63629,10 @@ function detectEcosystems(directory) {
|
|
|
63452
63629
|
ecosystems.push("dotnet");
|
|
63453
63630
|
}
|
|
63454
63631
|
} catch {}
|
|
63455
|
-
if (fs48.existsSync(
|
|
63632
|
+
if (fs48.existsSync(path61.join(cwd, "Gemfile")) || fs48.existsSync(path61.join(cwd, "Gemfile.lock"))) {
|
|
63456
63633
|
ecosystems.push("ruby");
|
|
63457
63634
|
}
|
|
63458
|
-
if (fs48.existsSync(
|
|
63635
|
+
if (fs48.existsSync(path61.join(cwd, "pubspec.yaml"))) {
|
|
63459
63636
|
ecosystems.push("dart");
|
|
63460
63637
|
}
|
|
63461
63638
|
return ecosystems;
|
|
@@ -64478,7 +64655,7 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
64478
64655
|
// src/tools/pre-check-batch.ts
|
|
64479
64656
|
init_dist();
|
|
64480
64657
|
import * as fs50 from "fs";
|
|
64481
|
-
import * as
|
|
64658
|
+
import * as path63 from "path";
|
|
64482
64659
|
|
|
64483
64660
|
// node_modules/yocto-queue/index.js
|
|
64484
64661
|
class Node2 {
|
|
@@ -64753,7 +64930,7 @@ init_dist();
|
|
|
64753
64930
|
init_manager();
|
|
64754
64931
|
init_detector();
|
|
64755
64932
|
import * as fs49 from "fs";
|
|
64756
|
-
import * as
|
|
64933
|
+
import * as path62 from "path";
|
|
64757
64934
|
import { extname as extname12 } from "path";
|
|
64758
64935
|
|
|
64759
64936
|
// src/sast/rules/c.ts
|
|
@@ -65719,9 +65896,9 @@ async function sastScan(input, directory, config3) {
|
|
|
65719
65896
|
_filesSkipped++;
|
|
65720
65897
|
continue;
|
|
65721
65898
|
}
|
|
65722
|
-
const resolvedPath =
|
|
65723
|
-
const resolvedDirectory =
|
|
65724
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
65899
|
+
const resolvedPath = path62.isAbsolute(filePath) ? filePath : path62.resolve(directory, filePath);
|
|
65900
|
+
const resolvedDirectory = path62.resolve(directory);
|
|
65901
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path62.sep) && resolvedPath !== resolvedDirectory) {
|
|
65725
65902
|
_filesSkipped++;
|
|
65726
65903
|
continue;
|
|
65727
65904
|
}
|
|
@@ -65923,18 +66100,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
65923
66100
|
let resolved;
|
|
65924
66101
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
65925
66102
|
if (isWinAbs) {
|
|
65926
|
-
resolved =
|
|
65927
|
-
} else if (
|
|
65928
|
-
resolved =
|
|
66103
|
+
resolved = path63.win32.resolve(inputPath);
|
|
66104
|
+
} else if (path63.isAbsolute(inputPath)) {
|
|
66105
|
+
resolved = path63.resolve(inputPath);
|
|
65929
66106
|
} else {
|
|
65930
|
-
resolved =
|
|
66107
|
+
resolved = path63.resolve(baseDir, inputPath);
|
|
65931
66108
|
}
|
|
65932
|
-
const workspaceResolved =
|
|
66109
|
+
const workspaceResolved = path63.resolve(workspaceDir);
|
|
65933
66110
|
let relative11;
|
|
65934
66111
|
if (isWinAbs) {
|
|
65935
|
-
relative11 =
|
|
66112
|
+
relative11 = path63.win32.relative(workspaceResolved, resolved);
|
|
65936
66113
|
} else {
|
|
65937
|
-
relative11 =
|
|
66114
|
+
relative11 = path63.relative(workspaceResolved, resolved);
|
|
65938
66115
|
}
|
|
65939
66116
|
if (relative11.startsWith("..")) {
|
|
65940
66117
|
return "path traversal detected";
|
|
@@ -65999,7 +66176,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
65999
66176
|
if (typeof file3 !== "string") {
|
|
66000
66177
|
continue;
|
|
66001
66178
|
}
|
|
66002
|
-
const resolvedPath =
|
|
66179
|
+
const resolvedPath = path63.resolve(file3);
|
|
66003
66180
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
66004
66181
|
if (validationError) {
|
|
66005
66182
|
continue;
|
|
@@ -66156,7 +66333,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
66156
66333
|
skippedFiles++;
|
|
66157
66334
|
continue;
|
|
66158
66335
|
}
|
|
66159
|
-
const resolvedPath =
|
|
66336
|
+
const resolvedPath = path63.resolve(file3);
|
|
66160
66337
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
66161
66338
|
if (validationError) {
|
|
66162
66339
|
skippedFiles++;
|
|
@@ -66174,7 +66351,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
66174
66351
|
};
|
|
66175
66352
|
}
|
|
66176
66353
|
for (const file3 of validatedFiles) {
|
|
66177
|
-
const ext =
|
|
66354
|
+
const ext = path63.extname(file3).toLowerCase();
|
|
66178
66355
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
66179
66356
|
skippedFiles++;
|
|
66180
66357
|
continue;
|
|
@@ -66380,7 +66557,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
66380
66557
|
const preexistingFindings = [];
|
|
66381
66558
|
for (const finding of findings) {
|
|
66382
66559
|
const filePath = finding.location.file;
|
|
66383
|
-
const normalised =
|
|
66560
|
+
const normalised = path63.relative(directory, filePath).replace(/\\/g, "/");
|
|
66384
66561
|
const changedLines = changedLineRanges.get(normalised);
|
|
66385
66562
|
if (changedLines && changedLines.has(finding.location.line)) {
|
|
66386
66563
|
newFindings.push(finding);
|
|
@@ -66431,7 +66608,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
66431
66608
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
66432
66609
|
continue;
|
|
66433
66610
|
}
|
|
66434
|
-
changedFiles.push(
|
|
66611
|
+
changedFiles.push(path63.resolve(directory, file3));
|
|
66435
66612
|
}
|
|
66436
66613
|
if (changedFiles.length === 0) {
|
|
66437
66614
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -66619,7 +66796,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
66619
66796
|
};
|
|
66620
66797
|
return JSON.stringify(errorResult, null, 2);
|
|
66621
66798
|
}
|
|
66622
|
-
const resolvedDirectory =
|
|
66799
|
+
const resolvedDirectory = path63.resolve(typedArgs.directory);
|
|
66623
66800
|
const workspaceAnchor = resolvedDirectory;
|
|
66624
66801
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
66625
66802
|
if (dirError) {
|
|
@@ -66726,25 +66903,25 @@ ${paginatedContent}`;
|
|
|
66726
66903
|
// src/tools/save-plan.ts
|
|
66727
66904
|
init_tool();
|
|
66728
66905
|
import * as fs52 from "fs";
|
|
66729
|
-
import * as
|
|
66906
|
+
import * as path65 from "path";
|
|
66730
66907
|
|
|
66731
66908
|
// src/parallel/file-locks.ts
|
|
66732
66909
|
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
66733
66910
|
import * as fs51 from "fs";
|
|
66734
|
-
import * as
|
|
66911
|
+
import * as path64 from "path";
|
|
66735
66912
|
var LOCKS_DIR = ".swarm/locks";
|
|
66736
66913
|
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
66737
66914
|
function getLockFilePath(directory, filePath) {
|
|
66738
|
-
const normalized =
|
|
66739
|
-
if (!normalized.startsWith(
|
|
66915
|
+
const normalized = path64.resolve(directory, filePath);
|
|
66916
|
+
if (!normalized.startsWith(path64.resolve(directory))) {
|
|
66740
66917
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
66741
66918
|
}
|
|
66742
66919
|
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
66743
|
-
return
|
|
66920
|
+
return path64.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
66744
66921
|
}
|
|
66745
66922
|
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
66746
66923
|
const lockPath = getLockFilePath(directory, filePath);
|
|
66747
|
-
const locksDir =
|
|
66924
|
+
const locksDir = path64.dirname(lockPath);
|
|
66748
66925
|
if (!fs51.existsSync(locksDir)) {
|
|
66749
66926
|
fs51.mkdirSync(locksDir, { recursive: true });
|
|
66750
66927
|
}
|
|
@@ -66897,7 +67074,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
66897
67074
|
await savePlan(dir, plan);
|
|
66898
67075
|
await writeCheckpoint(dir).catch(() => {});
|
|
66899
67076
|
try {
|
|
66900
|
-
const markerPath =
|
|
67077
|
+
const markerPath = path65.join(dir, ".swarm", ".plan-write-marker");
|
|
66901
67078
|
const marker = JSON.stringify({
|
|
66902
67079
|
source: "save_plan",
|
|
66903
67080
|
timestamp: new Date().toISOString(),
|
|
@@ -66920,7 +67097,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
66920
67097
|
return {
|
|
66921
67098
|
success: true,
|
|
66922
67099
|
message: "Plan saved successfully",
|
|
66923
|
-
plan_path:
|
|
67100
|
+
plan_path: path65.join(dir, ".swarm", "plan.json"),
|
|
66924
67101
|
phases_count: plan.phases.length,
|
|
66925
67102
|
tasks_count: tasksCount,
|
|
66926
67103
|
...warnings.length > 0 ? { warnings } : {}
|
|
@@ -66965,7 +67142,7 @@ var save_plan = createSwarmTool({
|
|
|
66965
67142
|
init_dist();
|
|
66966
67143
|
init_manager();
|
|
66967
67144
|
import * as fs53 from "fs";
|
|
66968
|
-
import * as
|
|
67145
|
+
import * as path66 from "path";
|
|
66969
67146
|
|
|
66970
67147
|
// src/sbom/detectors/index.ts
|
|
66971
67148
|
init_utils();
|
|
@@ -67815,7 +67992,7 @@ function findManifestFiles(rootDir) {
|
|
|
67815
67992
|
try {
|
|
67816
67993
|
const entries = fs53.readdirSync(dir, { withFileTypes: true });
|
|
67817
67994
|
for (const entry of entries) {
|
|
67818
|
-
const fullPath =
|
|
67995
|
+
const fullPath = path66.join(dir, entry.name);
|
|
67819
67996
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
67820
67997
|
continue;
|
|
67821
67998
|
}
|
|
@@ -67824,7 +68001,7 @@ function findManifestFiles(rootDir) {
|
|
|
67824
68001
|
} else if (entry.isFile()) {
|
|
67825
68002
|
for (const pattern of patterns) {
|
|
67826
68003
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
67827
|
-
manifestFiles.push(
|
|
68004
|
+
manifestFiles.push(path66.relative(rootDir, fullPath));
|
|
67828
68005
|
break;
|
|
67829
68006
|
}
|
|
67830
68007
|
}
|
|
@@ -67842,11 +68019,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
67842
68019
|
try {
|
|
67843
68020
|
const entries = fs53.readdirSync(dir, { withFileTypes: true });
|
|
67844
68021
|
for (const entry of entries) {
|
|
67845
|
-
const fullPath =
|
|
68022
|
+
const fullPath = path66.join(dir, entry.name);
|
|
67846
68023
|
if (entry.isFile()) {
|
|
67847
68024
|
for (const pattern of patterns) {
|
|
67848
68025
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
67849
|
-
found.push(
|
|
68026
|
+
found.push(path66.relative(workingDir, fullPath));
|
|
67850
68027
|
break;
|
|
67851
68028
|
}
|
|
67852
68029
|
}
|
|
@@ -67859,11 +68036,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
67859
68036
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
67860
68037
|
const dirs = new Set;
|
|
67861
68038
|
for (const file3 of changedFiles) {
|
|
67862
|
-
let currentDir =
|
|
68039
|
+
let currentDir = path66.dirname(file3);
|
|
67863
68040
|
while (true) {
|
|
67864
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
67865
|
-
dirs.add(
|
|
67866
|
-
const parent =
|
|
68041
|
+
if (currentDir && currentDir !== "." && currentDir !== path66.sep) {
|
|
68042
|
+
dirs.add(path66.join(workingDir, currentDir));
|
|
68043
|
+
const parent = path66.dirname(currentDir);
|
|
67867
68044
|
if (parent === currentDir)
|
|
67868
68045
|
break;
|
|
67869
68046
|
currentDir = parent;
|
|
@@ -67947,7 +68124,7 @@ var sbom_generate = createSwarmTool({
|
|
|
67947
68124
|
const changedFiles = obj.changed_files;
|
|
67948
68125
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
67949
68126
|
const workingDir = directory;
|
|
67950
|
-
const outputDir =
|
|
68127
|
+
const outputDir = path66.isAbsolute(relativeOutputDir) ? relativeOutputDir : path66.join(workingDir, relativeOutputDir);
|
|
67951
68128
|
let manifestFiles = [];
|
|
67952
68129
|
if (scope === "all") {
|
|
67953
68130
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -67970,7 +68147,7 @@ var sbom_generate = createSwarmTool({
|
|
|
67970
68147
|
const processedFiles = [];
|
|
67971
68148
|
for (const manifestFile of manifestFiles) {
|
|
67972
68149
|
try {
|
|
67973
|
-
const fullPath =
|
|
68150
|
+
const fullPath = path66.isAbsolute(manifestFile) ? manifestFile : path66.join(workingDir, manifestFile);
|
|
67974
68151
|
if (!fs53.existsSync(fullPath)) {
|
|
67975
68152
|
continue;
|
|
67976
68153
|
}
|
|
@@ -67987,7 +68164,7 @@ var sbom_generate = createSwarmTool({
|
|
|
67987
68164
|
const bom = generateCycloneDX(allComponents);
|
|
67988
68165
|
const bomJson = serializeCycloneDX(bom);
|
|
67989
68166
|
const filename = generateSbomFilename();
|
|
67990
|
-
const outputPath =
|
|
68167
|
+
const outputPath = path66.join(outputDir, filename);
|
|
67991
68168
|
fs53.writeFileSync(outputPath, bomJson, "utf-8");
|
|
67992
68169
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
67993
68170
|
try {
|
|
@@ -68031,7 +68208,7 @@ var sbom_generate = createSwarmTool({
|
|
|
68031
68208
|
init_dist();
|
|
68032
68209
|
init_create_tool();
|
|
68033
68210
|
import * as fs54 from "fs";
|
|
68034
|
-
import * as
|
|
68211
|
+
import * as path67 from "path";
|
|
68035
68212
|
var SPEC_CANDIDATES = [
|
|
68036
68213
|
"openapi.json",
|
|
68037
68214
|
"openapi.yaml",
|
|
@@ -68063,12 +68240,12 @@ function normalizePath2(p) {
|
|
|
68063
68240
|
}
|
|
68064
68241
|
function discoverSpecFile(cwd, specFileArg) {
|
|
68065
68242
|
if (specFileArg) {
|
|
68066
|
-
const resolvedPath =
|
|
68067
|
-
const normalizedCwd = cwd.endsWith(
|
|
68243
|
+
const resolvedPath = path67.resolve(cwd, specFileArg);
|
|
68244
|
+
const normalizedCwd = cwd.endsWith(path67.sep) ? cwd : cwd + path67.sep;
|
|
68068
68245
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
68069
68246
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
68070
68247
|
}
|
|
68071
|
-
const ext =
|
|
68248
|
+
const ext = path67.extname(resolvedPath).toLowerCase();
|
|
68072
68249
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
68073
68250
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
68074
68251
|
}
|
|
@@ -68082,7 +68259,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
68082
68259
|
return resolvedPath;
|
|
68083
68260
|
}
|
|
68084
68261
|
for (const candidate of SPEC_CANDIDATES) {
|
|
68085
|
-
const candidatePath =
|
|
68262
|
+
const candidatePath = path67.resolve(cwd, candidate);
|
|
68086
68263
|
if (fs54.existsSync(candidatePath)) {
|
|
68087
68264
|
const stats = fs54.statSync(candidatePath);
|
|
68088
68265
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -68094,7 +68271,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
68094
68271
|
}
|
|
68095
68272
|
function parseSpec(specFile) {
|
|
68096
68273
|
const content = fs54.readFileSync(specFile, "utf-8");
|
|
68097
|
-
const ext =
|
|
68274
|
+
const ext = path67.extname(specFile).toLowerCase();
|
|
68098
68275
|
if (ext === ".json") {
|
|
68099
68276
|
return parseJsonSpec(content);
|
|
68100
68277
|
}
|
|
@@ -68170,7 +68347,7 @@ function extractRoutes(cwd) {
|
|
|
68170
68347
|
return;
|
|
68171
68348
|
}
|
|
68172
68349
|
for (const entry of entries) {
|
|
68173
|
-
const fullPath =
|
|
68350
|
+
const fullPath = path67.join(dir, entry.name);
|
|
68174
68351
|
if (entry.isSymbolicLink()) {
|
|
68175
68352
|
continue;
|
|
68176
68353
|
}
|
|
@@ -68180,7 +68357,7 @@ function extractRoutes(cwd) {
|
|
|
68180
68357
|
}
|
|
68181
68358
|
walkDir(fullPath);
|
|
68182
68359
|
} else if (entry.isFile()) {
|
|
68183
|
-
const ext =
|
|
68360
|
+
const ext = path67.extname(entry.name).toLowerCase();
|
|
68184
68361
|
const baseName = entry.name.toLowerCase();
|
|
68185
68362
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
68186
68363
|
continue;
|
|
@@ -68346,7 +68523,7 @@ var schema_drift = createSwarmTool({
|
|
|
68346
68523
|
init_tool();
|
|
68347
68524
|
init_create_tool();
|
|
68348
68525
|
import * as fs55 from "fs";
|
|
68349
|
-
import * as
|
|
68526
|
+
import * as path68 from "path";
|
|
68350
68527
|
var DEFAULT_MAX_RESULTS = 100;
|
|
68351
68528
|
var DEFAULT_MAX_LINES = 200;
|
|
68352
68529
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -68382,11 +68559,11 @@ function containsWindowsAttacks3(str) {
|
|
|
68382
68559
|
}
|
|
68383
68560
|
function isPathInWorkspace3(filePath, workspace) {
|
|
68384
68561
|
try {
|
|
68385
|
-
const resolvedPath =
|
|
68562
|
+
const resolvedPath = path68.resolve(workspace, filePath);
|
|
68386
68563
|
const realWorkspace = fs55.realpathSync(workspace);
|
|
68387
68564
|
const realResolvedPath = fs55.realpathSync(resolvedPath);
|
|
68388
|
-
const relativePath =
|
|
68389
|
-
if (relativePath.startsWith("..") ||
|
|
68565
|
+
const relativePath = path68.relative(realWorkspace, realResolvedPath);
|
|
68566
|
+
if (relativePath.startsWith("..") || path68.isAbsolute(relativePath)) {
|
|
68390
68567
|
return false;
|
|
68391
68568
|
}
|
|
68392
68569
|
return true;
|
|
@@ -68399,11 +68576,11 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
68399
68576
|
}
|
|
68400
68577
|
function findRgInEnvPath() {
|
|
68401
68578
|
const searchPath = process.env.PATH ?? "";
|
|
68402
|
-
for (const dir of searchPath.split(
|
|
68579
|
+
for (const dir of searchPath.split(path68.delimiter)) {
|
|
68403
68580
|
if (!dir)
|
|
68404
68581
|
continue;
|
|
68405
68582
|
const isWindows = process.platform === "win32";
|
|
68406
|
-
const candidate =
|
|
68583
|
+
const candidate = path68.join(dir, isWindows ? "rg.exe" : "rg");
|
|
68407
68584
|
if (fs55.existsSync(candidate))
|
|
68408
68585
|
return candidate;
|
|
68409
68586
|
}
|
|
@@ -68533,8 +68710,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
68533
68710
|
try {
|
|
68534
68711
|
const entries = fs55.readdirSync(dir, { withFileTypes: true });
|
|
68535
68712
|
for (const entry of entries) {
|
|
68536
|
-
const fullPath =
|
|
68537
|
-
const relativePath =
|
|
68713
|
+
const fullPath = path68.join(dir, entry.name);
|
|
68714
|
+
const relativePath = path68.relative(workspace, fullPath);
|
|
68538
68715
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
68539
68716
|
continue;
|
|
68540
68717
|
}
|
|
@@ -68575,7 +68752,7 @@ async function fallbackSearch(opts) {
|
|
|
68575
68752
|
const matches = [];
|
|
68576
68753
|
let total = 0;
|
|
68577
68754
|
for (const file3 of files) {
|
|
68578
|
-
const fullPath =
|
|
68755
|
+
const fullPath = path68.join(opts.workspace, file3);
|
|
68579
68756
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
68580
68757
|
continue;
|
|
68581
68758
|
}
|
|
@@ -68746,7 +68923,7 @@ init_secretscan();
|
|
|
68746
68923
|
init_tool();
|
|
68747
68924
|
init_create_tool();
|
|
68748
68925
|
import * as fs56 from "fs";
|
|
68749
|
-
import * as
|
|
68926
|
+
import * as path69 from "path";
|
|
68750
68927
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
68751
68928
|
function containsWindowsAttacks4(str) {
|
|
68752
68929
|
if (/:[^\\/]/.test(str))
|
|
@@ -68760,14 +68937,14 @@ function containsWindowsAttacks4(str) {
|
|
|
68760
68937
|
}
|
|
68761
68938
|
function isPathInWorkspace4(filePath, workspace) {
|
|
68762
68939
|
try {
|
|
68763
|
-
const resolvedPath =
|
|
68940
|
+
const resolvedPath = path69.resolve(workspace, filePath);
|
|
68764
68941
|
if (!fs56.existsSync(resolvedPath)) {
|
|
68765
68942
|
return true;
|
|
68766
68943
|
}
|
|
68767
68944
|
const realWorkspace = fs56.realpathSync(workspace);
|
|
68768
68945
|
const realResolvedPath = fs56.realpathSync(resolvedPath);
|
|
68769
|
-
const relativePath =
|
|
68770
|
-
if (relativePath.startsWith("..") ||
|
|
68946
|
+
const relativePath = path69.relative(realWorkspace, realResolvedPath);
|
|
68947
|
+
if (relativePath.startsWith("..") || path69.isAbsolute(relativePath)) {
|
|
68771
68948
|
return false;
|
|
68772
68949
|
}
|
|
68773
68950
|
return true;
|
|
@@ -68975,7 +69152,7 @@ var suggestPatch = createSwarmTool({
|
|
|
68975
69152
|
});
|
|
68976
69153
|
continue;
|
|
68977
69154
|
}
|
|
68978
|
-
const fullPath =
|
|
69155
|
+
const fullPath = path69.resolve(directory, change.file);
|
|
68979
69156
|
if (!fs56.existsSync(fullPath)) {
|
|
68980
69157
|
errors5.push({
|
|
68981
69158
|
success: false,
|
|
@@ -69079,7 +69256,7 @@ init_dist();
|
|
|
69079
69256
|
init_utils();
|
|
69080
69257
|
init_create_tool();
|
|
69081
69258
|
import * as fs57 from "fs";
|
|
69082
|
-
import * as
|
|
69259
|
+
import * as path70 from "path";
|
|
69083
69260
|
var MAX_TEXT_LENGTH = 200;
|
|
69084
69261
|
var MAX_FILE_SIZE_BYTES9 = 1024 * 1024;
|
|
69085
69262
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -69144,9 +69321,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
69144
69321
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
69145
69322
|
}
|
|
69146
69323
|
try {
|
|
69147
|
-
const resolvedPath =
|
|
69148
|
-
const normalizedCwd =
|
|
69149
|
-
const normalizedResolved =
|
|
69324
|
+
const resolvedPath = path70.resolve(paths);
|
|
69325
|
+
const normalizedCwd = path70.resolve(cwd);
|
|
69326
|
+
const normalizedResolved = path70.resolve(resolvedPath);
|
|
69150
69327
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
69151
69328
|
return {
|
|
69152
69329
|
error: "paths must be within the current working directory",
|
|
@@ -69162,7 +69339,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
69162
69339
|
}
|
|
69163
69340
|
}
|
|
69164
69341
|
function isSupportedExtension(filePath) {
|
|
69165
|
-
const ext =
|
|
69342
|
+
const ext = path70.extname(filePath).toLowerCase();
|
|
69166
69343
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
69167
69344
|
}
|
|
69168
69345
|
function findSourceFiles2(dir, files = []) {
|
|
@@ -69177,7 +69354,7 @@ function findSourceFiles2(dir, files = []) {
|
|
|
69177
69354
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
69178
69355
|
continue;
|
|
69179
69356
|
}
|
|
69180
|
-
const fullPath =
|
|
69357
|
+
const fullPath = path70.join(dir, entry);
|
|
69181
69358
|
let stat2;
|
|
69182
69359
|
try {
|
|
69183
69360
|
stat2 = fs57.statSync(fullPath);
|
|
@@ -69289,7 +69466,7 @@ var todo_extract = createSwarmTool({
|
|
|
69289
69466
|
filesToScan.push(scanPath);
|
|
69290
69467
|
} else {
|
|
69291
69468
|
const errorResult = {
|
|
69292
|
-
error: `unsupported file extension: ${
|
|
69469
|
+
error: `unsupported file extension: ${path70.extname(scanPath)}`,
|
|
69293
69470
|
total: 0,
|
|
69294
69471
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
69295
69472
|
entries: []
|
|
@@ -69336,14 +69513,14 @@ init_tool();
|
|
|
69336
69513
|
init_schema();
|
|
69337
69514
|
init_gate_evidence();
|
|
69338
69515
|
import * as fs59 from "fs";
|
|
69339
|
-
import * as
|
|
69516
|
+
import * as path72 from "path";
|
|
69340
69517
|
|
|
69341
69518
|
// src/hooks/diff-scope.ts
|
|
69342
69519
|
import * as fs58 from "fs";
|
|
69343
|
-
import * as
|
|
69520
|
+
import * as path71 from "path";
|
|
69344
69521
|
function getDeclaredScope(taskId, directory) {
|
|
69345
69522
|
try {
|
|
69346
|
-
const planPath =
|
|
69523
|
+
const planPath = path71.join(directory, ".swarm", "plan.json");
|
|
69347
69524
|
if (!fs58.existsSync(planPath))
|
|
69348
69525
|
return null;
|
|
69349
69526
|
const raw = fs58.readFileSync(planPath, "utf-8");
|
|
@@ -69459,7 +69636,7 @@ var TIER_3_PATTERNS = [
|
|
|
69459
69636
|
];
|
|
69460
69637
|
function matchesTier3Pattern(files) {
|
|
69461
69638
|
for (const file3 of files) {
|
|
69462
|
-
const fileName =
|
|
69639
|
+
const fileName = path72.basename(file3);
|
|
69463
69640
|
for (const pattern of TIER_3_PATTERNS) {
|
|
69464
69641
|
if (pattern.test(fileName)) {
|
|
69465
69642
|
return true;
|
|
@@ -69473,7 +69650,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
69473
69650
|
if (hasActiveTurboMode()) {
|
|
69474
69651
|
const resolvedDir2 = workingDirectory;
|
|
69475
69652
|
try {
|
|
69476
|
-
const planPath =
|
|
69653
|
+
const planPath = path72.join(resolvedDir2, ".swarm", "plan.json");
|
|
69477
69654
|
const planRaw = fs59.readFileSync(planPath, "utf-8");
|
|
69478
69655
|
const plan = JSON.parse(planRaw);
|
|
69479
69656
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -69540,7 +69717,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
69540
69717
|
}
|
|
69541
69718
|
try {
|
|
69542
69719
|
const resolvedDir2 = workingDirectory;
|
|
69543
|
-
const planPath =
|
|
69720
|
+
const planPath = path72.join(resolvedDir2, ".swarm", "plan.json");
|
|
69544
69721
|
const planRaw = fs59.readFileSync(planPath, "utf-8");
|
|
69545
69722
|
const plan = JSON.parse(planRaw);
|
|
69546
69723
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -69723,8 +69900,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
69723
69900
|
};
|
|
69724
69901
|
}
|
|
69725
69902
|
}
|
|
69726
|
-
normalizedDir =
|
|
69727
|
-
const pathParts = normalizedDir.split(
|
|
69903
|
+
normalizedDir = path72.normalize(args2.working_directory);
|
|
69904
|
+
const pathParts = normalizedDir.split(path72.sep);
|
|
69728
69905
|
if (pathParts.includes("..")) {
|
|
69729
69906
|
return {
|
|
69730
69907
|
success: false,
|
|
@@ -69734,10 +69911,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
69734
69911
|
]
|
|
69735
69912
|
};
|
|
69736
69913
|
}
|
|
69737
|
-
const resolvedDir =
|
|
69914
|
+
const resolvedDir = path72.resolve(normalizedDir);
|
|
69738
69915
|
try {
|
|
69739
69916
|
const realPath = fs59.realpathSync(resolvedDir);
|
|
69740
|
-
const planPath =
|
|
69917
|
+
const planPath = path72.join(realPath, ".swarm", "plan.json");
|
|
69741
69918
|
if (!fs59.existsSync(planPath)) {
|
|
69742
69919
|
return {
|
|
69743
69920
|
success: false,
|
|
@@ -69771,7 +69948,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
69771
69948
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
69772
69949
|
let phaseRequiresReviewer = true;
|
|
69773
69950
|
try {
|
|
69774
|
-
const planPath =
|
|
69951
|
+
const planPath = path72.join(directory, ".swarm", "plan.json");
|
|
69775
69952
|
const planRaw = fs59.readFileSync(planPath, "utf-8");
|
|
69776
69953
|
const plan = JSON.parse(planRaw);
|
|
69777
69954
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
@@ -69836,7 +70013,7 @@ init_tool();
|
|
|
69836
70013
|
init_utils2();
|
|
69837
70014
|
init_create_tool();
|
|
69838
70015
|
import fs60 from "fs";
|
|
69839
|
-
import
|
|
70016
|
+
import path73 from "path";
|
|
69840
70017
|
function normalizeVerdict(verdict) {
|
|
69841
70018
|
switch (verdict) {
|
|
69842
70019
|
case "APPROVED":
|
|
@@ -69883,7 +70060,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
69883
70060
|
entries: [evidenceEntry]
|
|
69884
70061
|
};
|
|
69885
70062
|
const filename = "drift-verifier.json";
|
|
69886
|
-
const relativePath =
|
|
70063
|
+
const relativePath = path73.join("evidence", String(phase), filename);
|
|
69887
70064
|
let validatedPath;
|
|
69888
70065
|
try {
|
|
69889
70066
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -69894,10 +70071,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
69894
70071
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
69895
70072
|
}, null, 2);
|
|
69896
70073
|
}
|
|
69897
|
-
const evidenceDir =
|
|
70074
|
+
const evidenceDir = path73.dirname(validatedPath);
|
|
69898
70075
|
try {
|
|
69899
70076
|
await fs60.promises.mkdir(evidenceDir, { recursive: true });
|
|
69900
|
-
const tempPath =
|
|
70077
|
+
const tempPath = path73.join(evidenceDir, `.${filename}.tmp`);
|
|
69901
70078
|
await fs60.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
69902
70079
|
await fs60.promises.rename(tempPath, validatedPath);
|
|
69903
70080
|
return JSON.stringify({
|
|
@@ -70013,7 +70190,8 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
70013
70190
|
console.warn("");
|
|
70014
70191
|
}
|
|
70015
70192
|
const delegationHandler = createDelegationTrackerHook(config3, guardrailsConfig.enabled);
|
|
70016
|
-
const
|
|
70193
|
+
const authorityConfig = AuthorityConfigSchema.parse(config3.authority ?? {});
|
|
70194
|
+
const guardrailsHooks = createGuardrailsHooks(ctx.directory, undefined, guardrailsConfig, authorityConfig);
|
|
70017
70195
|
const watchdogConfig = WatchdogConfigSchema.parse(config3.watchdog ?? {});
|
|
70018
70196
|
const advisoryInjector = (sessionId, message) => {
|
|
70019
70197
|
const s = swarmState.agentSessions.get(sessionId);
|
|
@@ -70090,7 +70268,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
70090
70268
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
70091
70269
|
preflightTriggerManager = new PTM(automationConfig);
|
|
70092
70270
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
70093
|
-
const swarmDir =
|
|
70271
|
+
const swarmDir = path74.resolve(ctx.directory, ".swarm");
|
|
70094
70272
|
statusArtifact = new ASA(swarmDir);
|
|
70095
70273
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
70096
70274
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|