opencode-swarm 7.12.0 → 7.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/dist/cli/index.js +38 -14
- package/dist/commands/command-names.d.ts +4 -0
- package/dist/commands/command-names.test.d.ts +1 -0
- package/dist/commands/conflict-registry.d.ts +2 -2
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/registry.d.ts +22 -5
- package/dist/council/council-service.d.ts +3 -3
- package/dist/index.js +562 -434
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.
|
|
36
|
+
version: "7.13.1",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -57533,6 +57533,14 @@ var init_write_retro2 = __esm(() => {
|
|
|
57533
57533
|
init_write_retro();
|
|
57534
57534
|
});
|
|
57535
57535
|
|
|
57536
|
+
// src/commands/command-names.ts
|
|
57537
|
+
var COMMAND_NAMES, COMMAND_NAME_SET;
|
|
57538
|
+
var init_command_names = __esm(() => {
|
|
57539
|
+
init_registry();
|
|
57540
|
+
COMMAND_NAMES = Object.freeze(Object.keys(COMMAND_REGISTRY));
|
|
57541
|
+
COMMAND_NAME_SET = new Set(COMMAND_NAMES);
|
|
57542
|
+
});
|
|
57543
|
+
|
|
57536
57544
|
// src/commands/index.ts
|
|
57537
57545
|
var exports_commands = {};
|
|
57538
57546
|
__export(exports_commands, {
|
|
@@ -57580,7 +57588,9 @@ __export(exports_commands, {
|
|
|
57580
57588
|
createSwarmCommandHandler: () => createSwarmCommandHandler,
|
|
57581
57589
|
buildHelpText: () => buildHelpText,
|
|
57582
57590
|
VALID_COMMANDS: () => VALID_COMMANDS,
|
|
57583
|
-
COMMAND_REGISTRY: () => COMMAND_REGISTRY
|
|
57591
|
+
COMMAND_REGISTRY: () => COMMAND_REGISTRY,
|
|
57592
|
+
COMMAND_NAME_SET: () => COMMAND_NAME_SET,
|
|
57593
|
+
COMMAND_NAMES: () => COMMAND_NAMES
|
|
57584
57594
|
});
|
|
57585
57595
|
import fs30 from "node:fs";
|
|
57586
57596
|
import path46 from "node:path";
|
|
@@ -57760,6 +57770,7 @@ var init_commands = __esm(() => {
|
|
|
57760
57770
|
init_benchmark();
|
|
57761
57771
|
init_checkpoint2();
|
|
57762
57772
|
init_close();
|
|
57773
|
+
init_command_names();
|
|
57763
57774
|
init_config2();
|
|
57764
57775
|
init_council();
|
|
57765
57776
|
init_curate();
|
|
@@ -58017,11 +58028,19 @@ var init_registry = __esm(() => {
|
|
|
58017
58028
|
category: "core",
|
|
58018
58029
|
clashesWithNativeCcCommand: "/status"
|
|
58019
58030
|
},
|
|
58031
|
+
"show-plan": {
|
|
58032
|
+
handler: (ctx) => handlePlanCommand(ctx.directory, ctx.args),
|
|
58033
|
+
description: "Show current plan (optionally filter by phase number)",
|
|
58034
|
+
category: "core",
|
|
58035
|
+
args: "[phase-number]"
|
|
58036
|
+
},
|
|
58020
58037
|
plan: {
|
|
58021
58038
|
handler: (ctx) => handlePlanCommand(ctx.directory, ctx.args),
|
|
58022
|
-
description: "Show plan (
|
|
58039
|
+
description: "Show current plan (deprecated alias for /swarm show-plan)",
|
|
58023
58040
|
category: "core",
|
|
58024
|
-
clashesWithNativeCcCommand: "/plan"
|
|
58041
|
+
clashesWithNativeCcCommand: "/plan",
|
|
58042
|
+
aliasOf: "show-plan",
|
|
58043
|
+
deprecated: true
|
|
58025
58044
|
},
|
|
58026
58045
|
agents: {
|
|
58027
58046
|
handler: (ctx) => Promise.resolve(handleAgentsCommand(ctx.agents, undefined)),
|
|
@@ -58191,13 +58210,22 @@ var init_registry = __esm(() => {
|
|
|
58191
58210
|
args: "--threshold <number>, --min-commits <number>",
|
|
58192
58211
|
category: "diagnostics"
|
|
58193
58212
|
},
|
|
58194
|
-
|
|
58213
|
+
finalize: {
|
|
58195
58214
|
handler: (ctx) => handleCloseCommand(ctx.directory, ctx.args),
|
|
58196
|
-
description: "Use /swarm
|
|
58215
|
+
description: "Use /swarm finalize to finalize the swarm project and archive evidence",
|
|
58197
58216
|
details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs safe git ff-only to main. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation.",
|
|
58198
58217
|
args: "--prune-branches",
|
|
58199
58218
|
category: "core"
|
|
58200
58219
|
},
|
|
58220
|
+
close: {
|
|
58221
|
+
handler: (ctx) => handleCloseCommand(ctx.directory, ctx.args),
|
|
58222
|
+
description: "Use /swarm close (deprecated alias) to finalize and archive swarm state",
|
|
58223
|
+
details: "Deprecated alias for /swarm finalize. Preserved for backward compatibility.",
|
|
58224
|
+
args: "--prune-branches",
|
|
58225
|
+
category: "core",
|
|
58226
|
+
aliasOf: "finalize",
|
|
58227
|
+
deprecated: true
|
|
58228
|
+
},
|
|
58201
58229
|
simulate: {
|
|
58202
58230
|
handler: (ctx) => handleSimulateCommand(ctx.directory, ctx.args),
|
|
58203
58231
|
description: "Dry-run hidden coupling analysis with configurable thresholds",
|
|
@@ -58231,9 +58259,9 @@ var init_registry = __esm(() => {
|
|
|
58231
58259
|
},
|
|
58232
58260
|
council: {
|
|
58233
58261
|
handler: (ctx) => handleCouncilCommand(ctx.directory, ctx.args),
|
|
58234
|
-
description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--spec-review]",
|
|
58235
|
-
args: "<question> [--spec-review]",
|
|
58236
|
-
details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). " + "The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in opencode-swarm.json.",
|
|
58262
|
+
description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--preset <name>] [--spec-review]",
|
|
58263
|
+
args: "<question> [--preset <name>] [--spec-review]",
|
|
58264
|
+
details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). Use --preset <name> to choose a named member preset from council.general.presets. " + "The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in opencode-swarm.json.",
|
|
58237
58265
|
category: "agent"
|
|
58238
58266
|
},
|
|
58239
58267
|
"pr-review": {
|
|
@@ -58553,7 +58581,7 @@ function buildSlashCommandsList() {
|
|
|
58553
58581
|
"history",
|
|
58554
58582
|
"agents",
|
|
58555
58583
|
"config",
|
|
58556
|
-
"plan",
|
|
58584
|
+
"show-plan",
|
|
58557
58585
|
"benchmark",
|
|
58558
58586
|
"export",
|
|
58559
58587
|
"retrieve"
|
|
@@ -58569,7 +58597,7 @@ function buildSlashCommandsList() {
|
|
|
58569
58597
|
];
|
|
58570
58598
|
const COMMANDS_BY_CATEGORY = {
|
|
58571
58599
|
"Session Lifecycle": [
|
|
58572
|
-
"
|
|
58600
|
+
"finalize",
|
|
58573
58601
|
"reset",
|
|
58574
58602
|
"reset-session",
|
|
58575
58603
|
"handoff",
|
|
@@ -58579,7 +58607,7 @@ function buildSlashCommandsList() {
|
|
|
58579
58607
|
"specify",
|
|
58580
58608
|
"clarify",
|
|
58581
58609
|
"analyze",
|
|
58582
|
-
"plan",
|
|
58610
|
+
"show-plan",
|
|
58583
58611
|
"sync-plan",
|
|
58584
58612
|
"acknowledge-spec-drift",
|
|
58585
58613
|
"council"
|
|
@@ -58734,7 +58762,7 @@ All swarm commands are invoked as /swarm <subcommand>.
|
|
|
58734
58762
|
NEVER invoke a bare slash command that shares a name with a swarm subcommand.
|
|
58735
58763
|
|
|
58736
58764
|
CRITICAL CONFLICTS — bare CC command = catastrophic:
|
|
58737
|
-
/plan (CC) → Blocks all execution. /swarm plan → Reads .swarm/plan.md. USE THIS.
|
|
58765
|
+
/plan (CC) → Blocks all execution. /swarm show-plan → Reads .swarm/plan.md. USE THIS.
|
|
58738
58766
|
/reset (CC) → WIPES conversation context. /swarm reset → Clears .swarm (--confirm). USE THIS.
|
|
58739
58767
|
/checkpoint (CC) → Reverts your work. /swarm checkpoint → Project snapshots. USE THIS.
|
|
58740
58768
|
|
|
@@ -59692,7 +59720,7 @@ GREENFIELD EXEMPTION: If the work is purely greenfield (new project, no existing
|
|
|
59692
59720
|
|
|
59693
59721
|
### MODE: COUNCIL
|
|
59694
59722
|
|
|
59695
|
-
Activates when: user invokes \`/swarm council <question>\` (optionally with \`--spec-review\`).
|
|
59723
|
+
Activates when: user invokes \`/swarm council <question>\` (optionally with \`--preset <name>\` and/or \`--spec-review\`).
|
|
59696
59724
|
|
|
59697
59725
|
Purpose: convene a fixed three-agent multi-model General Council (generalist / skeptic / domain expert) for an advisory deliberation. The architect runs a curated web research pass upfront, dispatches the three agents in parallel with the gathered RESEARCH CONTEXT, routes any disagreements back for one targeted reconciliation round, and synthesizes the final user-facing answer directly.
|
|
59698
59726
|
|
|
@@ -68701,12 +68729,12 @@ ${content.substring(endIndex + 1)}`;
|
|
|
68701
68729
|
// src/commands/conflict-registry.ts
|
|
68702
68730
|
var CLAUDE_CODE_CONFLICTS = [
|
|
68703
68731
|
{
|
|
68704
|
-
swarmCommand: "plan",
|
|
68732
|
+
swarmCommand: "show-plan",
|
|
68705
68733
|
ccCommand: "/plan",
|
|
68706
68734
|
severity: "CRITICAL",
|
|
68707
68735
|
ccBehavior: "Enters Claude Code plan mode — Claude proposes all actions before executing them",
|
|
68708
68736
|
swarmBehavior: "Displays the current .swarm/plan.md task list",
|
|
68709
|
-
disambiguationNote: "Use /swarm plan to read the swarm task plan. NEVER invoke the bare /plan command — it enters Claude Code plan mode and blocks execution."
|
|
68737
|
+
disambiguationNote: "Use /swarm show-plan to read the swarm task plan. NEVER invoke the bare /plan command — it enters Claude Code plan mode and blocks execution."
|
|
68710
68738
|
},
|
|
68711
68739
|
{
|
|
68712
68740
|
swarmCommand: "reset",
|
|
@@ -81869,10 +81897,6 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
81869
81897
|
}
|
|
81870
81898
|
}
|
|
81871
81899
|
|
|
81872
|
-
// src/council/council-service.ts
|
|
81873
|
-
import fs65 from "node:fs";
|
|
81874
|
-
import path87 from "node:path";
|
|
81875
|
-
|
|
81876
81900
|
// src/council/types.ts
|
|
81877
81901
|
var COUNCIL_DEFAULTS = {
|
|
81878
81902
|
enabled: false,
|
|
@@ -81997,7 +82021,7 @@ function buildUnifiedFeedback(taskId, verdict, vetoedBy, requiredFixes, advisory
|
|
|
81997
82021
|
return lines.join(`
|
|
81998
82022
|
`);
|
|
81999
82023
|
}
|
|
82000
|
-
function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, roundNumber, config3 = {},
|
|
82024
|
+
function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, roundNumber, config3 = {}, _workingDir) {
|
|
82001
82025
|
const cfg = { ...COUNCIL_DEFAULTS, ...config3 };
|
|
82002
82026
|
const timestamp = new Date().toISOString();
|
|
82003
82027
|
const scope = "phase";
|
|
@@ -82030,47 +82054,6 @@ function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, rou
|
|
|
82030
82054
|
const allCriteriaMet = allUnmetIds.size === 0 && verdicts.length > 0;
|
|
82031
82055
|
const unifiedFeedbackMd = buildPhaseCouncilFeedback(phaseNumber, phaseSummary, overallVerdict, rejectingMembers, requiredFixes, advisoryFindings, unresolvedConflicts, roundNumber, cfg.maxRounds);
|
|
82032
82056
|
const evidencePath = `.swarm/evidence/${phaseNumber}/phase-council.json`;
|
|
82033
|
-
const baseDir = workingDir ?? process.cwd();
|
|
82034
|
-
const evidenceDir = path87.join(baseDir, ".swarm", "evidence", String(phaseNumber));
|
|
82035
|
-
fs65.mkdirSync(evidenceDir, { recursive: true });
|
|
82036
|
-
const evidenceFile = path87.join(evidenceDir, "phase-council.json");
|
|
82037
|
-
const evidenceBundle = {
|
|
82038
|
-
entries: [
|
|
82039
|
-
{
|
|
82040
|
-
type: "phase-council",
|
|
82041
|
-
phase_number: phaseNumber,
|
|
82042
|
-
scope: "phase",
|
|
82043
|
-
timestamp,
|
|
82044
|
-
verdict: overallVerdict,
|
|
82045
|
-
quorumSize,
|
|
82046
|
-
phaseSummary,
|
|
82047
|
-
requiredFixes: requiredFixes.map((f) => ({
|
|
82048
|
-
severity: f.severity,
|
|
82049
|
-
category: f.category,
|
|
82050
|
-
location: f.location,
|
|
82051
|
-
detail: f.detail,
|
|
82052
|
-
evidence: f.evidence
|
|
82053
|
-
})),
|
|
82054
|
-
advisoryNotes,
|
|
82055
|
-
advisoryFindings: advisoryFindings.map((f) => ({
|
|
82056
|
-
severity: f.severity,
|
|
82057
|
-
category: f.category,
|
|
82058
|
-
location: f.location,
|
|
82059
|
-
detail: f.detail,
|
|
82060
|
-
evidence: f.evidence
|
|
82061
|
-
})),
|
|
82062
|
-
roundNumber,
|
|
82063
|
-
allCriteriaMet
|
|
82064
|
-
}
|
|
82065
|
-
]
|
|
82066
|
-
};
|
|
82067
|
-
try {
|
|
82068
|
-
const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
|
|
82069
|
-
fs65.writeFileSync(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
82070
|
-
fs65.renameSync(tempFile, evidenceFile);
|
|
82071
|
-
} catch (writeErr) {
|
|
82072
|
-
console.warn(`[phase-council] Failed to write phase-council evidence to ${evidenceFile}: ${writeErr instanceof Error ? writeErr.message : String(writeErr)}`);
|
|
82073
|
-
}
|
|
82074
82057
|
return {
|
|
82075
82058
|
phaseNumber,
|
|
82076
82059
|
scope,
|
|
@@ -82302,8 +82285,8 @@ var submit_council_verdicts = createSwarmTool({
|
|
|
82302
82285
|
// src/tools/convene-general-council.ts
|
|
82303
82286
|
init_zod();
|
|
82304
82287
|
init_loader();
|
|
82305
|
-
import * as
|
|
82306
|
-
import * as
|
|
82288
|
+
import * as fs65 from "node:fs";
|
|
82289
|
+
import * as path87 from "node:path";
|
|
82307
82290
|
|
|
82308
82291
|
// src/council/general-council-advisory.ts
|
|
82309
82292
|
var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
|
|
@@ -82731,13 +82714,13 @@ var convene_general_council = createSwarmTool({
|
|
|
82731
82714
|
const round1 = input.round1Responses;
|
|
82732
82715
|
const round2 = input.round2Responses ?? [];
|
|
82733
82716
|
const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
|
|
82734
|
-
const evidenceDir =
|
|
82717
|
+
const evidenceDir = path87.join(workingDir, ".swarm", "council", "general");
|
|
82735
82718
|
const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
|
|
82736
82719
|
const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
|
|
82737
|
-
const evidencePath =
|
|
82720
|
+
const evidencePath = path87.join(evidenceDir, evidenceFile);
|
|
82738
82721
|
try {
|
|
82739
|
-
await
|
|
82740
|
-
await
|
|
82722
|
+
await fs65.promises.mkdir(evidenceDir, { recursive: true });
|
|
82723
|
+
await fs65.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
|
|
82741
82724
|
} catch (err2) {
|
|
82742
82725
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
82743
82726
|
console.warn(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`);
|
|
@@ -82978,8 +82961,8 @@ init_scope_persistence();
|
|
|
82978
82961
|
init_state();
|
|
82979
82962
|
init_task_id();
|
|
82980
82963
|
init_create_tool();
|
|
82981
|
-
import * as
|
|
82982
|
-
import * as
|
|
82964
|
+
import * as fs66 from "node:fs";
|
|
82965
|
+
import * as path88 from "node:path";
|
|
82983
82966
|
function validateTaskIdFormat2(taskId) {
|
|
82984
82967
|
return validateTaskIdFormat(taskId);
|
|
82985
82968
|
}
|
|
@@ -83053,8 +83036,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83053
83036
|
};
|
|
83054
83037
|
}
|
|
83055
83038
|
}
|
|
83056
|
-
normalizedDir =
|
|
83057
|
-
const pathParts = normalizedDir.split(
|
|
83039
|
+
normalizedDir = path88.normalize(args2.working_directory);
|
|
83040
|
+
const pathParts = normalizedDir.split(path88.sep);
|
|
83058
83041
|
if (pathParts.includes("..")) {
|
|
83059
83042
|
return {
|
|
83060
83043
|
success: false,
|
|
@@ -83064,11 +83047,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83064
83047
|
]
|
|
83065
83048
|
};
|
|
83066
83049
|
}
|
|
83067
|
-
const resolvedDir =
|
|
83050
|
+
const resolvedDir = path88.resolve(normalizedDir);
|
|
83068
83051
|
try {
|
|
83069
|
-
const realPath =
|
|
83070
|
-
const planPath2 =
|
|
83071
|
-
if (!
|
|
83052
|
+
const realPath = fs66.realpathSync(resolvedDir);
|
|
83053
|
+
const planPath2 = path88.join(realPath, ".swarm", "plan.json");
|
|
83054
|
+
if (!fs66.existsSync(planPath2)) {
|
|
83072
83055
|
return {
|
|
83073
83056
|
success: false,
|
|
83074
83057
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -83091,8 +83074,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83091
83074
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
83092
83075
|
}
|
|
83093
83076
|
const directory = normalizedDir || fallbackDir;
|
|
83094
|
-
const planPath =
|
|
83095
|
-
if (!
|
|
83077
|
+
const planPath = path88.resolve(directory, ".swarm", "plan.json");
|
|
83078
|
+
if (!fs66.existsSync(planPath)) {
|
|
83096
83079
|
return {
|
|
83097
83080
|
success: false,
|
|
83098
83081
|
message: "No plan found",
|
|
@@ -83101,7 +83084,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83101
83084
|
}
|
|
83102
83085
|
let planContent;
|
|
83103
83086
|
try {
|
|
83104
|
-
planContent = JSON.parse(
|
|
83087
|
+
planContent = JSON.parse(fs66.readFileSync(planPath, "utf-8"));
|
|
83105
83088
|
} catch {
|
|
83106
83089
|
return {
|
|
83107
83090
|
success: false,
|
|
@@ -83131,8 +83114,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83131
83114
|
const normalizeErrors = [];
|
|
83132
83115
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
83133
83116
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
83134
|
-
if (
|
|
83135
|
-
const relativePath =
|
|
83117
|
+
if (path88.isAbsolute(file3)) {
|
|
83118
|
+
const relativePath = path88.relative(dir, file3).replace(/\\/g, "/");
|
|
83136
83119
|
if (relativePath.startsWith("..")) {
|
|
83137
83120
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
83138
83121
|
return file3;
|
|
@@ -83192,8 +83175,8 @@ var declare_scope = createSwarmTool({
|
|
|
83192
83175
|
// src/tools/diff.ts
|
|
83193
83176
|
init_zod();
|
|
83194
83177
|
import * as child_process7 from "node:child_process";
|
|
83195
|
-
import * as
|
|
83196
|
-
import * as
|
|
83178
|
+
import * as fs67 from "node:fs";
|
|
83179
|
+
import * as path89 from "node:path";
|
|
83197
83180
|
init_create_tool();
|
|
83198
83181
|
var MAX_DIFF_LINES = 500;
|
|
83199
83182
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -83222,20 +83205,20 @@ function validateBase(base) {
|
|
|
83222
83205
|
function validatePaths(paths) {
|
|
83223
83206
|
if (!paths)
|
|
83224
83207
|
return null;
|
|
83225
|
-
for (const
|
|
83226
|
-
if (!
|
|
83208
|
+
for (const path90 of paths) {
|
|
83209
|
+
if (!path90 || path90.length === 0) {
|
|
83227
83210
|
return "empty path not allowed";
|
|
83228
83211
|
}
|
|
83229
|
-
if (
|
|
83212
|
+
if (path90.length > MAX_PATH_LENGTH) {
|
|
83230
83213
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
83231
83214
|
}
|
|
83232
|
-
if (SHELL_METACHARACTERS2.test(
|
|
83215
|
+
if (SHELL_METACHARACTERS2.test(path90)) {
|
|
83233
83216
|
return "path contains shell metacharacters";
|
|
83234
83217
|
}
|
|
83235
|
-
if (
|
|
83218
|
+
if (path90.startsWith("-")) {
|
|
83236
83219
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
83237
83220
|
}
|
|
83238
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
83221
|
+
if (CONTROL_CHAR_PATTERN2.test(path90)) {
|
|
83239
83222
|
return "path contains control characters";
|
|
83240
83223
|
}
|
|
83241
83224
|
}
|
|
@@ -83343,8 +83326,8 @@ var diff = createSwarmTool({
|
|
|
83343
83326
|
if (parts2.length >= 3) {
|
|
83344
83327
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
83345
83328
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
83346
|
-
const
|
|
83347
|
-
files.push({ path:
|
|
83329
|
+
const path90 = parts2[2];
|
|
83330
|
+
files.push({ path: path90, additions, deletions });
|
|
83348
83331
|
}
|
|
83349
83332
|
}
|
|
83350
83333
|
const contractChanges = [];
|
|
@@ -83384,7 +83367,7 @@ var diff = createSwarmTool({
|
|
|
83384
83367
|
} else if (base === "unstaged") {
|
|
83385
83368
|
const oldRef = `:${file3.path}`;
|
|
83386
83369
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
83387
|
-
newContent =
|
|
83370
|
+
newContent = fs67.readFileSync(path89.join(directory, file3.path), "utf-8");
|
|
83388
83371
|
} else {
|
|
83389
83372
|
const oldRef = `${base}:${file3.path}`;
|
|
83390
83373
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
@@ -83458,8 +83441,8 @@ var diff = createSwarmTool({
|
|
|
83458
83441
|
// src/tools/diff-summary.ts
|
|
83459
83442
|
init_zod();
|
|
83460
83443
|
import * as child_process8 from "node:child_process";
|
|
83461
|
-
import * as
|
|
83462
|
-
import * as
|
|
83444
|
+
import * as fs68 from "node:fs";
|
|
83445
|
+
import * as path90 from "node:path";
|
|
83463
83446
|
init_create_tool();
|
|
83464
83447
|
var diff_summary = createSwarmTool({
|
|
83465
83448
|
description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
|
|
@@ -83507,7 +83490,7 @@ var diff_summary = createSwarmTool({
|
|
|
83507
83490
|
}
|
|
83508
83491
|
try {
|
|
83509
83492
|
let oldContent;
|
|
83510
|
-
const newContent =
|
|
83493
|
+
const newContent = fs68.readFileSync(path90.join(workingDir, filePath), "utf-8");
|
|
83511
83494
|
if (fileExistsInHead) {
|
|
83512
83495
|
oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
|
|
83513
83496
|
encoding: "utf-8",
|
|
@@ -83735,8 +83718,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
83735
83718
|
init_zod();
|
|
83736
83719
|
init_create_tool();
|
|
83737
83720
|
init_path_security();
|
|
83738
|
-
import * as
|
|
83739
|
-
import * as
|
|
83721
|
+
import * as fs69 from "node:fs";
|
|
83722
|
+
import * as path91 from "node:path";
|
|
83740
83723
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
83741
83724
|
var MAX_EVIDENCE_FILES = 1000;
|
|
83742
83725
|
var EVIDENCE_DIR3 = ".swarm/evidence";
|
|
@@ -83763,9 +83746,9 @@ function validateRequiredTypes(input) {
|
|
|
83763
83746
|
return null;
|
|
83764
83747
|
}
|
|
83765
83748
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
83766
|
-
const normalizedCwd =
|
|
83767
|
-
const swarmPath =
|
|
83768
|
-
const normalizedPath =
|
|
83749
|
+
const normalizedCwd = path91.resolve(cwd);
|
|
83750
|
+
const swarmPath = path91.join(normalizedCwd, ".swarm");
|
|
83751
|
+
const normalizedPath = path91.resolve(filePath);
|
|
83769
83752
|
return normalizedPath.startsWith(swarmPath);
|
|
83770
83753
|
}
|
|
83771
83754
|
function parseCompletedTasks(planContent) {
|
|
@@ -83781,12 +83764,12 @@ function parseCompletedTasks(planContent) {
|
|
|
83781
83764
|
}
|
|
83782
83765
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
83783
83766
|
const evidence = [];
|
|
83784
|
-
if (!
|
|
83767
|
+
if (!fs69.existsSync(evidenceDir) || !fs69.statSync(evidenceDir).isDirectory()) {
|
|
83785
83768
|
return evidence;
|
|
83786
83769
|
}
|
|
83787
83770
|
let files;
|
|
83788
83771
|
try {
|
|
83789
|
-
files =
|
|
83772
|
+
files = fs69.readdirSync(evidenceDir);
|
|
83790
83773
|
} catch {
|
|
83791
83774
|
return evidence;
|
|
83792
83775
|
}
|
|
@@ -83795,14 +83778,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
83795
83778
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
83796
83779
|
continue;
|
|
83797
83780
|
}
|
|
83798
|
-
const filePath =
|
|
83781
|
+
const filePath = path91.join(evidenceDir, filename);
|
|
83799
83782
|
try {
|
|
83800
|
-
const resolvedPath =
|
|
83801
|
-
const evidenceDirResolved =
|
|
83783
|
+
const resolvedPath = path91.resolve(filePath);
|
|
83784
|
+
const evidenceDirResolved = path91.resolve(evidenceDir);
|
|
83802
83785
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
83803
83786
|
continue;
|
|
83804
83787
|
}
|
|
83805
|
-
const stat7 =
|
|
83788
|
+
const stat7 = fs69.lstatSync(filePath);
|
|
83806
83789
|
if (!stat7.isFile()) {
|
|
83807
83790
|
continue;
|
|
83808
83791
|
}
|
|
@@ -83811,7 +83794,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
83811
83794
|
}
|
|
83812
83795
|
let fileStat;
|
|
83813
83796
|
try {
|
|
83814
|
-
fileStat =
|
|
83797
|
+
fileStat = fs69.statSync(filePath);
|
|
83815
83798
|
if (fileStat.size > MAX_FILE_SIZE_BYTES6) {
|
|
83816
83799
|
continue;
|
|
83817
83800
|
}
|
|
@@ -83820,7 +83803,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
83820
83803
|
}
|
|
83821
83804
|
let content;
|
|
83822
83805
|
try {
|
|
83823
|
-
content =
|
|
83806
|
+
content = fs69.readFileSync(filePath, "utf-8");
|
|
83824
83807
|
} catch {
|
|
83825
83808
|
continue;
|
|
83826
83809
|
}
|
|
@@ -83916,7 +83899,7 @@ var evidence_check = createSwarmTool({
|
|
|
83916
83899
|
return JSON.stringify(errorResult, null, 2);
|
|
83917
83900
|
}
|
|
83918
83901
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
83919
|
-
const planPath =
|
|
83902
|
+
const planPath = path91.join(cwd, PLAN_FILE);
|
|
83920
83903
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
83921
83904
|
const errorResult = {
|
|
83922
83905
|
error: "plan file path validation failed",
|
|
@@ -83930,7 +83913,7 @@ var evidence_check = createSwarmTool({
|
|
|
83930
83913
|
}
|
|
83931
83914
|
let planContent;
|
|
83932
83915
|
try {
|
|
83933
|
-
planContent =
|
|
83916
|
+
planContent = fs69.readFileSync(planPath, "utf-8");
|
|
83934
83917
|
} catch {
|
|
83935
83918
|
const result2 = {
|
|
83936
83919
|
message: "No completed tasks found in plan.",
|
|
@@ -83948,7 +83931,7 @@ var evidence_check = createSwarmTool({
|
|
|
83948
83931
|
};
|
|
83949
83932
|
return JSON.stringify(result2, null, 2);
|
|
83950
83933
|
}
|
|
83951
|
-
const evidenceDir =
|
|
83934
|
+
const evidenceDir = path91.join(cwd, EVIDENCE_DIR3);
|
|
83952
83935
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
83953
83936
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
83954
83937
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -83965,8 +83948,8 @@ var evidence_check = createSwarmTool({
|
|
|
83965
83948
|
// src/tools/file-extractor.ts
|
|
83966
83949
|
init_zod();
|
|
83967
83950
|
init_create_tool();
|
|
83968
|
-
import * as
|
|
83969
|
-
import * as
|
|
83951
|
+
import * as fs70 from "node:fs";
|
|
83952
|
+
import * as path92 from "node:path";
|
|
83970
83953
|
var EXT_MAP = {
|
|
83971
83954
|
python: ".py",
|
|
83972
83955
|
py: ".py",
|
|
@@ -84028,8 +84011,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
84028
84011
|
execute: async (args2, directory) => {
|
|
84029
84012
|
const { content, output_dir, prefix } = args2;
|
|
84030
84013
|
const targetDir = output_dir || directory;
|
|
84031
|
-
if (!
|
|
84032
|
-
|
|
84014
|
+
if (!fs70.existsSync(targetDir)) {
|
|
84015
|
+
fs70.mkdirSync(targetDir, { recursive: true });
|
|
84033
84016
|
}
|
|
84034
84017
|
if (!content) {
|
|
84035
84018
|
return "Error: content is required";
|
|
@@ -84047,16 +84030,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
84047
84030
|
if (prefix) {
|
|
84048
84031
|
filename = `${prefix}_${filename}`;
|
|
84049
84032
|
}
|
|
84050
|
-
let filepath =
|
|
84051
|
-
const base =
|
|
84052
|
-
const ext =
|
|
84033
|
+
let filepath = path92.join(targetDir, filename);
|
|
84034
|
+
const base = path92.basename(filepath, path92.extname(filepath));
|
|
84035
|
+
const ext = path92.extname(filepath);
|
|
84053
84036
|
let counter = 1;
|
|
84054
|
-
while (
|
|
84055
|
-
filepath =
|
|
84037
|
+
while (fs70.existsSync(filepath)) {
|
|
84038
|
+
filepath = path92.join(targetDir, `${base}_${counter}${ext}`);
|
|
84056
84039
|
counter++;
|
|
84057
84040
|
}
|
|
84058
84041
|
try {
|
|
84059
|
-
|
|
84042
|
+
fs70.writeFileSync(filepath, code.trim(), "utf-8");
|
|
84060
84043
|
savedFiles.push(filepath);
|
|
84061
84044
|
} catch (error93) {
|
|
84062
84045
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -84309,8 +84292,8 @@ var gitingest = createSwarmTool({
|
|
|
84309
84292
|
init_zod();
|
|
84310
84293
|
init_create_tool();
|
|
84311
84294
|
init_path_security();
|
|
84312
|
-
import * as
|
|
84313
|
-
import * as
|
|
84295
|
+
import * as fs71 from "node:fs";
|
|
84296
|
+
import * as path93 from "node:path";
|
|
84314
84297
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
84315
84298
|
var MAX_SYMBOL_LENGTH = 256;
|
|
84316
84299
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -84358,7 +84341,7 @@ function validateSymbolInput(symbol3) {
|
|
|
84358
84341
|
return null;
|
|
84359
84342
|
}
|
|
84360
84343
|
function isBinaryFile2(filePath, buffer) {
|
|
84361
|
-
const ext =
|
|
84344
|
+
const ext = path93.extname(filePath).toLowerCase();
|
|
84362
84345
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
84363
84346
|
return false;
|
|
84364
84347
|
}
|
|
@@ -84382,15 +84365,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
84382
84365
|
const imports = [];
|
|
84383
84366
|
let _resolvedTarget;
|
|
84384
84367
|
try {
|
|
84385
|
-
_resolvedTarget =
|
|
84368
|
+
_resolvedTarget = path93.resolve(targetFile);
|
|
84386
84369
|
} catch {
|
|
84387
84370
|
_resolvedTarget = targetFile;
|
|
84388
84371
|
}
|
|
84389
|
-
const targetBasename =
|
|
84372
|
+
const targetBasename = path93.basename(targetFile, path93.extname(targetFile));
|
|
84390
84373
|
const targetWithExt = targetFile;
|
|
84391
84374
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
84392
|
-
const normalizedTargetWithExt =
|
|
84393
|
-
const normalizedTargetWithoutExt =
|
|
84375
|
+
const normalizedTargetWithExt = path93.normalize(targetWithExt).replace(/\\/g, "/");
|
|
84376
|
+
const normalizedTargetWithoutExt = path93.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
84394
84377
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
84395
84378
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
84396
84379
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -84413,9 +84396,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
84413
84396
|
}
|
|
84414
84397
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
84415
84398
|
let isMatch = false;
|
|
84416
|
-
const _targetDir =
|
|
84417
|
-
const targetExt =
|
|
84418
|
-
const targetBasenameNoExt =
|
|
84399
|
+
const _targetDir = path93.dirname(targetFile);
|
|
84400
|
+
const targetExt = path93.extname(targetFile);
|
|
84401
|
+
const targetBasenameNoExt = path93.basename(targetFile, targetExt);
|
|
84419
84402
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
84420
84403
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
84421
84404
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -84472,7 +84455,7 @@ var SKIP_DIRECTORIES4 = new Set([
|
|
|
84472
84455
|
function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
84473
84456
|
let entries;
|
|
84474
84457
|
try {
|
|
84475
|
-
entries =
|
|
84458
|
+
entries = fs71.readdirSync(dir);
|
|
84476
84459
|
} catch (e) {
|
|
84477
84460
|
stats.fileErrors.push({
|
|
84478
84461
|
path: dir,
|
|
@@ -84483,13 +84466,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
84483
84466
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
84484
84467
|
for (const entry of entries) {
|
|
84485
84468
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
84486
|
-
stats.skippedDirs.push(
|
|
84469
|
+
stats.skippedDirs.push(path93.join(dir, entry));
|
|
84487
84470
|
continue;
|
|
84488
84471
|
}
|
|
84489
|
-
const fullPath =
|
|
84472
|
+
const fullPath = path93.join(dir, entry);
|
|
84490
84473
|
let stat7;
|
|
84491
84474
|
try {
|
|
84492
|
-
stat7 =
|
|
84475
|
+
stat7 = fs71.statSync(fullPath);
|
|
84493
84476
|
} catch (e) {
|
|
84494
84477
|
stats.fileErrors.push({
|
|
84495
84478
|
path: fullPath,
|
|
@@ -84500,7 +84483,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
84500
84483
|
if (stat7.isDirectory()) {
|
|
84501
84484
|
findSourceFiles2(fullPath, files, stats);
|
|
84502
84485
|
} else if (stat7.isFile()) {
|
|
84503
|
-
const ext =
|
|
84486
|
+
const ext = path93.extname(fullPath).toLowerCase();
|
|
84504
84487
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
84505
84488
|
files.push(fullPath);
|
|
84506
84489
|
}
|
|
@@ -84557,8 +84540,8 @@ var imports = createSwarmTool({
|
|
|
84557
84540
|
return JSON.stringify(errorResult, null, 2);
|
|
84558
84541
|
}
|
|
84559
84542
|
try {
|
|
84560
|
-
const targetFile =
|
|
84561
|
-
if (!
|
|
84543
|
+
const targetFile = path93.resolve(file3);
|
|
84544
|
+
if (!fs71.existsSync(targetFile)) {
|
|
84562
84545
|
const errorResult = {
|
|
84563
84546
|
error: `target file not found: ${file3}`,
|
|
84564
84547
|
target: file3,
|
|
@@ -84568,7 +84551,7 @@ var imports = createSwarmTool({
|
|
|
84568
84551
|
};
|
|
84569
84552
|
return JSON.stringify(errorResult, null, 2);
|
|
84570
84553
|
}
|
|
84571
|
-
const targetStat =
|
|
84554
|
+
const targetStat = fs71.statSync(targetFile);
|
|
84572
84555
|
if (!targetStat.isFile()) {
|
|
84573
84556
|
const errorResult = {
|
|
84574
84557
|
error: "target must be a file, not a directory",
|
|
@@ -84579,7 +84562,7 @@ var imports = createSwarmTool({
|
|
|
84579
84562
|
};
|
|
84580
84563
|
return JSON.stringify(errorResult, null, 2);
|
|
84581
84564
|
}
|
|
84582
|
-
const baseDir =
|
|
84565
|
+
const baseDir = path93.dirname(targetFile);
|
|
84583
84566
|
const scanStats = {
|
|
84584
84567
|
skippedDirs: [],
|
|
84585
84568
|
skippedFiles: 0,
|
|
@@ -84594,12 +84577,12 @@ var imports = createSwarmTool({
|
|
|
84594
84577
|
if (consumers.length >= MAX_CONSUMERS)
|
|
84595
84578
|
break;
|
|
84596
84579
|
try {
|
|
84597
|
-
const stat7 =
|
|
84580
|
+
const stat7 = fs71.statSync(filePath);
|
|
84598
84581
|
if (stat7.size > MAX_FILE_SIZE_BYTES7) {
|
|
84599
84582
|
skippedFileCount++;
|
|
84600
84583
|
continue;
|
|
84601
84584
|
}
|
|
84602
|
-
const buffer =
|
|
84585
|
+
const buffer = fs71.readFileSync(filePath);
|
|
84603
84586
|
if (isBinaryFile2(filePath, buffer)) {
|
|
84604
84587
|
skippedFileCount++;
|
|
84605
84588
|
continue;
|
|
@@ -85175,30 +85158,30 @@ init_config();
|
|
|
85175
85158
|
init_schema();
|
|
85176
85159
|
init_qa_gate_profile();
|
|
85177
85160
|
init_manager2();
|
|
85178
|
-
import * as
|
|
85179
|
-
import * as
|
|
85161
|
+
import * as fs74 from "node:fs";
|
|
85162
|
+
import * as path96 from "node:path";
|
|
85180
85163
|
|
|
85181
85164
|
// src/full-auto/phase-approval.ts
|
|
85182
85165
|
init_utils2();
|
|
85183
85166
|
init_logger();
|
|
85184
85167
|
init_state2();
|
|
85185
|
-
import * as
|
|
85186
|
-
import * as
|
|
85168
|
+
import * as fs72 from "node:fs";
|
|
85169
|
+
import * as path94 from "node:path";
|
|
85187
85170
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
85188
85171
|
function readEvidenceDir(directory, phase) {
|
|
85189
85172
|
try {
|
|
85190
|
-
const dirPath = validateSwarmPath(directory,
|
|
85191
|
-
if (!
|
|
85173
|
+
const dirPath = validateSwarmPath(directory, path94.posix.join("evidence", String(phase)));
|
|
85174
|
+
if (!fs72.existsSync(dirPath))
|
|
85192
85175
|
return [];
|
|
85193
|
-
const entries =
|
|
85194
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
85176
|
+
const entries = fs72.readdirSync(dirPath);
|
|
85177
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path94.join(dirPath, e));
|
|
85195
85178
|
} catch {
|
|
85196
85179
|
return [];
|
|
85197
85180
|
}
|
|
85198
85181
|
}
|
|
85199
85182
|
function parseEvidence(filePath) {
|
|
85200
85183
|
try {
|
|
85201
|
-
const raw =
|
|
85184
|
+
const raw = fs72.readFileSync(filePath, "utf-8");
|
|
85202
85185
|
const parsed = JSON.parse(raw);
|
|
85203
85186
|
return parsed;
|
|
85204
85187
|
} catch (error93) {
|
|
@@ -85287,9 +85270,9 @@ function verifyFullAutoPhaseApproval(directory, sessionID, phase, config3) {
|
|
|
85287
85270
|
function phaseIsExplicitlyNonCode(directory, phase) {
|
|
85288
85271
|
try {
|
|
85289
85272
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
85290
|
-
if (!
|
|
85273
|
+
if (!fs72.existsSync(planPath))
|
|
85291
85274
|
return false;
|
|
85292
|
-
const raw =
|
|
85275
|
+
const raw = fs72.readFileSync(planPath, "utf-8");
|
|
85293
85276
|
const plan = JSON.parse(raw);
|
|
85294
85277
|
const phases = Array.isArray(plan.phases) ? plan.phases : [];
|
|
85295
85278
|
const entry = phases.find((p) => p.id === phase || p.phase === phase);
|
|
@@ -85329,20 +85312,20 @@ init_file_locks();
|
|
|
85329
85312
|
init_plan_schema();
|
|
85330
85313
|
init_ledger();
|
|
85331
85314
|
init_manager();
|
|
85332
|
-
import * as
|
|
85333
|
-
import * as
|
|
85315
|
+
import * as fs73 from "node:fs";
|
|
85316
|
+
import * as path95 from "node:path";
|
|
85334
85317
|
async function writeCheckpoint(directory) {
|
|
85335
85318
|
try {
|
|
85336
85319
|
const plan = await loadPlan(directory);
|
|
85337
85320
|
if (!plan)
|
|
85338
85321
|
return;
|
|
85339
|
-
const swarmDir =
|
|
85340
|
-
|
|
85341
|
-
const jsonPath =
|
|
85342
|
-
const mdPath =
|
|
85343
|
-
|
|
85322
|
+
const swarmDir = path95.join(directory, ".swarm");
|
|
85323
|
+
fs73.mkdirSync(swarmDir, { recursive: true });
|
|
85324
|
+
const jsonPath = path95.join(swarmDir, "SWARM_PLAN.json");
|
|
85325
|
+
const mdPath = path95.join(swarmDir, "SWARM_PLAN.md");
|
|
85326
|
+
fs73.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
85344
85327
|
const md = derivePlanMarkdown(plan);
|
|
85345
|
-
|
|
85328
|
+
fs73.writeFileSync(mdPath, md, "utf8");
|
|
85346
85329
|
} catch (error93) {
|
|
85347
85330
|
console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
85348
85331
|
}
|
|
@@ -85574,8 +85557,8 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85574
85557
|
let driftCheckEnabled = true;
|
|
85575
85558
|
let driftHasSpecMd = false;
|
|
85576
85559
|
try {
|
|
85577
|
-
const specMdPath =
|
|
85578
|
-
driftHasSpecMd =
|
|
85560
|
+
const specMdPath = path96.join(dir, ".swarm", "spec.md");
|
|
85561
|
+
driftHasSpecMd = fs74.existsSync(specMdPath);
|
|
85579
85562
|
const gatePlan = await loadPlan(dir);
|
|
85580
85563
|
if (gatePlan) {
|
|
85581
85564
|
const gatePlanId = derivePlanId(gatePlan);
|
|
@@ -85596,9 +85579,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85596
85579
|
} else {
|
|
85597
85580
|
let phaseType;
|
|
85598
85581
|
try {
|
|
85599
|
-
const planPath =
|
|
85600
|
-
if (
|
|
85601
|
-
const planRaw =
|
|
85582
|
+
const planPath = path96.join(dir, ".swarm", "plan.json");
|
|
85583
|
+
if (fs74.existsSync(planPath)) {
|
|
85584
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
85602
85585
|
const plan = JSON.parse(planRaw);
|
|
85603
85586
|
const targetPhase = plan.phases?.find((p) => p.id === phase);
|
|
85604
85587
|
phaseType = targetPhase?.type;
|
|
@@ -85609,11 +85592,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85609
85592
|
warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
|
|
85610
85593
|
} else {
|
|
85611
85594
|
try {
|
|
85612
|
-
const driftEvidencePath =
|
|
85595
|
+
const driftEvidencePath = path96.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
85613
85596
|
let driftVerdictFound = false;
|
|
85614
85597
|
let driftVerdictApproved = false;
|
|
85615
85598
|
try {
|
|
85616
|
-
const driftEvidenceContent =
|
|
85599
|
+
const driftEvidenceContent = fs74.readFileSync(driftEvidencePath, "utf-8");
|
|
85617
85600
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
85618
85601
|
const entries = driftEvidence.entries ?? [];
|
|
85619
85602
|
for (const entry of entries) {
|
|
@@ -85647,9 +85630,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85647
85630
|
let incompleteTaskCount = 0;
|
|
85648
85631
|
let planParseable = false;
|
|
85649
85632
|
try {
|
|
85650
|
-
const planPath =
|
|
85651
|
-
if (
|
|
85652
|
-
const planRaw =
|
|
85633
|
+
const planPath = path96.join(dir, ".swarm", "plan.json");
|
|
85634
|
+
if (fs74.existsSync(planPath)) {
|
|
85635
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
85653
85636
|
const plan = JSON.parse(planRaw);
|
|
85654
85637
|
planParseable = true;
|
|
85655
85638
|
const planPhase = plan.phases?.find((p) => p.id === phase);
|
|
@@ -85714,11 +85697,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85714
85697
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
85715
85698
|
const effective = getEffectiveGates(profile, overrides);
|
|
85716
85699
|
if (effective.hallucination_guard === true) {
|
|
85717
|
-
const hgPath =
|
|
85700
|
+
const hgPath = path96.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
85718
85701
|
let hgVerdictFound = false;
|
|
85719
85702
|
let hgVerdictApproved = false;
|
|
85720
85703
|
try {
|
|
85721
|
-
const hgContent =
|
|
85704
|
+
const hgContent = fs74.readFileSync(hgPath, "utf-8");
|
|
85722
85705
|
const hgBundle = JSON.parse(hgContent);
|
|
85723
85706
|
for (const entry of hgBundle.entries ?? []) {
|
|
85724
85707
|
if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
|
|
@@ -85786,11 +85769,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85786
85769
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
85787
85770
|
const effective = getEffectiveGates(profile, overrides);
|
|
85788
85771
|
if (effective.mutation_test === true) {
|
|
85789
|
-
const mgPath =
|
|
85772
|
+
const mgPath = path96.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
85790
85773
|
let mgVerdictFound = false;
|
|
85791
85774
|
let mgVerdict;
|
|
85792
85775
|
try {
|
|
85793
|
-
const mgContent =
|
|
85776
|
+
const mgContent = fs74.readFileSync(mgPath, "utf-8");
|
|
85794
85777
|
const mgBundle = JSON.parse(mgContent);
|
|
85795
85778
|
for (const entry of mgBundle.entries ?? []) {
|
|
85796
85779
|
if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
|
|
@@ -85860,14 +85843,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85860
85843
|
const effective = getEffectiveGates(profile, overrides);
|
|
85861
85844
|
if (effective.council_mode === true) {
|
|
85862
85845
|
councilModeEnabled = true;
|
|
85863
|
-
const pcPath =
|
|
85846
|
+
const pcPath = path96.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
85864
85847
|
let pcVerdictFound = false;
|
|
85865
85848
|
let _pcVerdict;
|
|
85866
85849
|
let pcQuorumSize;
|
|
85867
85850
|
let pcTimestamp;
|
|
85868
85851
|
let pcPhaseNumber;
|
|
85869
85852
|
try {
|
|
85870
|
-
const pcContent =
|
|
85853
|
+
const pcContent = fs74.readFileSync(pcPath, "utf-8");
|
|
85871
85854
|
const pcBundle = JSON.parse(pcContent);
|
|
85872
85855
|
for (const entry of pcBundle.entries ?? []) {
|
|
85873
85856
|
if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
|
|
@@ -86068,11 +86051,11 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86068
86051
|
const effective = getEffectiveGates(profile, overrides);
|
|
86069
86052
|
if (effective.final_council === true) {
|
|
86070
86053
|
finalCouncilEnabled = true;
|
|
86071
|
-
const fcPath =
|
|
86054
|
+
const fcPath = path96.join(dir, ".swarm", "evidence", "final-council.json");
|
|
86072
86055
|
let fcVerdictFound = false;
|
|
86073
86056
|
let _fcVerdict;
|
|
86074
86057
|
try {
|
|
86075
|
-
const fcContent =
|
|
86058
|
+
const fcContent = fs74.readFileSync(fcPath, "utf-8");
|
|
86076
86059
|
const fcBundle = JSON.parse(fcContent);
|
|
86077
86060
|
for (const entry of fcBundle.entries ?? []) {
|
|
86078
86061
|
if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
|
|
@@ -86200,7 +86183,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86200
86183
|
}
|
|
86201
86184
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
86202
86185
|
try {
|
|
86203
|
-
const projectName =
|
|
86186
|
+
const projectName = path96.basename(dir);
|
|
86204
86187
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
86205
86188
|
if (curationResult) {
|
|
86206
86189
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -86280,7 +86263,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86280
86263
|
let phaseRequiredAgents;
|
|
86281
86264
|
try {
|
|
86282
86265
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86283
|
-
const planRaw =
|
|
86266
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86284
86267
|
const plan = JSON.parse(planRaw);
|
|
86285
86268
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
86286
86269
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -86295,7 +86278,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86295
86278
|
if (agentsMissing.length > 0) {
|
|
86296
86279
|
try {
|
|
86297
86280
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86298
|
-
const planRaw =
|
|
86281
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86299
86282
|
const plan = JSON.parse(planRaw);
|
|
86300
86283
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
86301
86284
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -86335,7 +86318,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86335
86318
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
86336
86319
|
try {
|
|
86337
86320
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86338
|
-
const planRaw =
|
|
86321
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86339
86322
|
const plan = JSON.parse(planRaw);
|
|
86340
86323
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
86341
86324
|
if (targetPhase) {
|
|
@@ -86389,7 +86372,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86389
86372
|
}
|
|
86390
86373
|
try {
|
|
86391
86374
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
86392
|
-
|
|
86375
|
+
fs74.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
86393
86376
|
`, "utf-8");
|
|
86394
86377
|
} catch (writeError) {
|
|
86395
86378
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -86464,12 +86447,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86464
86447
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
86465
86448
|
try {
|
|
86466
86449
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86467
|
-
const planRaw =
|
|
86450
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86468
86451
|
const plan2 = JSON.parse(planRaw);
|
|
86469
86452
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
86470
86453
|
if (phaseObj) {
|
|
86471
86454
|
phaseObj.status = "complete";
|
|
86472
|
-
|
|
86455
|
+
fs74.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
86473
86456
|
}
|
|
86474
86457
|
} catch {}
|
|
86475
86458
|
} else if (plan) {
|
|
@@ -86506,12 +86489,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86506
86489
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
86507
86490
|
try {
|
|
86508
86491
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86509
|
-
const planRaw =
|
|
86492
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86510
86493
|
const plan = JSON.parse(planRaw);
|
|
86511
86494
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
86512
86495
|
if (phaseObj) {
|
|
86513
86496
|
phaseObj.status = "complete";
|
|
86514
|
-
|
|
86497
|
+
fs74.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
86515
86498
|
}
|
|
86516
86499
|
} catch {}
|
|
86517
86500
|
}
|
|
@@ -86569,8 +86552,8 @@ init_discovery();
|
|
|
86569
86552
|
init_utils();
|
|
86570
86553
|
init_bun_compat();
|
|
86571
86554
|
init_create_tool();
|
|
86572
|
-
import * as
|
|
86573
|
-
import * as
|
|
86555
|
+
import * as fs75 from "node:fs";
|
|
86556
|
+
import * as path97 from "node:path";
|
|
86574
86557
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
86575
86558
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
86576
86559
|
function isValidEcosystem(value) {
|
|
@@ -86598,31 +86581,31 @@ function validateArgs3(args2) {
|
|
|
86598
86581
|
function detectEcosystems(directory) {
|
|
86599
86582
|
const ecosystems = [];
|
|
86600
86583
|
const cwd = directory;
|
|
86601
|
-
if (
|
|
86584
|
+
if (fs75.existsSync(path97.join(cwd, "package.json"))) {
|
|
86602
86585
|
ecosystems.push("npm");
|
|
86603
86586
|
}
|
|
86604
|
-
if (
|
|
86587
|
+
if (fs75.existsSync(path97.join(cwd, "pyproject.toml")) || fs75.existsSync(path97.join(cwd, "requirements.txt"))) {
|
|
86605
86588
|
ecosystems.push("pip");
|
|
86606
86589
|
}
|
|
86607
|
-
if (
|
|
86590
|
+
if (fs75.existsSync(path97.join(cwd, "Cargo.toml"))) {
|
|
86608
86591
|
ecosystems.push("cargo");
|
|
86609
86592
|
}
|
|
86610
|
-
if (
|
|
86593
|
+
if (fs75.existsSync(path97.join(cwd, "go.mod"))) {
|
|
86611
86594
|
ecosystems.push("go");
|
|
86612
86595
|
}
|
|
86613
86596
|
try {
|
|
86614
|
-
const files =
|
|
86597
|
+
const files = fs75.readdirSync(cwd);
|
|
86615
86598
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
86616
86599
|
ecosystems.push("dotnet");
|
|
86617
86600
|
}
|
|
86618
86601
|
} catch {}
|
|
86619
|
-
if (
|
|
86602
|
+
if (fs75.existsSync(path97.join(cwd, "Gemfile")) || fs75.existsSync(path97.join(cwd, "Gemfile.lock"))) {
|
|
86620
86603
|
ecosystems.push("ruby");
|
|
86621
86604
|
}
|
|
86622
|
-
if (
|
|
86605
|
+
if (fs75.existsSync(path97.join(cwd, "pubspec.yaml"))) {
|
|
86623
86606
|
ecosystems.push("dart");
|
|
86624
86607
|
}
|
|
86625
|
-
if (
|
|
86608
|
+
if (fs75.existsSync(path97.join(cwd, "composer.lock"))) {
|
|
86626
86609
|
ecosystems.push("composer");
|
|
86627
86610
|
}
|
|
86628
86611
|
return ecosystems;
|
|
@@ -87757,8 +87740,8 @@ var pkg_audit = createSwarmTool({
|
|
|
87757
87740
|
// src/tools/placeholder-scan.ts
|
|
87758
87741
|
init_zod();
|
|
87759
87742
|
init_manager2();
|
|
87760
|
-
import * as
|
|
87761
|
-
import * as
|
|
87743
|
+
import * as fs76 from "node:fs";
|
|
87744
|
+
import * as path98 from "node:path";
|
|
87762
87745
|
init_utils();
|
|
87763
87746
|
init_create_tool();
|
|
87764
87747
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -87881,7 +87864,7 @@ function isScaffoldFile(filePath) {
|
|
|
87881
87864
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
87882
87865
|
return true;
|
|
87883
87866
|
}
|
|
87884
|
-
const filename =
|
|
87867
|
+
const filename = path98.basename(filePath);
|
|
87885
87868
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
87886
87869
|
return true;
|
|
87887
87870
|
}
|
|
@@ -87898,7 +87881,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
87898
87881
|
if (regex.test(normalizedPath)) {
|
|
87899
87882
|
return true;
|
|
87900
87883
|
}
|
|
87901
|
-
const filename =
|
|
87884
|
+
const filename = path98.basename(filePath);
|
|
87902
87885
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
87903
87886
|
if (filenameRegex.test(filename)) {
|
|
87904
87887
|
return true;
|
|
@@ -87907,7 +87890,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
87907
87890
|
return false;
|
|
87908
87891
|
}
|
|
87909
87892
|
function isParserSupported(filePath) {
|
|
87910
|
-
const ext =
|
|
87893
|
+
const ext = path98.extname(filePath).toLowerCase();
|
|
87911
87894
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
87912
87895
|
}
|
|
87913
87896
|
function isPlanFile(filePath) {
|
|
@@ -88154,28 +88137,28 @@ async function placeholderScan(input, directory) {
|
|
|
88154
88137
|
let filesScanned = 0;
|
|
88155
88138
|
const filesWithFindings = new Set;
|
|
88156
88139
|
for (const filePath of changed_files) {
|
|
88157
|
-
const fullPath =
|
|
88158
|
-
const resolvedDirectory =
|
|
88159
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
88140
|
+
const fullPath = path98.isAbsolute(filePath) ? filePath : path98.resolve(directory, filePath);
|
|
88141
|
+
const resolvedDirectory = path98.resolve(directory);
|
|
88142
|
+
if (!fullPath.startsWith(resolvedDirectory + path98.sep) && fullPath !== resolvedDirectory) {
|
|
88160
88143
|
continue;
|
|
88161
88144
|
}
|
|
88162
|
-
if (!
|
|
88145
|
+
if (!fs76.existsSync(fullPath)) {
|
|
88163
88146
|
continue;
|
|
88164
88147
|
}
|
|
88165
88148
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
88166
88149
|
continue;
|
|
88167
88150
|
}
|
|
88168
|
-
const relativeFilePath =
|
|
88151
|
+
const relativeFilePath = path98.relative(directory, fullPath).replace(/\\/g, "/");
|
|
88169
88152
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
88170
88153
|
continue;
|
|
88171
88154
|
}
|
|
88172
88155
|
let content;
|
|
88173
88156
|
try {
|
|
88174
|
-
const stat7 =
|
|
88157
|
+
const stat7 = fs76.statSync(fullPath);
|
|
88175
88158
|
if (stat7.size > MAX_FILE_SIZE) {
|
|
88176
88159
|
continue;
|
|
88177
88160
|
}
|
|
88178
|
-
content =
|
|
88161
|
+
content = fs76.readFileSync(fullPath, "utf-8");
|
|
88179
88162
|
} catch {
|
|
88180
88163
|
continue;
|
|
88181
88164
|
}
|
|
@@ -88236,8 +88219,8 @@ var placeholder_scan = createSwarmTool({
|
|
|
88236
88219
|
}
|
|
88237
88220
|
});
|
|
88238
88221
|
// src/tools/pre-check-batch.ts
|
|
88239
|
-
import * as
|
|
88240
|
-
import * as
|
|
88222
|
+
import * as fs80 from "node:fs";
|
|
88223
|
+
import * as path102 from "node:path";
|
|
88241
88224
|
init_zod();
|
|
88242
88225
|
init_manager2();
|
|
88243
88226
|
init_utils();
|
|
@@ -88377,8 +88360,8 @@ var _internals30 = {
|
|
|
88377
88360
|
init_zod();
|
|
88378
88361
|
init_manager2();
|
|
88379
88362
|
init_detector();
|
|
88380
|
-
import * as
|
|
88381
|
-
import * as
|
|
88363
|
+
import * as fs79 from "node:fs";
|
|
88364
|
+
import * as path101 from "node:path";
|
|
88382
88365
|
import { extname as extname18 } from "node:path";
|
|
88383
88366
|
|
|
88384
88367
|
// src/sast/rules/c.ts
|
|
@@ -89093,8 +89076,8 @@ function executeRulesSync(filePath, content, language) {
|
|
|
89093
89076
|
|
|
89094
89077
|
// src/sast/semgrep.ts
|
|
89095
89078
|
import * as child_process9 from "node:child_process";
|
|
89096
|
-
import * as
|
|
89097
|
-
import * as
|
|
89079
|
+
import * as fs77 from "node:fs";
|
|
89080
|
+
import * as path99 from "node:path";
|
|
89098
89081
|
var semgrepAvailableCache = null;
|
|
89099
89082
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
89100
89083
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
@@ -89281,14 +89264,14 @@ async function runSemgrep(options) {
|
|
|
89281
89264
|
}
|
|
89282
89265
|
function getRulesDirectory(projectRoot) {
|
|
89283
89266
|
if (projectRoot) {
|
|
89284
|
-
return
|
|
89267
|
+
return path99.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
89285
89268
|
}
|
|
89286
89269
|
return DEFAULT_RULES_DIR;
|
|
89287
89270
|
}
|
|
89288
89271
|
function hasBundledRules(projectRoot) {
|
|
89289
89272
|
const rulesDir = getRulesDirectory(projectRoot);
|
|
89290
89273
|
try {
|
|
89291
|
-
return
|
|
89274
|
+
return fs77.existsSync(rulesDir);
|
|
89292
89275
|
} catch {
|
|
89293
89276
|
return false;
|
|
89294
89277
|
}
|
|
@@ -89301,25 +89284,25 @@ init_create_tool();
|
|
|
89301
89284
|
// src/tools/sast-baseline.ts
|
|
89302
89285
|
init_utils2();
|
|
89303
89286
|
import * as crypto9 from "node:crypto";
|
|
89304
|
-
import * as
|
|
89305
|
-
import * as
|
|
89287
|
+
import * as fs78 from "node:fs";
|
|
89288
|
+
import * as path100 from "node:path";
|
|
89306
89289
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
89307
89290
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
89308
89291
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
89309
89292
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
89310
89293
|
function normalizeFindingPath(directory, file3) {
|
|
89311
|
-
const resolved =
|
|
89312
|
-
const rel =
|
|
89294
|
+
const resolved = path100.isAbsolute(file3) ? file3 : path100.resolve(directory, file3);
|
|
89295
|
+
const rel = path100.relative(path100.resolve(directory), resolved);
|
|
89313
89296
|
return rel.replace(/\\/g, "/");
|
|
89314
89297
|
}
|
|
89315
89298
|
function baselineRelPath(phase) {
|
|
89316
|
-
return
|
|
89299
|
+
return path100.join("evidence", String(phase), "sast-baseline.json");
|
|
89317
89300
|
}
|
|
89318
89301
|
function tempRelPath(phase) {
|
|
89319
|
-
return
|
|
89302
|
+
return path100.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
89320
89303
|
}
|
|
89321
89304
|
function lockRelPath(phase) {
|
|
89322
|
-
return
|
|
89305
|
+
return path100.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
89323
89306
|
}
|
|
89324
89307
|
function getLine(lines, idx) {
|
|
89325
89308
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -89336,7 +89319,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
|
|
|
89336
89319
|
}
|
|
89337
89320
|
const lineNum = finding.location.line;
|
|
89338
89321
|
try {
|
|
89339
|
-
const content =
|
|
89322
|
+
const content = fs78.readFileSync(finding.location.file, "utf-8");
|
|
89340
89323
|
const lines = content.split(`
|
|
89341
89324
|
`);
|
|
89342
89325
|
const idx = lineNum - 1;
|
|
@@ -89367,7 +89350,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
89367
89350
|
try {
|
|
89368
89351
|
if (relFile.startsWith(".."))
|
|
89369
89352
|
throw new Error("escapes workspace");
|
|
89370
|
-
const content =
|
|
89353
|
+
const content = fs78.readFileSync(finding.location.file, "utf-8");
|
|
89371
89354
|
const lines = content.split(`
|
|
89372
89355
|
`);
|
|
89373
89356
|
const idx = lineNum - 1;
|
|
@@ -89396,11 +89379,11 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
89396
89379
|
async function acquireLock(lockPath) {
|
|
89397
89380
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
89398
89381
|
try {
|
|
89399
|
-
const fd =
|
|
89400
|
-
|
|
89382
|
+
const fd = fs78.openSync(lockPath, "wx");
|
|
89383
|
+
fs78.closeSync(fd);
|
|
89401
89384
|
return () => {
|
|
89402
89385
|
try {
|
|
89403
|
-
|
|
89386
|
+
fs78.unlinkSync(lockPath);
|
|
89404
89387
|
} catch {}
|
|
89405
89388
|
};
|
|
89406
89389
|
} catch {
|
|
@@ -89440,13 +89423,13 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
89440
89423
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
89441
89424
|
};
|
|
89442
89425
|
}
|
|
89443
|
-
|
|
89444
|
-
|
|
89426
|
+
fs78.mkdirSync(path100.dirname(baselinePath), { recursive: true });
|
|
89427
|
+
fs78.mkdirSync(path100.dirname(tempPath), { recursive: true });
|
|
89445
89428
|
const releaseLock = await acquireLock(lockPath);
|
|
89446
89429
|
try {
|
|
89447
89430
|
let existing = null;
|
|
89448
89431
|
try {
|
|
89449
|
-
const raw =
|
|
89432
|
+
const raw = fs78.readFileSync(baselinePath, "utf-8");
|
|
89450
89433
|
const parsed = JSON.parse(raw);
|
|
89451
89434
|
if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
|
|
89452
89435
|
existing = parsed;
|
|
@@ -89506,8 +89489,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
89506
89489
|
message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
89507
89490
|
};
|
|
89508
89491
|
}
|
|
89509
|
-
|
|
89510
|
-
|
|
89492
|
+
fs78.writeFileSync(tempPath, json4, "utf-8");
|
|
89493
|
+
fs78.renameSync(tempPath, baselinePath);
|
|
89511
89494
|
return {
|
|
89512
89495
|
status: "merged",
|
|
89513
89496
|
path: baselinePath,
|
|
@@ -89538,8 +89521,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
89538
89521
|
message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
89539
89522
|
};
|
|
89540
89523
|
}
|
|
89541
|
-
|
|
89542
|
-
|
|
89524
|
+
fs78.writeFileSync(tempPath, json3, "utf-8");
|
|
89525
|
+
fs78.renameSync(tempPath, baselinePath);
|
|
89543
89526
|
return {
|
|
89544
89527
|
status: "written",
|
|
89545
89528
|
path: baselinePath,
|
|
@@ -89564,7 +89547,7 @@ function loadBaseline(directory, phase) {
|
|
|
89564
89547
|
};
|
|
89565
89548
|
}
|
|
89566
89549
|
try {
|
|
89567
|
-
const raw =
|
|
89550
|
+
const raw = fs78.readFileSync(baselinePath, "utf-8");
|
|
89568
89551
|
const parsed = JSON.parse(raw);
|
|
89569
89552
|
if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
|
|
89570
89553
|
return {
|
|
@@ -89612,17 +89595,17 @@ var SEVERITY_ORDER = {
|
|
|
89612
89595
|
};
|
|
89613
89596
|
function shouldSkipFile(filePath) {
|
|
89614
89597
|
try {
|
|
89615
|
-
const stats =
|
|
89598
|
+
const stats = fs79.statSync(filePath);
|
|
89616
89599
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
89617
89600
|
return { skip: true, reason: "file too large" };
|
|
89618
89601
|
}
|
|
89619
89602
|
if (stats.size === 0) {
|
|
89620
89603
|
return { skip: true, reason: "empty file" };
|
|
89621
89604
|
}
|
|
89622
|
-
const fd =
|
|
89605
|
+
const fd = fs79.openSync(filePath, "r");
|
|
89623
89606
|
const buffer = Buffer.alloc(8192);
|
|
89624
|
-
const bytesRead =
|
|
89625
|
-
|
|
89607
|
+
const bytesRead = fs79.readSync(fd, buffer, 0, 8192, 0);
|
|
89608
|
+
fs79.closeSync(fd);
|
|
89626
89609
|
if (bytesRead > 0) {
|
|
89627
89610
|
let nullCount = 0;
|
|
89628
89611
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -89661,7 +89644,7 @@ function countBySeverity(findings) {
|
|
|
89661
89644
|
}
|
|
89662
89645
|
function scanFileWithTierA(filePath, language) {
|
|
89663
89646
|
try {
|
|
89664
|
-
const content =
|
|
89647
|
+
const content = fs79.readFileSync(filePath, "utf-8");
|
|
89665
89648
|
const findings = executeRulesSync(filePath, content, language);
|
|
89666
89649
|
return findings.map((f) => ({
|
|
89667
89650
|
rule_id: f.rule_id,
|
|
@@ -89714,13 +89697,13 @@ async function sastScan(input, directory, config3) {
|
|
|
89714
89697
|
_filesSkipped++;
|
|
89715
89698
|
continue;
|
|
89716
89699
|
}
|
|
89717
|
-
const resolvedPath =
|
|
89718
|
-
const resolvedDirectory =
|
|
89719
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
89700
|
+
const resolvedPath = path101.isAbsolute(filePath) ? filePath : path101.resolve(directory, filePath);
|
|
89701
|
+
const resolvedDirectory = path101.resolve(directory);
|
|
89702
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path101.sep) && resolvedPath !== resolvedDirectory) {
|
|
89720
89703
|
_filesSkipped++;
|
|
89721
89704
|
continue;
|
|
89722
89705
|
}
|
|
89723
|
-
if (!
|
|
89706
|
+
if (!fs79.existsSync(resolvedPath)) {
|
|
89724
89707
|
_filesSkipped++;
|
|
89725
89708
|
continue;
|
|
89726
89709
|
}
|
|
@@ -90031,18 +90014,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
90031
90014
|
let resolved;
|
|
90032
90015
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
90033
90016
|
if (isWinAbs) {
|
|
90034
|
-
resolved =
|
|
90035
|
-
} else if (
|
|
90036
|
-
resolved =
|
|
90017
|
+
resolved = path102.win32.resolve(inputPath);
|
|
90018
|
+
} else if (path102.isAbsolute(inputPath)) {
|
|
90019
|
+
resolved = path102.resolve(inputPath);
|
|
90037
90020
|
} else {
|
|
90038
|
-
resolved =
|
|
90021
|
+
resolved = path102.resolve(baseDir, inputPath);
|
|
90039
90022
|
}
|
|
90040
|
-
const workspaceResolved =
|
|
90023
|
+
const workspaceResolved = path102.resolve(workspaceDir);
|
|
90041
90024
|
let relative22;
|
|
90042
90025
|
if (isWinAbs) {
|
|
90043
|
-
relative22 =
|
|
90026
|
+
relative22 = path102.win32.relative(workspaceResolved, resolved);
|
|
90044
90027
|
} else {
|
|
90045
|
-
relative22 =
|
|
90028
|
+
relative22 = path102.relative(workspaceResolved, resolved);
|
|
90046
90029
|
}
|
|
90047
90030
|
if (relative22.startsWith("..")) {
|
|
90048
90031
|
return "path traversal detected";
|
|
@@ -90107,7 +90090,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
90107
90090
|
if (typeof file3 !== "string") {
|
|
90108
90091
|
continue;
|
|
90109
90092
|
}
|
|
90110
|
-
const resolvedPath =
|
|
90093
|
+
const resolvedPath = path102.resolve(file3);
|
|
90111
90094
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
90112
90095
|
if (validationError) {
|
|
90113
90096
|
continue;
|
|
@@ -90264,7 +90247,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
90264
90247
|
skippedFiles++;
|
|
90265
90248
|
continue;
|
|
90266
90249
|
}
|
|
90267
|
-
const resolvedPath =
|
|
90250
|
+
const resolvedPath = path102.resolve(file3);
|
|
90268
90251
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
90269
90252
|
if (validationError) {
|
|
90270
90253
|
skippedFiles++;
|
|
@@ -90282,14 +90265,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
90282
90265
|
};
|
|
90283
90266
|
}
|
|
90284
90267
|
for (const file3 of validatedFiles) {
|
|
90285
|
-
const ext =
|
|
90268
|
+
const ext = path102.extname(file3).toLowerCase();
|
|
90286
90269
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
90287
90270
|
skippedFiles++;
|
|
90288
90271
|
continue;
|
|
90289
90272
|
}
|
|
90290
90273
|
let stat7;
|
|
90291
90274
|
try {
|
|
90292
|
-
stat7 =
|
|
90275
|
+
stat7 = fs80.statSync(file3);
|
|
90293
90276
|
} catch {
|
|
90294
90277
|
skippedFiles++;
|
|
90295
90278
|
continue;
|
|
@@ -90300,7 +90283,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
90300
90283
|
}
|
|
90301
90284
|
let content;
|
|
90302
90285
|
try {
|
|
90303
|
-
const buffer =
|
|
90286
|
+
const buffer = fs80.readFileSync(file3);
|
|
90304
90287
|
if (buffer.includes(0)) {
|
|
90305
90288
|
skippedFiles++;
|
|
90306
90289
|
continue;
|
|
@@ -90501,7 +90484,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
90501
90484
|
const preexistingFindings = [];
|
|
90502
90485
|
for (const finding of findings) {
|
|
90503
90486
|
const filePath = finding.location.file;
|
|
90504
|
-
const normalised =
|
|
90487
|
+
const normalised = path102.relative(directory, filePath).replace(/\\/g, "/");
|
|
90505
90488
|
const changedLines = changedLineRanges.get(normalised);
|
|
90506
90489
|
if (changedLines?.has(finding.location.line)) {
|
|
90507
90490
|
newFindings.push(finding);
|
|
@@ -90552,7 +90535,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
90552
90535
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
90553
90536
|
continue;
|
|
90554
90537
|
}
|
|
90555
|
-
changedFiles.push(
|
|
90538
|
+
changedFiles.push(path102.resolve(directory, file3));
|
|
90556
90539
|
}
|
|
90557
90540
|
if (changedFiles.length === 0) {
|
|
90558
90541
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -90753,7 +90736,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
90753
90736
|
};
|
|
90754
90737
|
return JSON.stringify(errorResult, null, 2);
|
|
90755
90738
|
}
|
|
90756
|
-
const resolvedDirectory =
|
|
90739
|
+
const resolvedDirectory = path102.resolve(typedArgs.directory);
|
|
90757
90740
|
const workspaceAnchor = resolvedDirectory;
|
|
90758
90741
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
90759
90742
|
if (dirError) {
|
|
@@ -90794,7 +90777,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
90794
90777
|
});
|
|
90795
90778
|
// src/tools/repo-map.ts
|
|
90796
90779
|
init_zod();
|
|
90797
|
-
import * as
|
|
90780
|
+
import * as path103 from "node:path";
|
|
90798
90781
|
init_path_security();
|
|
90799
90782
|
init_create_tool();
|
|
90800
90783
|
var VALID_ACTIONS = [
|
|
@@ -90819,7 +90802,7 @@ function validateFile(p) {
|
|
|
90819
90802
|
return "file contains control characters";
|
|
90820
90803
|
if (containsPathTraversal(p))
|
|
90821
90804
|
return "file contains path traversal";
|
|
90822
|
-
if (
|
|
90805
|
+
if (path103.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
90823
90806
|
return "file must be a workspace-relative path, not absolute";
|
|
90824
90807
|
}
|
|
90825
90808
|
return null;
|
|
@@ -90842,8 +90825,8 @@ function ok(action, payload) {
|
|
|
90842
90825
|
}
|
|
90843
90826
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
90844
90827
|
const normalized = input.replace(/\\/g, "/");
|
|
90845
|
-
if (
|
|
90846
|
-
const rel =
|
|
90828
|
+
if (path103.isAbsolute(normalized)) {
|
|
90829
|
+
const rel = path103.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
90847
90830
|
return normalizeGraphPath2(rel);
|
|
90848
90831
|
}
|
|
90849
90832
|
return normalizeGraphPath2(normalized);
|
|
@@ -90987,8 +90970,8 @@ var repo_map = createSwarmTool({
|
|
|
90987
90970
|
// src/tools/req-coverage.ts
|
|
90988
90971
|
init_zod();
|
|
90989
90972
|
init_create_tool();
|
|
90990
|
-
import * as
|
|
90991
|
-
import * as
|
|
90973
|
+
import * as fs81 from "node:fs";
|
|
90974
|
+
import * as path104 from "node:path";
|
|
90992
90975
|
var SPEC_FILE = ".swarm/spec.md";
|
|
90993
90976
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
90994
90977
|
var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -91047,19 +91030,19 @@ function extractObligationAndText(id, lineText) {
|
|
|
91047
91030
|
var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
91048
91031
|
function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
91049
91032
|
const touchedFiles = new Set;
|
|
91050
|
-
if (!
|
|
91033
|
+
if (!fs81.existsSync(evidenceDir) || !fs81.statSync(evidenceDir).isDirectory()) {
|
|
91051
91034
|
return [];
|
|
91052
91035
|
}
|
|
91053
91036
|
let entries;
|
|
91054
91037
|
try {
|
|
91055
|
-
entries =
|
|
91038
|
+
entries = fs81.readdirSync(evidenceDir);
|
|
91056
91039
|
} catch {
|
|
91057
91040
|
return [];
|
|
91058
91041
|
}
|
|
91059
91042
|
for (const entry of entries) {
|
|
91060
|
-
const entryPath =
|
|
91043
|
+
const entryPath = path104.join(evidenceDir, entry);
|
|
91061
91044
|
try {
|
|
91062
|
-
const stat7 =
|
|
91045
|
+
const stat7 = fs81.statSync(entryPath);
|
|
91063
91046
|
if (!stat7.isDirectory()) {
|
|
91064
91047
|
continue;
|
|
91065
91048
|
}
|
|
@@ -91073,14 +91056,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91073
91056
|
if (entryPhase !== String(phase)) {
|
|
91074
91057
|
continue;
|
|
91075
91058
|
}
|
|
91076
|
-
const evidenceFilePath =
|
|
91059
|
+
const evidenceFilePath = path104.join(entryPath, "evidence.json");
|
|
91077
91060
|
try {
|
|
91078
|
-
const resolvedPath =
|
|
91079
|
-
const evidenceDirResolved =
|
|
91080
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
91061
|
+
const resolvedPath = path104.resolve(evidenceFilePath);
|
|
91062
|
+
const evidenceDirResolved = path104.resolve(evidenceDir);
|
|
91063
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path104.sep)) {
|
|
91081
91064
|
continue;
|
|
91082
91065
|
}
|
|
91083
|
-
const stat7 =
|
|
91066
|
+
const stat7 = fs81.lstatSync(evidenceFilePath);
|
|
91084
91067
|
if (!stat7.isFile()) {
|
|
91085
91068
|
continue;
|
|
91086
91069
|
}
|
|
@@ -91092,7 +91075,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91092
91075
|
}
|
|
91093
91076
|
let content;
|
|
91094
91077
|
try {
|
|
91095
|
-
content =
|
|
91078
|
+
content = fs81.readFileSync(evidenceFilePath, "utf-8");
|
|
91096
91079
|
} catch {
|
|
91097
91080
|
continue;
|
|
91098
91081
|
}
|
|
@@ -91111,7 +91094,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91111
91094
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
91112
91095
|
for (const file3 of diffEntry.files_changed) {
|
|
91113
91096
|
if (typeof file3 === "string") {
|
|
91114
|
-
touchedFiles.add(
|
|
91097
|
+
touchedFiles.add(path104.resolve(cwd, file3));
|
|
91115
91098
|
}
|
|
91116
91099
|
}
|
|
91117
91100
|
}
|
|
@@ -91124,12 +91107,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91124
91107
|
}
|
|
91125
91108
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
91126
91109
|
try {
|
|
91127
|
-
const resolvedPath =
|
|
91128
|
-
const cwdResolved =
|
|
91110
|
+
const resolvedPath = path104.resolve(filePath);
|
|
91111
|
+
const cwdResolved = path104.resolve(cwd);
|
|
91129
91112
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
91130
91113
|
return false;
|
|
91131
91114
|
}
|
|
91132
|
-
const content =
|
|
91115
|
+
const content = fs81.readFileSync(resolvedPath, "utf-8");
|
|
91133
91116
|
for (const keyword of keywords) {
|
|
91134
91117
|
const regex = new RegExp(`\\b${keyword}\\b`, "i");
|
|
91135
91118
|
if (regex.test(content)) {
|
|
@@ -91259,10 +91242,10 @@ var req_coverage = createSwarmTool({
|
|
|
91259
91242
|
}, null, 2);
|
|
91260
91243
|
}
|
|
91261
91244
|
const cwd = inputDirectory || directory;
|
|
91262
|
-
const specPath =
|
|
91245
|
+
const specPath = path104.join(cwd, SPEC_FILE);
|
|
91263
91246
|
let specContent;
|
|
91264
91247
|
try {
|
|
91265
|
-
specContent =
|
|
91248
|
+
specContent = fs81.readFileSync(specPath, "utf-8");
|
|
91266
91249
|
} catch (readError) {
|
|
91267
91250
|
return JSON.stringify({
|
|
91268
91251
|
success: false,
|
|
@@ -91286,7 +91269,7 @@ var req_coverage = createSwarmTool({
|
|
|
91286
91269
|
message: "No FR requirements found in spec.md"
|
|
91287
91270
|
}, null, 2);
|
|
91288
91271
|
}
|
|
91289
|
-
const evidenceDir =
|
|
91272
|
+
const evidenceDir = path104.join(cwd, EVIDENCE_DIR4);
|
|
91290
91273
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
91291
91274
|
const analyzedRequirements = [];
|
|
91292
91275
|
let coveredCount = 0;
|
|
@@ -91312,12 +91295,12 @@ var req_coverage = createSwarmTool({
|
|
|
91312
91295
|
requirements: analyzedRequirements
|
|
91313
91296
|
};
|
|
91314
91297
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
91315
|
-
const reportPath =
|
|
91298
|
+
const reportPath = path104.join(evidenceDir, reportFilename);
|
|
91316
91299
|
try {
|
|
91317
|
-
if (!
|
|
91318
|
-
|
|
91300
|
+
if (!fs81.existsSync(evidenceDir)) {
|
|
91301
|
+
fs81.mkdirSync(evidenceDir, { recursive: true });
|
|
91319
91302
|
}
|
|
91320
|
-
|
|
91303
|
+
fs81.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
|
|
91321
91304
|
} catch (writeError) {
|
|
91322
91305
|
console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
91323
91306
|
}
|
|
@@ -91399,8 +91382,8 @@ init_plan_schema();
|
|
|
91399
91382
|
init_qa_gate_profile();
|
|
91400
91383
|
init_file_locks();
|
|
91401
91384
|
import * as crypto10 from "node:crypto";
|
|
91402
|
-
import * as
|
|
91403
|
-
import * as
|
|
91385
|
+
import * as fs82 from "node:fs";
|
|
91386
|
+
import * as path105 from "node:path";
|
|
91404
91387
|
init_ledger();
|
|
91405
91388
|
init_manager();
|
|
91406
91389
|
init_state();
|
|
@@ -91478,17 +91461,17 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91478
91461
|
};
|
|
91479
91462
|
}
|
|
91480
91463
|
if (args2.working_directory && fallbackDir) {
|
|
91481
|
-
const resolvedTarget =
|
|
91482
|
-
const resolvedRoot =
|
|
91464
|
+
const resolvedTarget = path105.resolve(args2.working_directory);
|
|
91465
|
+
const resolvedRoot = path105.resolve(fallbackDir);
|
|
91483
91466
|
let fallbackExists = false;
|
|
91484
91467
|
try {
|
|
91485
|
-
|
|
91468
|
+
fs82.accessSync(resolvedRoot, fs82.constants.F_OK);
|
|
91486
91469
|
fallbackExists = true;
|
|
91487
91470
|
} catch {
|
|
91488
91471
|
fallbackExists = false;
|
|
91489
91472
|
}
|
|
91490
91473
|
if (fallbackExists) {
|
|
91491
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
91474
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path105.sep);
|
|
91492
91475
|
if (isSubdirectory) {
|
|
91493
91476
|
return {
|
|
91494
91477
|
success: false,
|
|
@@ -91504,11 +91487,11 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91504
91487
|
let specMtime;
|
|
91505
91488
|
let specHash;
|
|
91506
91489
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
91507
|
-
const specPath =
|
|
91490
|
+
const specPath = path105.join(targetWorkspace, ".swarm", "spec.md");
|
|
91508
91491
|
try {
|
|
91509
|
-
const stat7 = await
|
|
91492
|
+
const stat7 = await fs82.promises.stat(specPath);
|
|
91510
91493
|
specMtime = stat7.mtime.toISOString();
|
|
91511
|
-
const content = await
|
|
91494
|
+
const content = await fs82.promises.readFile(specPath, "utf8");
|
|
91512
91495
|
specHash = crypto10.createHash("sha256").update(content).digest("hex");
|
|
91513
91496
|
} catch {
|
|
91514
91497
|
return {
|
|
@@ -91520,10 +91503,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91520
91503
|
}
|
|
91521
91504
|
}
|
|
91522
91505
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
91523
|
-
const contextPath =
|
|
91506
|
+
const contextPath = path105.join(targetWorkspace, ".swarm", "context.md");
|
|
91524
91507
|
let contextContent = "";
|
|
91525
91508
|
try {
|
|
91526
|
-
contextContent = await
|
|
91509
|
+
contextContent = await fs82.promises.readFile(contextPath, "utf8");
|
|
91527
91510
|
} catch {}
|
|
91528
91511
|
const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
|
|
91529
91512
|
if (!hasPendingSection) {
|
|
@@ -91673,14 +91656,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91673
91656
|
}
|
|
91674
91657
|
await writeCheckpoint(dir).catch(() => {});
|
|
91675
91658
|
try {
|
|
91676
|
-
const markerPath =
|
|
91659
|
+
const markerPath = path105.join(dir, ".swarm", ".plan-write-marker");
|
|
91677
91660
|
const marker = JSON.stringify({
|
|
91678
91661
|
source: "save_plan",
|
|
91679
91662
|
timestamp: new Date().toISOString(),
|
|
91680
91663
|
phases_count: plan.phases.length,
|
|
91681
91664
|
tasks_count: tasksCount
|
|
91682
91665
|
});
|
|
91683
|
-
await
|
|
91666
|
+
await fs82.promises.writeFile(markerPath, marker, "utf8");
|
|
91684
91667
|
} catch {}
|
|
91685
91668
|
const warnings = [];
|
|
91686
91669
|
let criticReviewFound = false;
|
|
@@ -91696,7 +91679,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91696
91679
|
return {
|
|
91697
91680
|
success: true,
|
|
91698
91681
|
message: "Plan saved successfully",
|
|
91699
|
-
plan_path:
|
|
91682
|
+
plan_path: path105.join(dir, ".swarm", "plan.json"),
|
|
91700
91683
|
phases_count: plan.phases.length,
|
|
91701
91684
|
tasks_count: tasksCount,
|
|
91702
91685
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -91748,8 +91731,8 @@ var save_plan = createSwarmTool({
|
|
|
91748
91731
|
// src/tools/sbom-generate.ts
|
|
91749
91732
|
init_zod();
|
|
91750
91733
|
init_manager2();
|
|
91751
|
-
import * as
|
|
91752
|
-
import * as
|
|
91734
|
+
import * as fs83 from "node:fs";
|
|
91735
|
+
import * as path106 from "node:path";
|
|
91753
91736
|
|
|
91754
91737
|
// src/sbom/detectors/index.ts
|
|
91755
91738
|
init_utils();
|
|
@@ -92597,9 +92580,9 @@ function findManifestFiles(rootDir) {
|
|
|
92597
92580
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
92598
92581
|
function searchDir(dir) {
|
|
92599
92582
|
try {
|
|
92600
|
-
const entries =
|
|
92583
|
+
const entries = fs83.readdirSync(dir, { withFileTypes: true });
|
|
92601
92584
|
for (const entry of entries) {
|
|
92602
|
-
const fullPath =
|
|
92585
|
+
const fullPath = path106.join(dir, entry.name);
|
|
92603
92586
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
92604
92587
|
continue;
|
|
92605
92588
|
}
|
|
@@ -92608,7 +92591,7 @@ function findManifestFiles(rootDir) {
|
|
|
92608
92591
|
} else if (entry.isFile()) {
|
|
92609
92592
|
for (const pattern of patterns) {
|
|
92610
92593
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
92611
|
-
manifestFiles.push(
|
|
92594
|
+
manifestFiles.push(path106.relative(rootDir, fullPath));
|
|
92612
92595
|
break;
|
|
92613
92596
|
}
|
|
92614
92597
|
}
|
|
@@ -92624,13 +92607,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
92624
92607
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
92625
92608
|
for (const dir of directories) {
|
|
92626
92609
|
try {
|
|
92627
|
-
const entries =
|
|
92610
|
+
const entries = fs83.readdirSync(dir, { withFileTypes: true });
|
|
92628
92611
|
for (const entry of entries) {
|
|
92629
|
-
const fullPath =
|
|
92612
|
+
const fullPath = path106.join(dir, entry.name);
|
|
92630
92613
|
if (entry.isFile()) {
|
|
92631
92614
|
for (const pattern of patterns) {
|
|
92632
92615
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
92633
|
-
found.push(
|
|
92616
|
+
found.push(path106.relative(workingDir, fullPath));
|
|
92634
92617
|
break;
|
|
92635
92618
|
}
|
|
92636
92619
|
}
|
|
@@ -92643,11 +92626,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
92643
92626
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
92644
92627
|
const dirs = new Set;
|
|
92645
92628
|
for (const file3 of changedFiles) {
|
|
92646
|
-
let currentDir =
|
|
92629
|
+
let currentDir = path106.dirname(file3);
|
|
92647
92630
|
while (true) {
|
|
92648
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
92649
|
-
dirs.add(
|
|
92650
|
-
const parent =
|
|
92631
|
+
if (currentDir && currentDir !== "." && currentDir !== path106.sep) {
|
|
92632
|
+
dirs.add(path106.join(workingDir, currentDir));
|
|
92633
|
+
const parent = path106.dirname(currentDir);
|
|
92651
92634
|
if (parent === currentDir)
|
|
92652
92635
|
break;
|
|
92653
92636
|
currentDir = parent;
|
|
@@ -92661,7 +92644,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
92661
92644
|
}
|
|
92662
92645
|
function ensureOutputDir(outputDir) {
|
|
92663
92646
|
try {
|
|
92664
|
-
|
|
92647
|
+
fs83.mkdirSync(outputDir, { recursive: true });
|
|
92665
92648
|
} catch (error93) {
|
|
92666
92649
|
if (!error93 || error93.code !== "EEXIST") {
|
|
92667
92650
|
throw error93;
|
|
@@ -92731,7 +92714,7 @@ var sbom_generate = createSwarmTool({
|
|
|
92731
92714
|
const changedFiles = obj.changed_files;
|
|
92732
92715
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
92733
92716
|
const workingDir = directory;
|
|
92734
|
-
const outputDir =
|
|
92717
|
+
const outputDir = path106.isAbsolute(relativeOutputDir) ? relativeOutputDir : path106.join(workingDir, relativeOutputDir);
|
|
92735
92718
|
let manifestFiles = [];
|
|
92736
92719
|
if (scope === "all") {
|
|
92737
92720
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -92754,11 +92737,11 @@ var sbom_generate = createSwarmTool({
|
|
|
92754
92737
|
const processedFiles = [];
|
|
92755
92738
|
for (const manifestFile of manifestFiles) {
|
|
92756
92739
|
try {
|
|
92757
|
-
const fullPath =
|
|
92758
|
-
if (!
|
|
92740
|
+
const fullPath = path106.isAbsolute(manifestFile) ? manifestFile : path106.join(workingDir, manifestFile);
|
|
92741
|
+
if (!fs83.existsSync(fullPath)) {
|
|
92759
92742
|
continue;
|
|
92760
92743
|
}
|
|
92761
|
-
const content =
|
|
92744
|
+
const content = fs83.readFileSync(fullPath, "utf-8");
|
|
92762
92745
|
const components = detectComponents(manifestFile, content);
|
|
92763
92746
|
processedFiles.push(manifestFile);
|
|
92764
92747
|
if (components.length > 0) {
|
|
@@ -92771,8 +92754,8 @@ var sbom_generate = createSwarmTool({
|
|
|
92771
92754
|
const bom = generateCycloneDX(allComponents);
|
|
92772
92755
|
const bomJson = serializeCycloneDX(bom);
|
|
92773
92756
|
const filename = generateSbomFilename();
|
|
92774
|
-
const outputPath =
|
|
92775
|
-
|
|
92757
|
+
const outputPath = path106.join(outputDir, filename);
|
|
92758
|
+
fs83.writeFileSync(outputPath, bomJson, "utf-8");
|
|
92776
92759
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
92777
92760
|
try {
|
|
92778
92761
|
const timestamp = new Date().toISOString();
|
|
@@ -92814,8 +92797,8 @@ var sbom_generate = createSwarmTool({
|
|
|
92814
92797
|
// src/tools/schema-drift.ts
|
|
92815
92798
|
init_zod();
|
|
92816
92799
|
init_create_tool();
|
|
92817
|
-
import * as
|
|
92818
|
-
import * as
|
|
92800
|
+
import * as fs84 from "node:fs";
|
|
92801
|
+
import * as path107 from "node:path";
|
|
92819
92802
|
var SPEC_CANDIDATES = [
|
|
92820
92803
|
"openapi.json",
|
|
92821
92804
|
"openapi.yaml",
|
|
@@ -92847,28 +92830,28 @@ function normalizePath4(p) {
|
|
|
92847
92830
|
}
|
|
92848
92831
|
function discoverSpecFile(cwd, specFileArg) {
|
|
92849
92832
|
if (specFileArg) {
|
|
92850
|
-
const resolvedPath =
|
|
92851
|
-
const normalizedCwd = cwd.endsWith(
|
|
92833
|
+
const resolvedPath = path107.resolve(cwd, specFileArg);
|
|
92834
|
+
const normalizedCwd = cwd.endsWith(path107.sep) ? cwd : cwd + path107.sep;
|
|
92852
92835
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
92853
92836
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
92854
92837
|
}
|
|
92855
|
-
const ext =
|
|
92838
|
+
const ext = path107.extname(resolvedPath).toLowerCase();
|
|
92856
92839
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
92857
92840
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
92858
92841
|
}
|
|
92859
|
-
const stats =
|
|
92842
|
+
const stats = fs84.statSync(resolvedPath);
|
|
92860
92843
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
92861
92844
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
92862
92845
|
}
|
|
92863
|
-
if (!
|
|
92846
|
+
if (!fs84.existsSync(resolvedPath)) {
|
|
92864
92847
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
92865
92848
|
}
|
|
92866
92849
|
return resolvedPath;
|
|
92867
92850
|
}
|
|
92868
92851
|
for (const candidate of SPEC_CANDIDATES) {
|
|
92869
|
-
const candidatePath =
|
|
92870
|
-
if (
|
|
92871
|
-
const stats =
|
|
92852
|
+
const candidatePath = path107.resolve(cwd, candidate);
|
|
92853
|
+
if (fs84.existsSync(candidatePath)) {
|
|
92854
|
+
const stats = fs84.statSync(candidatePath);
|
|
92872
92855
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
92873
92856
|
return candidatePath;
|
|
92874
92857
|
}
|
|
@@ -92877,8 +92860,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
92877
92860
|
return null;
|
|
92878
92861
|
}
|
|
92879
92862
|
function parseSpec(specFile) {
|
|
92880
|
-
const content =
|
|
92881
|
-
const ext =
|
|
92863
|
+
const content = fs84.readFileSync(specFile, "utf-8");
|
|
92864
|
+
const ext = path107.extname(specFile).toLowerCase();
|
|
92882
92865
|
if (ext === ".json") {
|
|
92883
92866
|
return parseJsonSpec(content);
|
|
92884
92867
|
}
|
|
@@ -92949,12 +92932,12 @@ function extractRoutes(cwd) {
|
|
|
92949
92932
|
function walkDir(dir) {
|
|
92950
92933
|
let entries;
|
|
92951
92934
|
try {
|
|
92952
|
-
entries =
|
|
92935
|
+
entries = fs84.readdirSync(dir, { withFileTypes: true });
|
|
92953
92936
|
} catch {
|
|
92954
92937
|
return;
|
|
92955
92938
|
}
|
|
92956
92939
|
for (const entry of entries) {
|
|
92957
|
-
const fullPath =
|
|
92940
|
+
const fullPath = path107.join(dir, entry.name);
|
|
92958
92941
|
if (entry.isSymbolicLink()) {
|
|
92959
92942
|
continue;
|
|
92960
92943
|
}
|
|
@@ -92964,7 +92947,7 @@ function extractRoutes(cwd) {
|
|
|
92964
92947
|
}
|
|
92965
92948
|
walkDir(fullPath);
|
|
92966
92949
|
} else if (entry.isFile()) {
|
|
92967
|
-
const ext =
|
|
92950
|
+
const ext = path107.extname(entry.name).toLowerCase();
|
|
92968
92951
|
const baseName = entry.name.toLowerCase();
|
|
92969
92952
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
92970
92953
|
continue;
|
|
@@ -92982,7 +92965,7 @@ function extractRoutes(cwd) {
|
|
|
92982
92965
|
}
|
|
92983
92966
|
function extractRoutesFromFile(filePath) {
|
|
92984
92967
|
const routes = [];
|
|
92985
|
-
const content =
|
|
92968
|
+
const content = fs84.readFileSync(filePath, "utf-8");
|
|
92986
92969
|
const lines = content.split(/\r?\n/);
|
|
92987
92970
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
92988
92971
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -93131,8 +93114,8 @@ init_zod();
|
|
|
93131
93114
|
init_bun_compat();
|
|
93132
93115
|
init_path_security();
|
|
93133
93116
|
init_create_tool();
|
|
93134
|
-
import * as
|
|
93135
|
-
import * as
|
|
93117
|
+
import * as fs85 from "node:fs";
|
|
93118
|
+
import * as path108 from "node:path";
|
|
93136
93119
|
var DEFAULT_MAX_RESULTS = 100;
|
|
93137
93120
|
var DEFAULT_MAX_LINES = 200;
|
|
93138
93121
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -93168,11 +93151,11 @@ function containsWindowsAttacks3(str) {
|
|
|
93168
93151
|
}
|
|
93169
93152
|
function isPathInWorkspace3(filePath, workspace) {
|
|
93170
93153
|
try {
|
|
93171
|
-
const resolvedPath =
|
|
93172
|
-
const realWorkspace =
|
|
93173
|
-
const realResolvedPath =
|
|
93174
|
-
const relativePath =
|
|
93175
|
-
if (relativePath.startsWith("..") ||
|
|
93154
|
+
const resolvedPath = path108.resolve(workspace, filePath);
|
|
93155
|
+
const realWorkspace = fs85.realpathSync(workspace);
|
|
93156
|
+
const realResolvedPath = fs85.realpathSync(resolvedPath);
|
|
93157
|
+
const relativePath = path108.relative(realWorkspace, realResolvedPath);
|
|
93158
|
+
if (relativePath.startsWith("..") || path108.isAbsolute(relativePath)) {
|
|
93176
93159
|
return false;
|
|
93177
93160
|
}
|
|
93178
93161
|
return true;
|
|
@@ -93185,12 +93168,12 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
93185
93168
|
}
|
|
93186
93169
|
function findRgInEnvPath() {
|
|
93187
93170
|
const searchPath = process.env.PATH ?? "";
|
|
93188
|
-
for (const dir of searchPath.split(
|
|
93171
|
+
for (const dir of searchPath.split(path108.delimiter)) {
|
|
93189
93172
|
if (!dir)
|
|
93190
93173
|
continue;
|
|
93191
93174
|
const isWindows = process.platform === "win32";
|
|
93192
|
-
const candidate =
|
|
93193
|
-
if (
|
|
93175
|
+
const candidate = path108.join(dir, isWindows ? "rg.exe" : "rg");
|
|
93176
|
+
if (fs85.existsSync(candidate))
|
|
93194
93177
|
return candidate;
|
|
93195
93178
|
}
|
|
93196
93179
|
return null;
|
|
@@ -93317,10 +93300,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
93317
93300
|
return files;
|
|
93318
93301
|
}
|
|
93319
93302
|
try {
|
|
93320
|
-
const entries =
|
|
93303
|
+
const entries = fs85.readdirSync(dir, { withFileTypes: true });
|
|
93321
93304
|
for (const entry of entries) {
|
|
93322
|
-
const fullPath =
|
|
93323
|
-
const relativePath =
|
|
93305
|
+
const fullPath = path108.join(dir, entry.name);
|
|
93306
|
+
const relativePath = path108.relative(workspace, fullPath);
|
|
93324
93307
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
93325
93308
|
continue;
|
|
93326
93309
|
}
|
|
@@ -93361,13 +93344,13 @@ async function fallbackSearch(opts) {
|
|
|
93361
93344
|
const matches = [];
|
|
93362
93345
|
let total = 0;
|
|
93363
93346
|
for (const file3 of files) {
|
|
93364
|
-
const fullPath =
|
|
93347
|
+
const fullPath = path108.join(opts.workspace, file3);
|
|
93365
93348
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
93366
93349
|
continue;
|
|
93367
93350
|
}
|
|
93368
93351
|
let stats;
|
|
93369
93352
|
try {
|
|
93370
|
-
stats =
|
|
93353
|
+
stats = fs85.statSync(fullPath);
|
|
93371
93354
|
if (stats.size > MAX_FILE_SIZE_BYTES10) {
|
|
93372
93355
|
continue;
|
|
93373
93356
|
}
|
|
@@ -93376,7 +93359,7 @@ async function fallbackSearch(opts) {
|
|
|
93376
93359
|
}
|
|
93377
93360
|
let content;
|
|
93378
93361
|
try {
|
|
93379
|
-
content =
|
|
93362
|
+
content = fs85.readFileSync(fullPath, "utf-8");
|
|
93380
93363
|
} catch {
|
|
93381
93364
|
continue;
|
|
93382
93365
|
}
|
|
@@ -93488,7 +93471,7 @@ var search = createSwarmTool({
|
|
|
93488
93471
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
93489
93472
|
}, null, 2);
|
|
93490
93473
|
}
|
|
93491
|
-
if (!
|
|
93474
|
+
if (!fs85.existsSync(directory)) {
|
|
93492
93475
|
return JSON.stringify({
|
|
93493
93476
|
error: true,
|
|
93494
93477
|
type: "unknown",
|
|
@@ -93668,7 +93651,7 @@ init_schema();
|
|
|
93668
93651
|
init_knowledge_store();
|
|
93669
93652
|
import { existsSync as existsSync64 } from "node:fs";
|
|
93670
93653
|
import { mkdir as mkdir17, rename as rename6, writeFile as writeFile14 } from "node:fs/promises";
|
|
93671
|
-
import * as
|
|
93654
|
+
import * as path110 from "node:path";
|
|
93672
93655
|
|
|
93673
93656
|
// src/hooks/skill-improver-llm-factory.ts
|
|
93674
93657
|
init_state();
|
|
@@ -93784,7 +93767,7 @@ init_skill_generator();
|
|
|
93784
93767
|
var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
|
|
93785
93768
|
import { existsSync as existsSync63 } from "node:fs";
|
|
93786
93769
|
import { mkdir as mkdir16, readFile as readFile15, rename as rename5, writeFile as writeFile13 } from "node:fs/promises";
|
|
93787
|
-
import * as
|
|
93770
|
+
import * as path109 from "node:path";
|
|
93788
93771
|
var LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
|
|
93789
93772
|
var LOCK_RETRY_OPTS = {
|
|
93790
93773
|
retries: {
|
|
@@ -93812,7 +93795,7 @@ async function acquireLock2(dir) {
|
|
|
93812
93795
|
}
|
|
93813
93796
|
}
|
|
93814
93797
|
function resolveQuotaPath(directory) {
|
|
93815
|
-
return
|
|
93798
|
+
return path109.join(directory, ".swarm", "skill-improver-quota.json");
|
|
93816
93799
|
}
|
|
93817
93800
|
function todayKey(window2, now = new Date) {
|
|
93818
93801
|
if (window2 === "utc") {
|
|
@@ -93838,7 +93821,7 @@ async function readState(filePath) {
|
|
|
93838
93821
|
}
|
|
93839
93822
|
}
|
|
93840
93823
|
async function writeState(filePath, state) {
|
|
93841
|
-
await mkdir16(
|
|
93824
|
+
await mkdir16(path109.dirname(filePath), { recursive: true });
|
|
93842
93825
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
93843
93826
|
await writeFile13(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
93844
93827
|
await rename5(tmp, filePath);
|
|
@@ -93861,10 +93844,10 @@ async function getQuotaState(directory, opts) {
|
|
|
93861
93844
|
}
|
|
93862
93845
|
async function reserveQuota(directory, opts) {
|
|
93863
93846
|
const filePath = resolveQuotaPath(directory);
|
|
93864
|
-
await mkdir16(
|
|
93847
|
+
await mkdir16(path109.dirname(filePath), { recursive: true });
|
|
93865
93848
|
let release = null;
|
|
93866
93849
|
try {
|
|
93867
|
-
release = await acquireLock2(
|
|
93850
|
+
release = await acquireLock2(path109.dirname(filePath));
|
|
93868
93851
|
const state = await getQuotaState(directory, opts);
|
|
93869
93852
|
if (state.calls_used + opts.nCalls > opts.maxCalls) {
|
|
93870
93853
|
return {
|
|
@@ -93891,10 +93874,10 @@ async function reserveQuota(directory, opts) {
|
|
|
93891
93874
|
}
|
|
93892
93875
|
async function releaseQuota(directory, opts) {
|
|
93893
93876
|
const filePath = resolveQuotaPath(directory);
|
|
93894
|
-
await mkdir16(
|
|
93877
|
+
await mkdir16(path109.dirname(filePath), { recursive: true });
|
|
93895
93878
|
let release = null;
|
|
93896
93879
|
try {
|
|
93897
|
-
release = await acquireLock2(
|
|
93880
|
+
release = await acquireLock2(path109.dirname(filePath));
|
|
93898
93881
|
const state = await getQuotaState(directory, opts);
|
|
93899
93882
|
const next = {
|
|
93900
93883
|
...state,
|
|
@@ -93917,7 +93900,7 @@ function timestampSlug(d) {
|
|
|
93917
93900
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
93918
93901
|
}
|
|
93919
93902
|
async function atomicWrite4(p, content) {
|
|
93920
|
-
await mkdir17(
|
|
93903
|
+
await mkdir17(path110.dirname(p), { recursive: true });
|
|
93921
93904
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
93922
93905
|
await writeFile14(tmp, content, "utf-8");
|
|
93923
93906
|
await rename6(tmp, p);
|
|
@@ -94117,8 +94100,8 @@ async function runSkillImprover(req) {
|
|
|
94117
94100
|
sourceKnowledgeIds: w.sourceKnowledgeIds
|
|
94118
94101
|
}));
|
|
94119
94102
|
}
|
|
94120
|
-
const proposalDir =
|
|
94121
|
-
const proposalFile =
|
|
94103
|
+
const proposalDir = path110.join(req.directory, ".swarm", "skill-improver", "proposals");
|
|
94104
|
+
const proposalFile = path110.join(proposalDir, `${timestampSlug(now)}.md`);
|
|
94122
94105
|
const finalBody = source === "llm" ? buildLLMProposalFrame({
|
|
94123
94106
|
body: body2,
|
|
94124
94107
|
targets,
|
|
@@ -94211,7 +94194,7 @@ init_config();
|
|
|
94211
94194
|
init_schema();
|
|
94212
94195
|
init_create_tool();
|
|
94213
94196
|
import { mkdir as mkdir18, rename as rename7, writeFile as writeFile15 } from "node:fs/promises";
|
|
94214
|
-
import * as
|
|
94197
|
+
import * as path111 from "node:path";
|
|
94215
94198
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
94216
94199
|
var spec_write = createSwarmTool({
|
|
94217
94200
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -94252,14 +94235,14 @@ var spec_write = createSwarmTool({
|
|
|
94252
94235
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
94253
94236
|
}, null, 2);
|
|
94254
94237
|
}
|
|
94255
|
-
const target =
|
|
94256
|
-
await mkdir18(
|
|
94238
|
+
const target = path111.join(directory, ".swarm", "spec.md");
|
|
94239
|
+
await mkdir18(path111.dirname(target), { recursive: true });
|
|
94257
94240
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
94258
94241
|
let finalContent = content;
|
|
94259
94242
|
if (mode === "append") {
|
|
94260
94243
|
try {
|
|
94261
|
-
const
|
|
94262
|
-
const prior = await
|
|
94244
|
+
const fs86 = await import("node:fs/promises");
|
|
94245
|
+
const prior = await fs86.readFile(target, "utf-8");
|
|
94263
94246
|
finalContent = `${prior.replace(/\s+$/, "")}
|
|
94264
94247
|
|
|
94265
94248
|
${content}
|
|
@@ -94280,6 +94263,15 @@ ${content}
|
|
|
94280
94263
|
// src/tools/submit-phase-council-verdicts.ts
|
|
94281
94264
|
init_zod();
|
|
94282
94265
|
init_loader();
|
|
94266
|
+
import {
|
|
94267
|
+
existsSync as existsSync65,
|
|
94268
|
+
mkdirSync as mkdirSync28,
|
|
94269
|
+
readFileSync as readFileSync55,
|
|
94270
|
+
renameSync as renameSync18,
|
|
94271
|
+
unlinkSync as unlinkSync14,
|
|
94272
|
+
writeFileSync as writeFileSync22
|
|
94273
|
+
} from "node:fs";
|
|
94274
|
+
import path112 from "node:path";
|
|
94283
94275
|
init_create_tool();
|
|
94284
94276
|
init_resolve_working_directory();
|
|
94285
94277
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -94382,6 +94374,12 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
94382
94374
|
}, null, 2);
|
|
94383
94375
|
}
|
|
94384
94376
|
const synthesis = synthesizePhaseCouncilAdvisory(input.phaseNumber, input.phaseSummary, input.verdicts, input.roundNumber ?? 1, config3.council, workingDir);
|
|
94377
|
+
const existingMutationGapFinding = input.verdicts.some((verdict) => verdict.findings.some((finding) => finding.category === "mutation_gap"));
|
|
94378
|
+
const mutationGapFinding = existingMutationGapFinding ? null : getPhaseMutationGapFinding(input.phaseNumber, workingDir);
|
|
94379
|
+
if (mutationGapFinding) {
|
|
94380
|
+
addMutationGapFindingToSynthesis(synthesis, mutationGapFinding);
|
|
94381
|
+
}
|
|
94382
|
+
writePhaseCouncilEvidence(workingDir, synthesis);
|
|
94385
94383
|
return JSON.stringify({
|
|
94386
94384
|
success: true,
|
|
94387
94385
|
overallVerdict: synthesis.overallVerdict,
|
|
@@ -94392,6 +94390,7 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
94392
94390
|
advisoryFindingsCount: synthesis.advisoryFindings?.length ?? 0,
|
|
94393
94391
|
unresolvedConflictsCount: synthesis.unresolvedConflicts?.length ?? 0,
|
|
94394
94392
|
advisoryNotes: synthesis.advisoryNotes ?? [],
|
|
94393
|
+
mutationGapEmitted: mutationGapFinding !== null,
|
|
94395
94394
|
membersVoted,
|
|
94396
94395
|
membersAbsent,
|
|
94397
94396
|
quorumSize: membersVoted.length,
|
|
@@ -94401,11 +94400,132 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
94401
94400
|
}, null, 2);
|
|
94402
94401
|
}
|
|
94403
94402
|
});
|
|
94403
|
+
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
94404
|
+
const mutationGatePath = path112.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
94405
|
+
try {
|
|
94406
|
+
const raw = readFileSync55(mutationGatePath, "utf-8");
|
|
94407
|
+
const parsed = JSON.parse(raw);
|
|
94408
|
+
const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
|
|
94409
|
+
if (!gateEntry) {
|
|
94410
|
+
return {
|
|
94411
|
+
severity: "HIGH",
|
|
94412
|
+
category: "mutation_gap",
|
|
94413
|
+
location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
|
|
94414
|
+
detail: "Mutation gate evidence is missing a mutation-gate entry for this phase.",
|
|
94415
|
+
evidence: 'Expected entries[].type="mutation-gate" with verdict in mutation-gate.json.'
|
|
94416
|
+
};
|
|
94417
|
+
}
|
|
94418
|
+
if (gateEntry.verdict === "skip") {
|
|
94419
|
+
return {
|
|
94420
|
+
severity: "MEDIUM",
|
|
94421
|
+
category: "mutation_gap",
|
|
94422
|
+
location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
|
|
94423
|
+
detail: "Mutation testing was skipped for this phase; coverage is unverified.",
|
|
94424
|
+
evidence: 'mutation-gate.json recorded verdict="skip". Run mutation_test and write_mutation_evidence.'
|
|
94425
|
+
};
|
|
94426
|
+
}
|
|
94427
|
+
if (gateEntry.verdict === "warn") {
|
|
94428
|
+
return {
|
|
94429
|
+
severity: "LOW",
|
|
94430
|
+
category: "mutation_gap",
|
|
94431
|
+
location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
|
|
94432
|
+
detail: "Mutation gate reported WARN; mutation coverage may be insufficient.",
|
|
94433
|
+
evidence: 'mutation-gate.json recorded verdict="warn" indicating below-pass mutation quality.'
|
|
94434
|
+
};
|
|
94435
|
+
}
|
|
94436
|
+
if (gateEntry.verdict === "fail") {
|
|
94437
|
+
return {
|
|
94438
|
+
severity: "HIGH",
|
|
94439
|
+
category: "mutation_gap",
|
|
94440
|
+
location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
|
|
94441
|
+
detail: "Mutation gate reported FAIL; mutation testing quality is below the required threshold.",
|
|
94442
|
+
evidence: 'mutation-gate.json recorded verdict="fail" indicating insufficient mutation kill rate.'
|
|
94443
|
+
};
|
|
94444
|
+
}
|
|
94445
|
+
return null;
|
|
94446
|
+
} catch (error93) {
|
|
94447
|
+
if (error93.code === "ENOENT") {
|
|
94448
|
+
return {
|
|
94449
|
+
severity: "HIGH",
|
|
94450
|
+
category: "mutation_gap",
|
|
94451
|
+
location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
|
|
94452
|
+
detail: "Mutation gate evidence file is missing for this phase, so mutation coverage cannot be verified.",
|
|
94453
|
+
evidence: "No .swarm/evidence/{phase}/mutation-gate.json was found at council synthesis time."
|
|
94454
|
+
};
|
|
94455
|
+
}
|
|
94456
|
+
return {
|
|
94457
|
+
severity: "MEDIUM",
|
|
94458
|
+
category: "mutation_gap",
|
|
94459
|
+
location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
|
|
94460
|
+
detail: "Mutation gate evidence could not be read, so mutation coverage cannot be verified.",
|
|
94461
|
+
evidence: error93 instanceof Error ? error93.message : String(error93)
|
|
94462
|
+
};
|
|
94463
|
+
}
|
|
94464
|
+
}
|
|
94465
|
+
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
94466
|
+
const evidenceDir = path112.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
94467
|
+
mkdirSync28(evidenceDir, { recursive: true });
|
|
94468
|
+
const evidenceFile = path112.join(evidenceDir, "phase-council.json");
|
|
94469
|
+
const evidenceBundle = {
|
|
94470
|
+
entries: [
|
|
94471
|
+
{
|
|
94472
|
+
type: "phase-council",
|
|
94473
|
+
phase_number: synthesis.phaseNumber,
|
|
94474
|
+
scope: "phase",
|
|
94475
|
+
timestamp: synthesis.timestamp,
|
|
94476
|
+
verdict: synthesis.overallVerdict,
|
|
94477
|
+
quorumSize: synthesis.quorumSize,
|
|
94478
|
+
phaseSummary: synthesis.phaseSummary ?? "",
|
|
94479
|
+
requiredFixes: synthesis.requiredFixes.map((finding) => ({
|
|
94480
|
+
severity: finding.severity,
|
|
94481
|
+
category: finding.category,
|
|
94482
|
+
location: finding.location,
|
|
94483
|
+
detail: finding.detail,
|
|
94484
|
+
evidence: finding.evidence
|
|
94485
|
+
})),
|
|
94486
|
+
advisoryNotes: synthesis.advisoryNotes,
|
|
94487
|
+
advisoryFindings: synthesis.advisoryFindings.map((finding) => ({
|
|
94488
|
+
severity: finding.severity,
|
|
94489
|
+
category: finding.category,
|
|
94490
|
+
location: finding.location,
|
|
94491
|
+
detail: finding.detail,
|
|
94492
|
+
evidence: finding.evidence
|
|
94493
|
+
})),
|
|
94494
|
+
roundNumber: synthesis.roundNumber,
|
|
94495
|
+
allCriteriaMet: synthesis.allCriteriaMet
|
|
94496
|
+
}
|
|
94497
|
+
]
|
|
94498
|
+
};
|
|
94499
|
+
const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
|
|
94500
|
+
try {
|
|
94501
|
+
writeFileSync22(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
94502
|
+
renameSync18(tempFile, evidenceFile);
|
|
94503
|
+
} finally {
|
|
94504
|
+
if (existsSync65(tempFile)) {
|
|
94505
|
+
unlinkSync14(tempFile);
|
|
94506
|
+
}
|
|
94507
|
+
}
|
|
94508
|
+
}
|
|
94509
|
+
function addMutationGapFindingToSynthesis(synthesis, finding) {
|
|
94510
|
+
if (finding.severity === "HIGH" || finding.severity === "MEDIUM") {
|
|
94511
|
+
synthesis.requiredFixes.push(finding);
|
|
94512
|
+
} else {
|
|
94513
|
+
synthesis.advisoryFindings.push(finding);
|
|
94514
|
+
}
|
|
94515
|
+
synthesis.unifiedFeedbackMd += formatMutationGapFeedback(finding);
|
|
94516
|
+
}
|
|
94517
|
+
function formatMutationGapFeedback(finding) {
|
|
94518
|
+
return `
|
|
94519
|
+
|
|
94520
|
+
### Mutation Coverage Gap
|
|
94521
|
+
- **[${finding.severity}]** \`${finding.location}\` (${finding.category}) — ${finding.detail}
|
|
94522
|
+
_Evidence:_ ${finding.evidence}`;
|
|
94523
|
+
}
|
|
94404
94524
|
// src/tools/suggest-patch.ts
|
|
94405
94525
|
init_zod();
|
|
94406
94526
|
init_path_security();
|
|
94407
94527
|
init_create_tool();
|
|
94408
|
-
import * as
|
|
94528
|
+
import * as fs86 from "node:fs";
|
|
94409
94529
|
import * as path113 from "node:path";
|
|
94410
94530
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
94411
94531
|
function containsWindowsAttacks4(str) {
|
|
@@ -94421,11 +94541,11 @@ function containsWindowsAttacks4(str) {
|
|
|
94421
94541
|
function isPathInWorkspace4(filePath, workspace) {
|
|
94422
94542
|
try {
|
|
94423
94543
|
const resolvedPath = path113.resolve(workspace, filePath);
|
|
94424
|
-
if (!
|
|
94544
|
+
if (!fs86.existsSync(resolvedPath)) {
|
|
94425
94545
|
return true;
|
|
94426
94546
|
}
|
|
94427
|
-
const realWorkspace =
|
|
94428
|
-
const realResolvedPath =
|
|
94547
|
+
const realWorkspace = fs86.realpathSync(workspace);
|
|
94548
|
+
const realResolvedPath = fs86.realpathSync(resolvedPath);
|
|
94429
94549
|
const relativePath = path113.relative(realWorkspace, realResolvedPath);
|
|
94430
94550
|
if (relativePath.startsWith("..") || path113.isAbsolute(relativePath)) {
|
|
94431
94551
|
return false;
|
|
@@ -94599,7 +94719,7 @@ var suggestPatch = createSwarmTool({
|
|
|
94599
94719
|
message: "changes cannot be empty"
|
|
94600
94720
|
}, null, 2);
|
|
94601
94721
|
}
|
|
94602
|
-
if (!
|
|
94722
|
+
if (!fs86.existsSync(directory)) {
|
|
94603
94723
|
return JSON.stringify({
|
|
94604
94724
|
success: false,
|
|
94605
94725
|
error: true,
|
|
@@ -94636,7 +94756,7 @@ var suggestPatch = createSwarmTool({
|
|
|
94636
94756
|
continue;
|
|
94637
94757
|
}
|
|
94638
94758
|
const fullPath = path113.resolve(directory, change.file);
|
|
94639
|
-
if (!
|
|
94759
|
+
if (!fs86.existsSync(fullPath)) {
|
|
94640
94760
|
errors5.push({
|
|
94641
94761
|
success: false,
|
|
94642
94762
|
error: true,
|
|
@@ -94650,7 +94770,7 @@ var suggestPatch = createSwarmTool({
|
|
|
94650
94770
|
}
|
|
94651
94771
|
let content;
|
|
94652
94772
|
try {
|
|
94653
|
-
content =
|
|
94773
|
+
content = fs86.readFileSync(fullPath, "utf-8");
|
|
94654
94774
|
} catch (err3) {
|
|
94655
94775
|
errors5.push({
|
|
94656
94776
|
success: false,
|
|
@@ -94897,7 +95017,7 @@ var generate_mutants = createSwarmTool({
|
|
|
94897
95017
|
// src/tools/lint-spec.ts
|
|
94898
95018
|
init_spec_schema();
|
|
94899
95019
|
init_create_tool();
|
|
94900
|
-
import * as
|
|
95020
|
+
import * as fs87 from "node:fs";
|
|
94901
95021
|
import * as path114 from "node:path";
|
|
94902
95022
|
var SPEC_FILE_NAME = "spec.md";
|
|
94903
95023
|
var SWARM_DIR2 = ".swarm";
|
|
@@ -94952,7 +95072,7 @@ var lint_spec = createSwarmTool({
|
|
|
94952
95072
|
const errors5 = [];
|
|
94953
95073
|
const warnings = [];
|
|
94954
95074
|
const specPath = path114.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
94955
|
-
if (!
|
|
95075
|
+
if (!fs87.existsSync(specPath)) {
|
|
94956
95076
|
const result2 = {
|
|
94957
95077
|
valid: false,
|
|
94958
95078
|
specMtime: null,
|
|
@@ -94971,12 +95091,12 @@ var lint_spec = createSwarmTool({
|
|
|
94971
95091
|
}
|
|
94972
95092
|
let specMtime = null;
|
|
94973
95093
|
try {
|
|
94974
|
-
const stats =
|
|
95094
|
+
const stats = fs87.statSync(specPath);
|
|
94975
95095
|
specMtime = stats.mtime.toISOString();
|
|
94976
95096
|
} catch {}
|
|
94977
95097
|
let content;
|
|
94978
95098
|
try {
|
|
94979
|
-
content =
|
|
95099
|
+
content = fs87.readFileSync(specPath, "utf-8");
|
|
94980
95100
|
} catch (e) {
|
|
94981
95101
|
const result2 = {
|
|
94982
95102
|
valid: false,
|
|
@@ -95021,12 +95141,12 @@ var lint_spec = createSwarmTool({
|
|
|
95021
95141
|
});
|
|
95022
95142
|
// src/tools/mutation-test.ts
|
|
95023
95143
|
init_zod();
|
|
95024
|
-
import * as
|
|
95144
|
+
import * as fs88 from "node:fs";
|
|
95025
95145
|
import * as path116 from "node:path";
|
|
95026
95146
|
|
|
95027
95147
|
// src/mutation/engine.ts
|
|
95028
95148
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
95029
|
-
import { unlinkSync as
|
|
95149
|
+
import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync23 } from "node:fs";
|
|
95030
95150
|
import * as path115 from "node:path";
|
|
95031
95151
|
|
|
95032
95152
|
// src/mutation/equivalence.ts
|
|
@@ -95169,7 +95289,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
95169
95289
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
95170
95290
|
patchFile = path115.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
95171
95291
|
try {
|
|
95172
|
-
|
|
95292
|
+
writeFileSync23(patchFile, patch.patch);
|
|
95173
95293
|
} catch (writeErr) {
|
|
95174
95294
|
error93 = `Failed to write patch file: ${writeErr}`;
|
|
95175
95295
|
outcome = "error";
|
|
@@ -95265,7 +95385,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
95265
95385
|
revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
|
|
95266
95386
|
}
|
|
95267
95387
|
try {
|
|
95268
|
-
|
|
95388
|
+
unlinkSync15(patchFile);
|
|
95269
95389
|
} catch (_unlinkErr) {}
|
|
95270
95390
|
}
|
|
95271
95391
|
}
|
|
@@ -95567,7 +95687,7 @@ var mutation_test = createSwarmTool({
|
|
|
95567
95687
|
for (const filePath of uniquePaths) {
|
|
95568
95688
|
try {
|
|
95569
95689
|
const resolvedPath = path116.resolve(cwd, filePath);
|
|
95570
|
-
sourceFiles.set(filePath,
|
|
95690
|
+
sourceFiles.set(filePath, fs88.readFileSync(resolvedPath, "utf-8"));
|
|
95571
95691
|
} catch {}
|
|
95572
95692
|
}
|
|
95573
95693
|
const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
|
|
@@ -95585,7 +95705,7 @@ var mutation_test = createSwarmTool({
|
|
|
95585
95705
|
init_zod();
|
|
95586
95706
|
init_manager2();
|
|
95587
95707
|
init_detector();
|
|
95588
|
-
import * as
|
|
95708
|
+
import * as fs89 from "node:fs";
|
|
95589
95709
|
import * as path117 from "node:path";
|
|
95590
95710
|
init_create_tool();
|
|
95591
95711
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
@@ -95695,7 +95815,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
95695
95815
|
}
|
|
95696
95816
|
let content;
|
|
95697
95817
|
try {
|
|
95698
|
-
content =
|
|
95818
|
+
content = fs89.readFileSync(fullPath, "utf8");
|
|
95699
95819
|
} catch {
|
|
95700
95820
|
result.skipped_reason = "file_read_error";
|
|
95701
95821
|
skippedCount++;
|
|
@@ -95806,7 +95926,7 @@ init_zod();
|
|
|
95806
95926
|
init_utils();
|
|
95807
95927
|
init_create_tool();
|
|
95808
95928
|
init_path_security();
|
|
95809
|
-
import * as
|
|
95929
|
+
import * as fs90 from "node:fs";
|
|
95810
95930
|
import * as path118 from "node:path";
|
|
95811
95931
|
var MAX_TEXT_LENGTH = 200;
|
|
95812
95932
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
@@ -95897,7 +96017,7 @@ function isSupportedExtension(filePath) {
|
|
|
95897
96017
|
function findSourceFiles3(dir, files = []) {
|
|
95898
96018
|
let entries;
|
|
95899
96019
|
try {
|
|
95900
|
-
entries =
|
|
96020
|
+
entries = fs90.readdirSync(dir);
|
|
95901
96021
|
} catch {
|
|
95902
96022
|
return files;
|
|
95903
96023
|
}
|
|
@@ -95909,7 +96029,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
95909
96029
|
const fullPath = path118.join(dir, entry);
|
|
95910
96030
|
let stat7;
|
|
95911
96031
|
try {
|
|
95912
|
-
stat7 =
|
|
96032
|
+
stat7 = fs90.statSync(fullPath);
|
|
95913
96033
|
} catch {
|
|
95914
96034
|
continue;
|
|
95915
96035
|
}
|
|
@@ -96002,7 +96122,7 @@ var todo_extract = createSwarmTool({
|
|
|
96002
96122
|
return JSON.stringify(errorResult, null, 2);
|
|
96003
96123
|
}
|
|
96004
96124
|
const scanPath = resolvedPath;
|
|
96005
|
-
if (!
|
|
96125
|
+
if (!fs90.existsSync(scanPath)) {
|
|
96006
96126
|
const errorResult = {
|
|
96007
96127
|
error: `path not found: ${pathsInput}`,
|
|
96008
96128
|
total: 0,
|
|
@@ -96012,7 +96132,7 @@ var todo_extract = createSwarmTool({
|
|
|
96012
96132
|
return JSON.stringify(errorResult, null, 2);
|
|
96013
96133
|
}
|
|
96014
96134
|
const filesToScan = [];
|
|
96015
|
-
const stat7 =
|
|
96135
|
+
const stat7 = fs90.statSync(scanPath);
|
|
96016
96136
|
if (stat7.isFile()) {
|
|
96017
96137
|
if (isSupportedExtension(scanPath)) {
|
|
96018
96138
|
filesToScan.push(scanPath);
|
|
@@ -96031,11 +96151,11 @@ var todo_extract = createSwarmTool({
|
|
|
96031
96151
|
const allEntries = [];
|
|
96032
96152
|
for (const filePath of filesToScan) {
|
|
96033
96153
|
try {
|
|
96034
|
-
const fileStat =
|
|
96154
|
+
const fileStat = fs90.statSync(filePath);
|
|
96035
96155
|
if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
|
|
96036
96156
|
continue;
|
|
96037
96157
|
}
|
|
96038
|
-
const content =
|
|
96158
|
+
const content = fs90.readFileSync(filePath, "utf-8");
|
|
96039
96159
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
96040
96160
|
allEntries.push(...entries);
|
|
96041
96161
|
} catch {}
|
|
@@ -96066,17 +96186,17 @@ init_loader();
|
|
|
96066
96186
|
init_schema();
|
|
96067
96187
|
init_qa_gate_profile();
|
|
96068
96188
|
init_gate_evidence();
|
|
96069
|
-
import * as
|
|
96189
|
+
import * as fs93 from "node:fs";
|
|
96070
96190
|
import * as path121 from "node:path";
|
|
96071
96191
|
|
|
96072
96192
|
// src/hooks/diff-scope.ts
|
|
96073
96193
|
init_bun_compat();
|
|
96074
|
-
import * as
|
|
96194
|
+
import * as fs92 from "node:fs";
|
|
96075
96195
|
import * as path120 from "node:path";
|
|
96076
96196
|
|
|
96077
96197
|
// src/utils/gitignore-warning.ts
|
|
96078
96198
|
init_bun_compat();
|
|
96079
|
-
import * as
|
|
96199
|
+
import * as fs91 from "node:fs";
|
|
96080
96200
|
import * as path119 from "node:path";
|
|
96081
96201
|
var _internals36 = { bunSpawn };
|
|
96082
96202
|
var _swarmGitExcludedChecked = false;
|
|
@@ -96154,13 +96274,13 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
96154
96274
|
const excludePath = path119.isAbsolute(excludeRelPath) ? excludeRelPath : path119.join(directory, excludeRelPath);
|
|
96155
96275
|
if (checkIgnoreExitCode !== 0) {
|
|
96156
96276
|
try {
|
|
96157
|
-
|
|
96277
|
+
fs91.mkdirSync(path119.dirname(excludePath), { recursive: true });
|
|
96158
96278
|
let existing = "";
|
|
96159
96279
|
try {
|
|
96160
|
-
existing =
|
|
96280
|
+
existing = fs91.readFileSync(excludePath, "utf8");
|
|
96161
96281
|
} catch {}
|
|
96162
96282
|
if (!fileCoversSwarm(existing)) {
|
|
96163
|
-
|
|
96283
|
+
fs91.appendFileSync(excludePath, `
|
|
96164
96284
|
# opencode-swarm local runtime state
|
|
96165
96285
|
.swarm/
|
|
96166
96286
|
`, "utf8");
|
|
@@ -96199,9 +96319,9 @@ var _internals37 = { bunSpawn };
|
|
|
96199
96319
|
function getDeclaredScope(taskId, directory) {
|
|
96200
96320
|
try {
|
|
96201
96321
|
const planPath = path120.join(directory, ".swarm", "plan.json");
|
|
96202
|
-
if (!
|
|
96322
|
+
if (!fs92.existsSync(planPath))
|
|
96203
96323
|
return null;
|
|
96204
|
-
const raw =
|
|
96324
|
+
const raw = fs92.readFileSync(planPath, "utf-8");
|
|
96205
96325
|
const plan = JSON.parse(raw);
|
|
96206
96326
|
for (const phase of plan.phases ?? []) {
|
|
96207
96327
|
for (const task of phase.tasks ?? []) {
|
|
@@ -96350,7 +96470,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
96350
96470
|
const resolvedDir2 = workingDirectory;
|
|
96351
96471
|
try {
|
|
96352
96472
|
const planPath = path121.join(resolvedDir2, ".swarm", "plan.json");
|
|
96353
|
-
const planRaw =
|
|
96473
|
+
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
96354
96474
|
const plan = JSON.parse(planRaw);
|
|
96355
96475
|
for (const planPhase of plan.phases ?? []) {
|
|
96356
96476
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -96417,7 +96537,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
96417
96537
|
try {
|
|
96418
96538
|
const resolvedDir2 = workingDirectory;
|
|
96419
96539
|
const planPath = path121.join(resolvedDir2, ".swarm", "plan.json");
|
|
96420
|
-
const planRaw =
|
|
96540
|
+
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
96421
96541
|
const plan = JSON.parse(planRaw);
|
|
96422
96542
|
for (const planPhase of plan.phases ?? []) {
|
|
96423
96543
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -96614,9 +96734,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
96614
96734
|
}
|
|
96615
96735
|
const resolvedDir = path121.resolve(normalizedDir);
|
|
96616
96736
|
try {
|
|
96617
|
-
const realPath =
|
|
96737
|
+
const realPath = fs93.realpathSync(resolvedDir);
|
|
96618
96738
|
const planPath = path121.join(realPath, ".swarm", "plan.json");
|
|
96619
|
-
if (!
|
|
96739
|
+
if (!fs93.existsSync(planPath)) {
|
|
96620
96740
|
return {
|
|
96621
96741
|
success: false,
|
|
96622
96742
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -96648,21 +96768,21 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
96648
96768
|
if (args2.status === "in_progress") {
|
|
96649
96769
|
try {
|
|
96650
96770
|
const evidencePath = path121.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
96651
|
-
|
|
96652
|
-
const fd =
|
|
96771
|
+
fs93.mkdirSync(path121.dirname(evidencePath), { recursive: true });
|
|
96772
|
+
const fd = fs93.openSync(evidencePath, "wx");
|
|
96653
96773
|
let writeOk = false;
|
|
96654
96774
|
try {
|
|
96655
|
-
|
|
96775
|
+
fs93.writeSync(fd, JSON.stringify({
|
|
96656
96776
|
taskId: args2.task_id,
|
|
96657
96777
|
required_gates: ["reviewer", "test_engineer"],
|
|
96658
96778
|
gates: {}
|
|
96659
96779
|
}, null, 2));
|
|
96660
96780
|
writeOk = true;
|
|
96661
96781
|
} finally {
|
|
96662
|
-
|
|
96782
|
+
fs93.closeSync(fd);
|
|
96663
96783
|
if (!writeOk) {
|
|
96664
96784
|
try {
|
|
96665
|
-
|
|
96785
|
+
fs93.unlinkSync(evidencePath);
|
|
96666
96786
|
} catch {}
|
|
96667
96787
|
}
|
|
96668
96788
|
}
|
|
@@ -96673,7 +96793,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
96673
96793
|
let phaseRequiresReviewer = true;
|
|
96674
96794
|
try {
|
|
96675
96795
|
const planPath = path121.join(directory, ".swarm", "plan.json");
|
|
96676
|
-
const planRaw =
|
|
96796
|
+
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
96677
96797
|
const plan = JSON.parse(planRaw);
|
|
96678
96798
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
96679
96799
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -96983,7 +97103,7 @@ init_utils2();
|
|
|
96983
97103
|
init_ledger();
|
|
96984
97104
|
init_manager();
|
|
96985
97105
|
init_create_tool();
|
|
96986
|
-
import
|
|
97106
|
+
import fs94 from "node:fs";
|
|
96987
97107
|
import path122 from "node:path";
|
|
96988
97108
|
function normalizeVerdict(verdict) {
|
|
96989
97109
|
switch (verdict) {
|
|
@@ -97045,10 +97165,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
97045
97165
|
}
|
|
97046
97166
|
const evidenceDir = path122.dirname(validatedPath);
|
|
97047
97167
|
try {
|
|
97048
|
-
await
|
|
97168
|
+
await fs94.promises.mkdir(evidenceDir, { recursive: true });
|
|
97049
97169
|
const tempPath = path122.join(evidenceDir, `.${filename}.tmp`);
|
|
97050
|
-
await
|
|
97051
|
-
await
|
|
97170
|
+
await fs94.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97171
|
+
await fs94.promises.rename(tempPath, validatedPath);
|
|
97052
97172
|
let snapshotInfo;
|
|
97053
97173
|
let snapshotError;
|
|
97054
97174
|
let qaProfileLocked;
|
|
@@ -97143,7 +97263,7 @@ init_zod();
|
|
|
97143
97263
|
init_utils2();
|
|
97144
97264
|
init_manager();
|
|
97145
97265
|
init_create_tool();
|
|
97146
|
-
import
|
|
97266
|
+
import fs95 from "node:fs";
|
|
97147
97267
|
import path123 from "node:path";
|
|
97148
97268
|
function normalizeVerdict2(verdict) {
|
|
97149
97269
|
switch (verdict) {
|
|
@@ -97208,10 +97328,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
97208
97328
|
}
|
|
97209
97329
|
const evidenceDir = path123.dirname(validatedPath);
|
|
97210
97330
|
try {
|
|
97211
|
-
await
|
|
97331
|
+
await fs95.promises.mkdir(evidenceDir, { recursive: true });
|
|
97212
97332
|
const tempPath = path123.join(evidenceDir, `.${filename}.tmp`);
|
|
97213
|
-
await
|
|
97214
|
-
await
|
|
97333
|
+
await fs95.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97334
|
+
await fs95.promises.rename(tempPath, validatedPath);
|
|
97215
97335
|
return JSON.stringify({
|
|
97216
97336
|
success: true,
|
|
97217
97337
|
phase,
|
|
@@ -97255,7 +97375,7 @@ var write_final_council_evidence = createSwarmTool({
|
|
|
97255
97375
|
init_zod();
|
|
97256
97376
|
init_utils2();
|
|
97257
97377
|
init_create_tool();
|
|
97258
|
-
import
|
|
97378
|
+
import fs96 from "node:fs";
|
|
97259
97379
|
import path124 from "node:path";
|
|
97260
97380
|
function normalizeVerdict3(verdict) {
|
|
97261
97381
|
switch (verdict) {
|
|
@@ -97317,10 +97437,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
97317
97437
|
}
|
|
97318
97438
|
const evidenceDir = path124.dirname(validatedPath);
|
|
97319
97439
|
try {
|
|
97320
|
-
await
|
|
97440
|
+
await fs96.promises.mkdir(evidenceDir, { recursive: true });
|
|
97321
97441
|
const tempPath = path124.join(evidenceDir, `.${filename}.tmp`);
|
|
97322
|
-
await
|
|
97323
|
-
await
|
|
97442
|
+
await fs96.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97443
|
+
await fs96.promises.rename(tempPath, validatedPath);
|
|
97324
97444
|
return JSON.stringify({
|
|
97325
97445
|
success: true,
|
|
97326
97446
|
phase,
|
|
@@ -97366,7 +97486,7 @@ var write_hallucination_evidence = createSwarmTool({
|
|
|
97366
97486
|
init_zod();
|
|
97367
97487
|
init_utils2();
|
|
97368
97488
|
init_create_tool();
|
|
97369
|
-
import
|
|
97489
|
+
import fs97 from "node:fs";
|
|
97370
97490
|
import path125 from "node:path";
|
|
97371
97491
|
function normalizeVerdict4(verdict) {
|
|
97372
97492
|
switch (verdict) {
|
|
@@ -97454,10 +97574,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
97454
97574
|
}
|
|
97455
97575
|
const evidenceDir = path125.dirname(validatedPath);
|
|
97456
97576
|
try {
|
|
97457
|
-
await
|
|
97577
|
+
await fs97.promises.mkdir(evidenceDir, { recursive: true });
|
|
97458
97578
|
const tempPath = path125.join(evidenceDir, `.${filename}.tmp`);
|
|
97459
|
-
await
|
|
97460
|
-
await
|
|
97579
|
+
await fs97.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97580
|
+
await fs97.promises.rename(tempPath, validatedPath);
|
|
97461
97581
|
return JSON.stringify({
|
|
97462
97582
|
success: true,
|
|
97463
97583
|
phase,
|
|
@@ -97943,15 +98063,19 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
97943
98063
|
...opencodeConfig.command || {},
|
|
97944
98064
|
swarm: {
|
|
97945
98065
|
template: "/swarm $ARGUMENTS",
|
|
97946
|
-
description: "Swarm management commands: /swarm [status|plan|agents|history|config|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|issue|qa-gates|dark-matter|knowledge|curate|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor
|
|
98066
|
+
description: "Swarm management commands: /swarm [status|show-plan|plan|agents|history|config|help|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|issue|qa-gates|dark-matter|knowledge|curate|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor tools|finalize|close]"
|
|
97947
98067
|
},
|
|
97948
98068
|
"swarm-status": {
|
|
97949
98069
|
template: "/swarm status",
|
|
97950
98070
|
description: "Use /swarm status to show current swarm status and active phase"
|
|
97951
98071
|
},
|
|
98072
|
+
"swarm-show-plan": {
|
|
98073
|
+
template: "/swarm show-plan $ARGUMENTS",
|
|
98074
|
+
description: "Use /swarm show-plan to view or filter the current execution plan"
|
|
98075
|
+
},
|
|
97952
98076
|
"swarm-plan": {
|
|
97953
98077
|
template: "/swarm plan $ARGUMENTS",
|
|
97954
|
-
description: "
|
|
98078
|
+
description: "Deprecated alias for /swarm show-plan"
|
|
97955
98079
|
},
|
|
97956
98080
|
"swarm-agents": {
|
|
97957
98081
|
template: "/swarm agents",
|
|
@@ -98031,7 +98155,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
98031
98155
|
},
|
|
98032
98156
|
"swarm-council": {
|
|
98033
98157
|
template: "/swarm council $ARGUMENTS",
|
|
98034
|
-
description: "Use /swarm council <question> to convene a multi-model General Council deliberation (generalist / skeptic / domain expert) [--spec-review]"
|
|
98158
|
+
description: "Use /swarm council <question> to convene a multi-model General Council deliberation (generalist / skeptic / domain expert) [--preset <name>] [--spec-review]"
|
|
98035
98159
|
},
|
|
98036
98160
|
"swarm-pr-review": {
|
|
98037
98161
|
template: "/swarm pr-review $ARGUMENTS",
|
|
@@ -98093,9 +98217,13 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
98093
98217
|
template: "/swarm evidence summary",
|
|
98094
98218
|
description: "Use /swarm evidence summary to generate evidence summaries"
|
|
98095
98219
|
},
|
|
98220
|
+
"swarm-finalize": {
|
|
98221
|
+
template: "/swarm finalize",
|
|
98222
|
+
description: "Use /swarm finalize to archive the swarm project and close active state"
|
|
98223
|
+
},
|
|
98096
98224
|
"swarm-close": {
|
|
98097
98225
|
template: "/swarm close",
|
|
98098
|
-
description: "
|
|
98226
|
+
description: "Deprecated alias for /swarm finalize"
|
|
98099
98227
|
},
|
|
98100
98228
|
"swarm-acknowledge-spec-drift": {
|
|
98101
98229
|
template: "/swarm acknowledge-spec-drift",
|