opencode-swarm 7.11.1 → 7.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/dist/cli/index.js +39 -10
- 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 +611 -441
- 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.0",
|
|
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",
|
|
@@ -23769,6 +23769,13 @@ var init_normalize_tool_name = __esm(() => {
|
|
|
23769
23769
|
import * as fsSync2 from "node:fs";
|
|
23770
23770
|
import * as fs8 from "node:fs/promises";
|
|
23771
23771
|
import * as path10 from "node:path";
|
|
23772
|
+
function extractStatusCode(errorMsg) {
|
|
23773
|
+
const match = errorMsg.match(/\b(408|429|500|502|503|504|529)\b/);
|
|
23774
|
+
if (match) {
|
|
23775
|
+
return parseInt(match[1], 10);
|
|
23776
|
+
}
|
|
23777
|
+
return null;
|
|
23778
|
+
}
|
|
23772
23779
|
function getStoredInputArgs(callID) {
|
|
23773
23780
|
return storedInputArgs.get(callID);
|
|
23774
23781
|
}
|
|
@@ -24977,14 +24984,40 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
24977
24984
|
if (hasError) {
|
|
24978
24985
|
const outputStr = typeof output.output === "string" ? output.output : "";
|
|
24979
24986
|
const errorContent = output.error ?? outputStr;
|
|
24987
|
+
const extractedStatus = typeof errorContent === "string" ? extractStatusCode(errorContent) : null;
|
|
24988
|
+
const isTransientStatusCode = extractedStatus !== null && TRANSIENT_STATUS_CODES.has(extractedStatus);
|
|
24980
24989
|
const isTransientPatternMatch = typeof errorContent === "string" && TRANSIENT_MODEL_ERROR_PATTERN.test(errorContent);
|
|
24981
|
-
const
|
|
24982
|
-
|
|
24983
|
-
|
|
24984
|
-
|
|
24990
|
+
const isTransientMatch = isTransientStatusCode || isTransientPatternMatch;
|
|
24991
|
+
const isTransient = !!session && isTransientMatch && window2.transientRetryCount < cfg.max_transient_retries;
|
|
24992
|
+
const isDegraded = !isTransient && typeof errorContent === "string" && DEGRADED_ERROR_PATTERN.test(errorContent);
|
|
24993
|
+
if (isTransient) {
|
|
24985
24994
|
window2.transientRetryCount++;
|
|
24995
|
+
} else if (isDegraded) {
|
|
24996
|
+
const isContentFilter = typeof errorContent === "string" && CONTENT_FILTER_PATTERN.test(errorContent);
|
|
24997
|
+
if (session && !session.modelFallbackExhausted) {
|
|
24998
|
+
session.model_fallback_index++;
|
|
24999
|
+
const baseAgentName = session.agentName ? session.agentName.replace(/^[^_]+[_]/, "") : "";
|
|
25000
|
+
const swarmAgents = getSwarmAgents();
|
|
25001
|
+
const fallbackModels = swarmAgents?.[baseAgentName]?.fallback_models;
|
|
25002
|
+
session.modelFallbackExhausted = !fallbackModels || session.model_fallback_index > fallbackModels.length;
|
|
25003
|
+
session.pendingAdvisoryMessages ??= [];
|
|
25004
|
+
if (isContentFilter) {
|
|
25005
|
+
session.pendingAdvisoryMessages.push(`DEGRADED: Content policy violation detected (content filter). Fallback model ${session.model_fallback_index}/${fallbackModels?.length ?? 0} considered. ` + `The input may need content modification to comply with provider policies.`);
|
|
25006
|
+
} else {
|
|
25007
|
+
session.pendingAdvisoryMessages.push(`DEGRADED: Context-limit or token-limit error detected. Fallback model ${session.model_fallback_index}/${fallbackModels?.length ?? 0} considered. ` + `Consider reducing input size or using /swarm handoff to switch models.`);
|
|
25008
|
+
}
|
|
25009
|
+
} else if (session) {
|
|
25010
|
+
session.pendingAdvisoryMessages ??= [];
|
|
25011
|
+
if (isContentFilter) {
|
|
25012
|
+
session.pendingAdvisoryMessages.push(`DEGRADED: Content policy violation detected (content filter). No fallback models available. ` + `The input may need content modification to comply with provider policies.`);
|
|
25013
|
+
} else {
|
|
25014
|
+
session.pendingAdvisoryMessages.push(`DEGRADED: Context-limit or token-limit error detected. No fallback models available. ` + `Consider reducing input size or add "fallback_models" config.`);
|
|
25015
|
+
}
|
|
25016
|
+
}
|
|
25017
|
+
} else {
|
|
25018
|
+
window2.consecutiveErrors++;
|
|
24986
25019
|
}
|
|
24987
|
-
if (session &&
|
|
25020
|
+
if (session && isTransientMatch && !session.modelFallbackExhausted && !isDegraded) {
|
|
24988
25021
|
session.model_fallback_index++;
|
|
24989
25022
|
const baseAgentName = session.agentName ? session.agentName.replace(/^[^_]+[_]/, "") : "";
|
|
24990
25023
|
const swarmAgents = getSwarmAgents();
|
|
@@ -25005,6 +25038,12 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25005
25038
|
telemetry.modelFallback(input.sessionID, session.agentName, primaryModel, fallbackModel ?? "none", "transient_model_error");
|
|
25006
25039
|
swarmState.pendingEvents++;
|
|
25007
25040
|
}
|
|
25041
|
+
if (session && isTransient && isTransientMatch) {
|
|
25042
|
+
session.pendingAdvisoryMessages ??= [];
|
|
25043
|
+
if (!session.pendingAdvisoryMessages.some((m) => m.startsWith("TRANSIENT ERROR:"))) {
|
|
25044
|
+
session.pendingAdvisoryMessages.push(`TRANSIENT ERROR: Provider error detected (attempt ${window2.transientRetryCount}/${cfg.max_transient_retries ?? 5}). Retrying...`);
|
|
25045
|
+
}
|
|
25046
|
+
}
|
|
25008
25047
|
} else {
|
|
25009
25048
|
window2.consecutiveErrors = 0;
|
|
25010
25049
|
window2.transientRetryCount = 0;
|
|
@@ -25582,7 +25621,7 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
|
|
|
25582
25621
|
}
|
|
25583
25622
|
return { allowed: true };
|
|
25584
25623
|
}
|
|
25585
|
-
var import_picomatch, storedInputArgs, TRANSIENT_MODEL_ERROR_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
25624
|
+
var import_picomatch, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
25586
25625
|
var init_guardrails = __esm(() => {
|
|
25587
25626
|
init_quick_lru();
|
|
25588
25627
|
init_agents2();
|
|
@@ -25603,7 +25642,10 @@ var init_guardrails = __esm(() => {
|
|
|
25603
25642
|
init_normalize_tool_name();
|
|
25604
25643
|
import_picomatch = __toESM(require_picomatch2(), 1);
|
|
25605
25644
|
storedInputArgs = new Map;
|
|
25606
|
-
|
|
25645
|
+
TRANSIENT_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504, 529]);
|
|
25646
|
+
TRANSIENT_MODEL_ERROR_PATTERN = /rate.?limit|429|500|502|503|504|529|timeout|overloaded|model.?not.?found|temporarily.?unavailable|server.?error|connection.?(refused|reset|timeout)|bad.?gateway|gateway.?timeout|internal.?server.?error|service.?unavailable/i;
|
|
25647
|
+
DEGRADED_ERROR_PATTERN = /context.?length|token.?(limit|budget)|input.?too.?long|content.?filter|exceeds?.?(maximum.?)?tokens|maximum.?context|context.?window|too.?many.?tokens|prompt.?too.?long|message.?too.?long|request.?too.?large|max.?tokens/i;
|
|
25648
|
+
CONTENT_FILTER_PATTERN = /content.?filter/i;
|
|
25607
25649
|
toolCallsSinceLastWrite = new Map;
|
|
25608
25650
|
noOpWarningIssued = new Set;
|
|
25609
25651
|
consecutiveNoToolTurns = new Map;
|
|
@@ -57491,6 +57533,14 @@ var init_write_retro2 = __esm(() => {
|
|
|
57491
57533
|
init_write_retro();
|
|
57492
57534
|
});
|
|
57493
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
|
+
|
|
57494
57544
|
// src/commands/index.ts
|
|
57495
57545
|
var exports_commands = {};
|
|
57496
57546
|
__export(exports_commands, {
|
|
@@ -57538,7 +57588,9 @@ __export(exports_commands, {
|
|
|
57538
57588
|
createSwarmCommandHandler: () => createSwarmCommandHandler,
|
|
57539
57589
|
buildHelpText: () => buildHelpText,
|
|
57540
57590
|
VALID_COMMANDS: () => VALID_COMMANDS,
|
|
57541
|
-
COMMAND_REGISTRY: () => COMMAND_REGISTRY
|
|
57591
|
+
COMMAND_REGISTRY: () => COMMAND_REGISTRY,
|
|
57592
|
+
COMMAND_NAME_SET: () => COMMAND_NAME_SET,
|
|
57593
|
+
COMMAND_NAMES: () => COMMAND_NAMES
|
|
57542
57594
|
});
|
|
57543
57595
|
import fs30 from "node:fs";
|
|
57544
57596
|
import path46 from "node:path";
|
|
@@ -57718,6 +57770,7 @@ var init_commands = __esm(() => {
|
|
|
57718
57770
|
init_benchmark();
|
|
57719
57771
|
init_checkpoint2();
|
|
57720
57772
|
init_close();
|
|
57773
|
+
init_command_names();
|
|
57721
57774
|
init_config2();
|
|
57722
57775
|
init_council();
|
|
57723
57776
|
init_curate();
|
|
@@ -57975,11 +58028,19 @@ var init_registry = __esm(() => {
|
|
|
57975
58028
|
category: "core",
|
|
57976
58029
|
clashesWithNativeCcCommand: "/status"
|
|
57977
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
|
+
},
|
|
57978
58037
|
plan: {
|
|
57979
58038
|
handler: (ctx) => handlePlanCommand(ctx.directory, ctx.args),
|
|
57980
|
-
description: "Show plan (
|
|
58039
|
+
description: "Show current plan (deprecated alias for /swarm show-plan)",
|
|
57981
58040
|
category: "core",
|
|
57982
|
-
clashesWithNativeCcCommand: "/plan"
|
|
58041
|
+
clashesWithNativeCcCommand: "/plan",
|
|
58042
|
+
aliasOf: "show-plan",
|
|
58043
|
+
deprecated: true
|
|
57983
58044
|
},
|
|
57984
58045
|
agents: {
|
|
57985
58046
|
handler: (ctx) => Promise.resolve(handleAgentsCommand(ctx.agents, undefined)),
|
|
@@ -58149,13 +58210,22 @@ var init_registry = __esm(() => {
|
|
|
58149
58210
|
args: "--threshold <number>, --min-commits <number>",
|
|
58150
58211
|
category: "diagnostics"
|
|
58151
58212
|
},
|
|
58152
|
-
|
|
58213
|
+
finalize: {
|
|
58153
58214
|
handler: (ctx) => handleCloseCommand(ctx.directory, ctx.args),
|
|
58154
|
-
description: "Use /swarm
|
|
58215
|
+
description: "Use /swarm finalize to finalize the swarm project and archive evidence",
|
|
58155
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.",
|
|
58156
58217
|
args: "--prune-branches",
|
|
58157
58218
|
category: "core"
|
|
58158
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
|
+
},
|
|
58159
58229
|
simulate: {
|
|
58160
58230
|
handler: (ctx) => handleSimulateCommand(ctx.directory, ctx.args),
|
|
58161
58231
|
description: "Dry-run hidden coupling analysis with configurable thresholds",
|
|
@@ -58189,9 +58259,9 @@ var init_registry = __esm(() => {
|
|
|
58189
58259
|
},
|
|
58190
58260
|
council: {
|
|
58191
58261
|
handler: (ctx) => handleCouncilCommand(ctx.directory, ctx.args),
|
|
58192
|
-
description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--spec-review]",
|
|
58193
|
-
args: "<question> [--spec-review]",
|
|
58194
|
-
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.",
|
|
58195
58265
|
category: "agent"
|
|
58196
58266
|
},
|
|
58197
58267
|
"pr-review": {
|
|
@@ -58511,7 +58581,7 @@ function buildSlashCommandsList() {
|
|
|
58511
58581
|
"history",
|
|
58512
58582
|
"agents",
|
|
58513
58583
|
"config",
|
|
58514
|
-
"plan",
|
|
58584
|
+
"show-plan",
|
|
58515
58585
|
"benchmark",
|
|
58516
58586
|
"export",
|
|
58517
58587
|
"retrieve"
|
|
@@ -58527,7 +58597,7 @@ function buildSlashCommandsList() {
|
|
|
58527
58597
|
];
|
|
58528
58598
|
const COMMANDS_BY_CATEGORY = {
|
|
58529
58599
|
"Session Lifecycle": [
|
|
58530
|
-
"
|
|
58600
|
+
"finalize",
|
|
58531
58601
|
"reset",
|
|
58532
58602
|
"reset-session",
|
|
58533
58603
|
"handoff",
|
|
@@ -58537,7 +58607,7 @@ function buildSlashCommandsList() {
|
|
|
58537
58607
|
"specify",
|
|
58538
58608
|
"clarify",
|
|
58539
58609
|
"analyze",
|
|
58540
|
-
"plan",
|
|
58610
|
+
"show-plan",
|
|
58541
58611
|
"sync-plan",
|
|
58542
58612
|
"acknowledge-spec-drift",
|
|
58543
58613
|
"council"
|
|
@@ -58692,7 +58762,7 @@ All swarm commands are invoked as /swarm <subcommand>.
|
|
|
58692
58762
|
NEVER invoke a bare slash command that shares a name with a swarm subcommand.
|
|
58693
58763
|
|
|
58694
58764
|
CRITICAL CONFLICTS — bare CC command = catastrophic:
|
|
58695
|
-
/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.
|
|
58696
58766
|
/reset (CC) → WIPES conversation context. /swarm reset → Clears .swarm (--confirm). USE THIS.
|
|
58697
58767
|
/checkpoint (CC) → Reverts your work. /swarm checkpoint → Project snapshots. USE THIS.
|
|
58698
58768
|
|
|
@@ -59650,7 +59720,7 @@ GREENFIELD EXEMPTION: If the work is purely greenfield (new project, no existing
|
|
|
59650
59720
|
|
|
59651
59721
|
### MODE: COUNCIL
|
|
59652
59722
|
|
|
59653
|
-
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\`).
|
|
59654
59724
|
|
|
59655
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.
|
|
59656
59726
|
|
|
@@ -68659,12 +68729,12 @@ ${content.substring(endIndex + 1)}`;
|
|
|
68659
68729
|
// src/commands/conflict-registry.ts
|
|
68660
68730
|
var CLAUDE_CODE_CONFLICTS = [
|
|
68661
68731
|
{
|
|
68662
|
-
swarmCommand: "plan",
|
|
68732
|
+
swarmCommand: "show-plan",
|
|
68663
68733
|
ccCommand: "/plan",
|
|
68664
68734
|
severity: "CRITICAL",
|
|
68665
68735
|
ccBehavior: "Enters Claude Code plan mode — Claude proposes all actions before executing them",
|
|
68666
68736
|
swarmBehavior: "Displays the current .swarm/plan.md task list",
|
|
68667
|
-
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."
|
|
68668
68738
|
},
|
|
68669
68739
|
{
|
|
68670
68740
|
swarmCommand: "reset",
|
|
@@ -81827,10 +81897,6 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
81827
81897
|
}
|
|
81828
81898
|
}
|
|
81829
81899
|
|
|
81830
|
-
// src/council/council-service.ts
|
|
81831
|
-
import fs65 from "node:fs";
|
|
81832
|
-
import path87 from "node:path";
|
|
81833
|
-
|
|
81834
81900
|
// src/council/types.ts
|
|
81835
81901
|
var COUNCIL_DEFAULTS = {
|
|
81836
81902
|
enabled: false,
|
|
@@ -81955,7 +82021,7 @@ function buildUnifiedFeedback(taskId, verdict, vetoedBy, requiredFixes, advisory
|
|
|
81955
82021
|
return lines.join(`
|
|
81956
82022
|
`);
|
|
81957
82023
|
}
|
|
81958
|
-
function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, roundNumber, config3 = {},
|
|
82024
|
+
function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, roundNumber, config3 = {}, _workingDir) {
|
|
81959
82025
|
const cfg = { ...COUNCIL_DEFAULTS, ...config3 };
|
|
81960
82026
|
const timestamp = new Date().toISOString();
|
|
81961
82027
|
const scope = "phase";
|
|
@@ -81988,47 +82054,6 @@ function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, rou
|
|
|
81988
82054
|
const allCriteriaMet = allUnmetIds.size === 0 && verdicts.length > 0;
|
|
81989
82055
|
const unifiedFeedbackMd = buildPhaseCouncilFeedback(phaseNumber, phaseSummary, overallVerdict, rejectingMembers, requiredFixes, advisoryFindings, unresolvedConflicts, roundNumber, cfg.maxRounds);
|
|
81990
82056
|
const evidencePath = `.swarm/evidence/${phaseNumber}/phase-council.json`;
|
|
81991
|
-
const baseDir = workingDir ?? process.cwd();
|
|
81992
|
-
const evidenceDir = path87.join(baseDir, ".swarm", "evidence", String(phaseNumber));
|
|
81993
|
-
fs65.mkdirSync(evidenceDir, { recursive: true });
|
|
81994
|
-
const evidenceFile = path87.join(evidenceDir, "phase-council.json");
|
|
81995
|
-
const evidenceBundle = {
|
|
81996
|
-
entries: [
|
|
81997
|
-
{
|
|
81998
|
-
type: "phase-council",
|
|
81999
|
-
phase_number: phaseNumber,
|
|
82000
|
-
scope: "phase",
|
|
82001
|
-
timestamp,
|
|
82002
|
-
verdict: overallVerdict,
|
|
82003
|
-
quorumSize,
|
|
82004
|
-
phaseSummary,
|
|
82005
|
-
requiredFixes: requiredFixes.map((f) => ({
|
|
82006
|
-
severity: f.severity,
|
|
82007
|
-
category: f.category,
|
|
82008
|
-
location: f.location,
|
|
82009
|
-
detail: f.detail,
|
|
82010
|
-
evidence: f.evidence
|
|
82011
|
-
})),
|
|
82012
|
-
advisoryNotes,
|
|
82013
|
-
advisoryFindings: advisoryFindings.map((f) => ({
|
|
82014
|
-
severity: f.severity,
|
|
82015
|
-
category: f.category,
|
|
82016
|
-
location: f.location,
|
|
82017
|
-
detail: f.detail,
|
|
82018
|
-
evidence: f.evidence
|
|
82019
|
-
})),
|
|
82020
|
-
roundNumber,
|
|
82021
|
-
allCriteriaMet
|
|
82022
|
-
}
|
|
82023
|
-
]
|
|
82024
|
-
};
|
|
82025
|
-
try {
|
|
82026
|
-
const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
|
|
82027
|
-
fs65.writeFileSync(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
82028
|
-
fs65.renameSync(tempFile, evidenceFile);
|
|
82029
|
-
} catch (writeErr) {
|
|
82030
|
-
console.warn(`[phase-council] Failed to write phase-council evidence to ${evidenceFile}: ${writeErr instanceof Error ? writeErr.message : String(writeErr)}`);
|
|
82031
|
-
}
|
|
82032
82057
|
return {
|
|
82033
82058
|
phaseNumber,
|
|
82034
82059
|
scope,
|
|
@@ -82260,8 +82285,8 @@ var submit_council_verdicts = createSwarmTool({
|
|
|
82260
82285
|
// src/tools/convene-general-council.ts
|
|
82261
82286
|
init_zod();
|
|
82262
82287
|
init_loader();
|
|
82263
|
-
import * as
|
|
82264
|
-
import * as
|
|
82288
|
+
import * as fs65 from "node:fs";
|
|
82289
|
+
import * as path87 from "node:path";
|
|
82265
82290
|
|
|
82266
82291
|
// src/council/general-council-advisory.ts
|
|
82267
82292
|
var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
|
|
@@ -82689,13 +82714,13 @@ var convene_general_council = createSwarmTool({
|
|
|
82689
82714
|
const round1 = input.round1Responses;
|
|
82690
82715
|
const round2 = input.round2Responses ?? [];
|
|
82691
82716
|
const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
|
|
82692
|
-
const evidenceDir =
|
|
82717
|
+
const evidenceDir = path87.join(workingDir, ".swarm", "council", "general");
|
|
82693
82718
|
const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
|
|
82694
82719
|
const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
|
|
82695
|
-
const evidencePath =
|
|
82720
|
+
const evidencePath = path87.join(evidenceDir, evidenceFile);
|
|
82696
82721
|
try {
|
|
82697
|
-
await
|
|
82698
|
-
await
|
|
82722
|
+
await fs65.promises.mkdir(evidenceDir, { recursive: true });
|
|
82723
|
+
await fs65.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
|
|
82699
82724
|
} catch (err2) {
|
|
82700
82725
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
82701
82726
|
console.warn(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`);
|
|
@@ -82936,8 +82961,8 @@ init_scope_persistence();
|
|
|
82936
82961
|
init_state();
|
|
82937
82962
|
init_task_id();
|
|
82938
82963
|
init_create_tool();
|
|
82939
|
-
import * as
|
|
82940
|
-
import * as
|
|
82964
|
+
import * as fs66 from "node:fs";
|
|
82965
|
+
import * as path88 from "node:path";
|
|
82941
82966
|
function validateTaskIdFormat2(taskId) {
|
|
82942
82967
|
return validateTaskIdFormat(taskId);
|
|
82943
82968
|
}
|
|
@@ -83011,8 +83036,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83011
83036
|
};
|
|
83012
83037
|
}
|
|
83013
83038
|
}
|
|
83014
|
-
normalizedDir =
|
|
83015
|
-
const pathParts = normalizedDir.split(
|
|
83039
|
+
normalizedDir = path88.normalize(args2.working_directory);
|
|
83040
|
+
const pathParts = normalizedDir.split(path88.sep);
|
|
83016
83041
|
if (pathParts.includes("..")) {
|
|
83017
83042
|
return {
|
|
83018
83043
|
success: false,
|
|
@@ -83022,11 +83047,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83022
83047
|
]
|
|
83023
83048
|
};
|
|
83024
83049
|
}
|
|
83025
|
-
const resolvedDir =
|
|
83050
|
+
const resolvedDir = path88.resolve(normalizedDir);
|
|
83026
83051
|
try {
|
|
83027
|
-
const realPath =
|
|
83028
|
-
const planPath2 =
|
|
83029
|
-
if (!
|
|
83052
|
+
const realPath = fs66.realpathSync(resolvedDir);
|
|
83053
|
+
const planPath2 = path88.join(realPath, ".swarm", "plan.json");
|
|
83054
|
+
if (!fs66.existsSync(planPath2)) {
|
|
83030
83055
|
return {
|
|
83031
83056
|
success: false,
|
|
83032
83057
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -83049,8 +83074,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83049
83074
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
83050
83075
|
}
|
|
83051
83076
|
const directory = normalizedDir || fallbackDir;
|
|
83052
|
-
const planPath =
|
|
83053
|
-
if (!
|
|
83077
|
+
const planPath = path88.resolve(directory, ".swarm", "plan.json");
|
|
83078
|
+
if (!fs66.existsSync(planPath)) {
|
|
83054
83079
|
return {
|
|
83055
83080
|
success: false,
|
|
83056
83081
|
message: "No plan found",
|
|
@@ -83059,7 +83084,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83059
83084
|
}
|
|
83060
83085
|
let planContent;
|
|
83061
83086
|
try {
|
|
83062
|
-
planContent = JSON.parse(
|
|
83087
|
+
planContent = JSON.parse(fs66.readFileSync(planPath, "utf-8"));
|
|
83063
83088
|
} catch {
|
|
83064
83089
|
return {
|
|
83065
83090
|
success: false,
|
|
@@ -83089,8 +83114,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
83089
83114
|
const normalizeErrors = [];
|
|
83090
83115
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
83091
83116
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
83092
|
-
if (
|
|
83093
|
-
const relativePath =
|
|
83117
|
+
if (path88.isAbsolute(file3)) {
|
|
83118
|
+
const relativePath = path88.relative(dir, file3).replace(/\\/g, "/");
|
|
83094
83119
|
if (relativePath.startsWith("..")) {
|
|
83095
83120
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
83096
83121
|
return file3;
|
|
@@ -83150,8 +83175,8 @@ var declare_scope = createSwarmTool({
|
|
|
83150
83175
|
// src/tools/diff.ts
|
|
83151
83176
|
init_zod();
|
|
83152
83177
|
import * as child_process7 from "node:child_process";
|
|
83153
|
-
import * as
|
|
83154
|
-
import * as
|
|
83178
|
+
import * as fs67 from "node:fs";
|
|
83179
|
+
import * as path89 from "node:path";
|
|
83155
83180
|
init_create_tool();
|
|
83156
83181
|
var MAX_DIFF_LINES = 500;
|
|
83157
83182
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -83180,20 +83205,20 @@ function validateBase(base) {
|
|
|
83180
83205
|
function validatePaths(paths) {
|
|
83181
83206
|
if (!paths)
|
|
83182
83207
|
return null;
|
|
83183
|
-
for (const
|
|
83184
|
-
if (!
|
|
83208
|
+
for (const path90 of paths) {
|
|
83209
|
+
if (!path90 || path90.length === 0) {
|
|
83185
83210
|
return "empty path not allowed";
|
|
83186
83211
|
}
|
|
83187
|
-
if (
|
|
83212
|
+
if (path90.length > MAX_PATH_LENGTH) {
|
|
83188
83213
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
83189
83214
|
}
|
|
83190
|
-
if (SHELL_METACHARACTERS2.test(
|
|
83215
|
+
if (SHELL_METACHARACTERS2.test(path90)) {
|
|
83191
83216
|
return "path contains shell metacharacters";
|
|
83192
83217
|
}
|
|
83193
|
-
if (
|
|
83218
|
+
if (path90.startsWith("-")) {
|
|
83194
83219
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
83195
83220
|
}
|
|
83196
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
83221
|
+
if (CONTROL_CHAR_PATTERN2.test(path90)) {
|
|
83197
83222
|
return "path contains control characters";
|
|
83198
83223
|
}
|
|
83199
83224
|
}
|
|
@@ -83301,8 +83326,8 @@ var diff = createSwarmTool({
|
|
|
83301
83326
|
if (parts2.length >= 3) {
|
|
83302
83327
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
83303
83328
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
83304
|
-
const
|
|
83305
|
-
files.push({ path:
|
|
83329
|
+
const path90 = parts2[2];
|
|
83330
|
+
files.push({ path: path90, additions, deletions });
|
|
83306
83331
|
}
|
|
83307
83332
|
}
|
|
83308
83333
|
const contractChanges = [];
|
|
@@ -83342,7 +83367,7 @@ var diff = createSwarmTool({
|
|
|
83342
83367
|
} else if (base === "unstaged") {
|
|
83343
83368
|
const oldRef = `:${file3.path}`;
|
|
83344
83369
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
83345
|
-
newContent =
|
|
83370
|
+
newContent = fs67.readFileSync(path89.join(directory, file3.path), "utf-8");
|
|
83346
83371
|
} else {
|
|
83347
83372
|
const oldRef = `${base}:${file3.path}`;
|
|
83348
83373
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
@@ -83416,8 +83441,8 @@ var diff = createSwarmTool({
|
|
|
83416
83441
|
// src/tools/diff-summary.ts
|
|
83417
83442
|
init_zod();
|
|
83418
83443
|
import * as child_process8 from "node:child_process";
|
|
83419
|
-
import * as
|
|
83420
|
-
import * as
|
|
83444
|
+
import * as fs68 from "node:fs";
|
|
83445
|
+
import * as path90 from "node:path";
|
|
83421
83446
|
init_create_tool();
|
|
83422
83447
|
var diff_summary = createSwarmTool({
|
|
83423
83448
|
description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
|
|
@@ -83465,7 +83490,7 @@ var diff_summary = createSwarmTool({
|
|
|
83465
83490
|
}
|
|
83466
83491
|
try {
|
|
83467
83492
|
let oldContent;
|
|
83468
|
-
const newContent =
|
|
83493
|
+
const newContent = fs68.readFileSync(path90.join(workingDir, filePath), "utf-8");
|
|
83469
83494
|
if (fileExistsInHead) {
|
|
83470
83495
|
oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
|
|
83471
83496
|
encoding: "utf-8",
|
|
@@ -83693,8 +83718,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
83693
83718
|
init_zod();
|
|
83694
83719
|
init_create_tool();
|
|
83695
83720
|
init_path_security();
|
|
83696
|
-
import * as
|
|
83697
|
-
import * as
|
|
83721
|
+
import * as fs69 from "node:fs";
|
|
83722
|
+
import * as path91 from "node:path";
|
|
83698
83723
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
83699
83724
|
var MAX_EVIDENCE_FILES = 1000;
|
|
83700
83725
|
var EVIDENCE_DIR3 = ".swarm/evidence";
|
|
@@ -83721,9 +83746,9 @@ function validateRequiredTypes(input) {
|
|
|
83721
83746
|
return null;
|
|
83722
83747
|
}
|
|
83723
83748
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
83724
|
-
const normalizedCwd =
|
|
83725
|
-
const swarmPath =
|
|
83726
|
-
const normalizedPath =
|
|
83749
|
+
const normalizedCwd = path91.resolve(cwd);
|
|
83750
|
+
const swarmPath = path91.join(normalizedCwd, ".swarm");
|
|
83751
|
+
const normalizedPath = path91.resolve(filePath);
|
|
83727
83752
|
return normalizedPath.startsWith(swarmPath);
|
|
83728
83753
|
}
|
|
83729
83754
|
function parseCompletedTasks(planContent) {
|
|
@@ -83739,12 +83764,12 @@ function parseCompletedTasks(planContent) {
|
|
|
83739
83764
|
}
|
|
83740
83765
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
83741
83766
|
const evidence = [];
|
|
83742
|
-
if (!
|
|
83767
|
+
if (!fs69.existsSync(evidenceDir) || !fs69.statSync(evidenceDir).isDirectory()) {
|
|
83743
83768
|
return evidence;
|
|
83744
83769
|
}
|
|
83745
83770
|
let files;
|
|
83746
83771
|
try {
|
|
83747
|
-
files =
|
|
83772
|
+
files = fs69.readdirSync(evidenceDir);
|
|
83748
83773
|
} catch {
|
|
83749
83774
|
return evidence;
|
|
83750
83775
|
}
|
|
@@ -83753,14 +83778,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
83753
83778
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
83754
83779
|
continue;
|
|
83755
83780
|
}
|
|
83756
|
-
const filePath =
|
|
83781
|
+
const filePath = path91.join(evidenceDir, filename);
|
|
83757
83782
|
try {
|
|
83758
|
-
const resolvedPath =
|
|
83759
|
-
const evidenceDirResolved =
|
|
83783
|
+
const resolvedPath = path91.resolve(filePath);
|
|
83784
|
+
const evidenceDirResolved = path91.resolve(evidenceDir);
|
|
83760
83785
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
83761
83786
|
continue;
|
|
83762
83787
|
}
|
|
83763
|
-
const stat7 =
|
|
83788
|
+
const stat7 = fs69.lstatSync(filePath);
|
|
83764
83789
|
if (!stat7.isFile()) {
|
|
83765
83790
|
continue;
|
|
83766
83791
|
}
|
|
@@ -83769,7 +83794,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
83769
83794
|
}
|
|
83770
83795
|
let fileStat;
|
|
83771
83796
|
try {
|
|
83772
|
-
fileStat =
|
|
83797
|
+
fileStat = fs69.statSync(filePath);
|
|
83773
83798
|
if (fileStat.size > MAX_FILE_SIZE_BYTES6) {
|
|
83774
83799
|
continue;
|
|
83775
83800
|
}
|
|
@@ -83778,7 +83803,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
83778
83803
|
}
|
|
83779
83804
|
let content;
|
|
83780
83805
|
try {
|
|
83781
|
-
content =
|
|
83806
|
+
content = fs69.readFileSync(filePath, "utf-8");
|
|
83782
83807
|
} catch {
|
|
83783
83808
|
continue;
|
|
83784
83809
|
}
|
|
@@ -83874,7 +83899,7 @@ var evidence_check = createSwarmTool({
|
|
|
83874
83899
|
return JSON.stringify(errorResult, null, 2);
|
|
83875
83900
|
}
|
|
83876
83901
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
83877
|
-
const planPath =
|
|
83902
|
+
const planPath = path91.join(cwd, PLAN_FILE);
|
|
83878
83903
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
83879
83904
|
const errorResult = {
|
|
83880
83905
|
error: "plan file path validation failed",
|
|
@@ -83888,7 +83913,7 @@ var evidence_check = createSwarmTool({
|
|
|
83888
83913
|
}
|
|
83889
83914
|
let planContent;
|
|
83890
83915
|
try {
|
|
83891
|
-
planContent =
|
|
83916
|
+
planContent = fs69.readFileSync(planPath, "utf-8");
|
|
83892
83917
|
} catch {
|
|
83893
83918
|
const result2 = {
|
|
83894
83919
|
message: "No completed tasks found in plan.",
|
|
@@ -83906,7 +83931,7 @@ var evidence_check = createSwarmTool({
|
|
|
83906
83931
|
};
|
|
83907
83932
|
return JSON.stringify(result2, null, 2);
|
|
83908
83933
|
}
|
|
83909
|
-
const evidenceDir =
|
|
83934
|
+
const evidenceDir = path91.join(cwd, EVIDENCE_DIR3);
|
|
83910
83935
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
83911
83936
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
83912
83937
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -83923,8 +83948,8 @@ var evidence_check = createSwarmTool({
|
|
|
83923
83948
|
// src/tools/file-extractor.ts
|
|
83924
83949
|
init_zod();
|
|
83925
83950
|
init_create_tool();
|
|
83926
|
-
import * as
|
|
83927
|
-
import * as
|
|
83951
|
+
import * as fs70 from "node:fs";
|
|
83952
|
+
import * as path92 from "node:path";
|
|
83928
83953
|
var EXT_MAP = {
|
|
83929
83954
|
python: ".py",
|
|
83930
83955
|
py: ".py",
|
|
@@ -83986,8 +84011,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
83986
84011
|
execute: async (args2, directory) => {
|
|
83987
84012
|
const { content, output_dir, prefix } = args2;
|
|
83988
84013
|
const targetDir = output_dir || directory;
|
|
83989
|
-
if (!
|
|
83990
|
-
|
|
84014
|
+
if (!fs70.existsSync(targetDir)) {
|
|
84015
|
+
fs70.mkdirSync(targetDir, { recursive: true });
|
|
83991
84016
|
}
|
|
83992
84017
|
if (!content) {
|
|
83993
84018
|
return "Error: content is required";
|
|
@@ -84005,16 +84030,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
84005
84030
|
if (prefix) {
|
|
84006
84031
|
filename = `${prefix}_${filename}`;
|
|
84007
84032
|
}
|
|
84008
|
-
let filepath =
|
|
84009
|
-
const base =
|
|
84010
|
-
const ext =
|
|
84033
|
+
let filepath = path92.join(targetDir, filename);
|
|
84034
|
+
const base = path92.basename(filepath, path92.extname(filepath));
|
|
84035
|
+
const ext = path92.extname(filepath);
|
|
84011
84036
|
let counter = 1;
|
|
84012
|
-
while (
|
|
84013
|
-
filepath =
|
|
84037
|
+
while (fs70.existsSync(filepath)) {
|
|
84038
|
+
filepath = path92.join(targetDir, `${base}_${counter}${ext}`);
|
|
84014
84039
|
counter++;
|
|
84015
84040
|
}
|
|
84016
84041
|
try {
|
|
84017
|
-
|
|
84042
|
+
fs70.writeFileSync(filepath, code.trim(), "utf-8");
|
|
84018
84043
|
savedFiles.push(filepath);
|
|
84019
84044
|
} catch (error93) {
|
|
84020
84045
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -84267,8 +84292,8 @@ var gitingest = createSwarmTool({
|
|
|
84267
84292
|
init_zod();
|
|
84268
84293
|
init_create_tool();
|
|
84269
84294
|
init_path_security();
|
|
84270
|
-
import * as
|
|
84271
|
-
import * as
|
|
84295
|
+
import * as fs71 from "node:fs";
|
|
84296
|
+
import * as path93 from "node:path";
|
|
84272
84297
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
84273
84298
|
var MAX_SYMBOL_LENGTH = 256;
|
|
84274
84299
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -84316,7 +84341,7 @@ function validateSymbolInput(symbol3) {
|
|
|
84316
84341
|
return null;
|
|
84317
84342
|
}
|
|
84318
84343
|
function isBinaryFile2(filePath, buffer) {
|
|
84319
|
-
const ext =
|
|
84344
|
+
const ext = path93.extname(filePath).toLowerCase();
|
|
84320
84345
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
84321
84346
|
return false;
|
|
84322
84347
|
}
|
|
@@ -84340,15 +84365,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
84340
84365
|
const imports = [];
|
|
84341
84366
|
let _resolvedTarget;
|
|
84342
84367
|
try {
|
|
84343
|
-
_resolvedTarget =
|
|
84368
|
+
_resolvedTarget = path93.resolve(targetFile);
|
|
84344
84369
|
} catch {
|
|
84345
84370
|
_resolvedTarget = targetFile;
|
|
84346
84371
|
}
|
|
84347
|
-
const targetBasename =
|
|
84372
|
+
const targetBasename = path93.basename(targetFile, path93.extname(targetFile));
|
|
84348
84373
|
const targetWithExt = targetFile;
|
|
84349
84374
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
84350
|
-
const normalizedTargetWithExt =
|
|
84351
|
-
const normalizedTargetWithoutExt =
|
|
84375
|
+
const normalizedTargetWithExt = path93.normalize(targetWithExt).replace(/\\/g, "/");
|
|
84376
|
+
const normalizedTargetWithoutExt = path93.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
84352
84377
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
84353
84378
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
84354
84379
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -84371,9 +84396,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
84371
84396
|
}
|
|
84372
84397
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
84373
84398
|
let isMatch = false;
|
|
84374
|
-
const _targetDir =
|
|
84375
|
-
const targetExt =
|
|
84376
|
-
const targetBasenameNoExt =
|
|
84399
|
+
const _targetDir = path93.dirname(targetFile);
|
|
84400
|
+
const targetExt = path93.extname(targetFile);
|
|
84401
|
+
const targetBasenameNoExt = path93.basename(targetFile, targetExt);
|
|
84377
84402
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
84378
84403
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
84379
84404
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -84430,7 +84455,7 @@ var SKIP_DIRECTORIES4 = new Set([
|
|
|
84430
84455
|
function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
84431
84456
|
let entries;
|
|
84432
84457
|
try {
|
|
84433
|
-
entries =
|
|
84458
|
+
entries = fs71.readdirSync(dir);
|
|
84434
84459
|
} catch (e) {
|
|
84435
84460
|
stats.fileErrors.push({
|
|
84436
84461
|
path: dir,
|
|
@@ -84441,13 +84466,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
84441
84466
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
84442
84467
|
for (const entry of entries) {
|
|
84443
84468
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
84444
|
-
stats.skippedDirs.push(
|
|
84469
|
+
stats.skippedDirs.push(path93.join(dir, entry));
|
|
84445
84470
|
continue;
|
|
84446
84471
|
}
|
|
84447
|
-
const fullPath =
|
|
84472
|
+
const fullPath = path93.join(dir, entry);
|
|
84448
84473
|
let stat7;
|
|
84449
84474
|
try {
|
|
84450
|
-
stat7 =
|
|
84475
|
+
stat7 = fs71.statSync(fullPath);
|
|
84451
84476
|
} catch (e) {
|
|
84452
84477
|
stats.fileErrors.push({
|
|
84453
84478
|
path: fullPath,
|
|
@@ -84458,7 +84483,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
84458
84483
|
if (stat7.isDirectory()) {
|
|
84459
84484
|
findSourceFiles2(fullPath, files, stats);
|
|
84460
84485
|
} else if (stat7.isFile()) {
|
|
84461
|
-
const ext =
|
|
84486
|
+
const ext = path93.extname(fullPath).toLowerCase();
|
|
84462
84487
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
84463
84488
|
files.push(fullPath);
|
|
84464
84489
|
}
|
|
@@ -84515,8 +84540,8 @@ var imports = createSwarmTool({
|
|
|
84515
84540
|
return JSON.stringify(errorResult, null, 2);
|
|
84516
84541
|
}
|
|
84517
84542
|
try {
|
|
84518
|
-
const targetFile =
|
|
84519
|
-
if (!
|
|
84543
|
+
const targetFile = path93.resolve(file3);
|
|
84544
|
+
if (!fs71.existsSync(targetFile)) {
|
|
84520
84545
|
const errorResult = {
|
|
84521
84546
|
error: `target file not found: ${file3}`,
|
|
84522
84547
|
target: file3,
|
|
@@ -84526,7 +84551,7 @@ var imports = createSwarmTool({
|
|
|
84526
84551
|
};
|
|
84527
84552
|
return JSON.stringify(errorResult, null, 2);
|
|
84528
84553
|
}
|
|
84529
|
-
const targetStat =
|
|
84554
|
+
const targetStat = fs71.statSync(targetFile);
|
|
84530
84555
|
if (!targetStat.isFile()) {
|
|
84531
84556
|
const errorResult = {
|
|
84532
84557
|
error: "target must be a file, not a directory",
|
|
@@ -84537,7 +84562,7 @@ var imports = createSwarmTool({
|
|
|
84537
84562
|
};
|
|
84538
84563
|
return JSON.stringify(errorResult, null, 2);
|
|
84539
84564
|
}
|
|
84540
|
-
const baseDir =
|
|
84565
|
+
const baseDir = path93.dirname(targetFile);
|
|
84541
84566
|
const scanStats = {
|
|
84542
84567
|
skippedDirs: [],
|
|
84543
84568
|
skippedFiles: 0,
|
|
@@ -84552,12 +84577,12 @@ var imports = createSwarmTool({
|
|
|
84552
84577
|
if (consumers.length >= MAX_CONSUMERS)
|
|
84553
84578
|
break;
|
|
84554
84579
|
try {
|
|
84555
|
-
const stat7 =
|
|
84580
|
+
const stat7 = fs71.statSync(filePath);
|
|
84556
84581
|
if (stat7.size > MAX_FILE_SIZE_BYTES7) {
|
|
84557
84582
|
skippedFileCount++;
|
|
84558
84583
|
continue;
|
|
84559
84584
|
}
|
|
84560
|
-
const buffer =
|
|
84585
|
+
const buffer = fs71.readFileSync(filePath);
|
|
84561
84586
|
if (isBinaryFile2(filePath, buffer)) {
|
|
84562
84587
|
skippedFileCount++;
|
|
84563
84588
|
continue;
|
|
@@ -85133,30 +85158,30 @@ init_config();
|
|
|
85133
85158
|
init_schema();
|
|
85134
85159
|
init_qa_gate_profile();
|
|
85135
85160
|
init_manager2();
|
|
85136
|
-
import * as
|
|
85137
|
-
import * as
|
|
85161
|
+
import * as fs74 from "node:fs";
|
|
85162
|
+
import * as path96 from "node:path";
|
|
85138
85163
|
|
|
85139
85164
|
// src/full-auto/phase-approval.ts
|
|
85140
85165
|
init_utils2();
|
|
85141
85166
|
init_logger();
|
|
85142
85167
|
init_state2();
|
|
85143
|
-
import * as
|
|
85144
|
-
import * as
|
|
85168
|
+
import * as fs72 from "node:fs";
|
|
85169
|
+
import * as path94 from "node:path";
|
|
85145
85170
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
85146
85171
|
function readEvidenceDir(directory, phase) {
|
|
85147
85172
|
try {
|
|
85148
|
-
const dirPath = validateSwarmPath(directory,
|
|
85149
|
-
if (!
|
|
85173
|
+
const dirPath = validateSwarmPath(directory, path94.posix.join("evidence", String(phase)));
|
|
85174
|
+
if (!fs72.existsSync(dirPath))
|
|
85150
85175
|
return [];
|
|
85151
|
-
const entries =
|
|
85152
|
-
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));
|
|
85153
85178
|
} catch {
|
|
85154
85179
|
return [];
|
|
85155
85180
|
}
|
|
85156
85181
|
}
|
|
85157
85182
|
function parseEvidence(filePath) {
|
|
85158
85183
|
try {
|
|
85159
|
-
const raw =
|
|
85184
|
+
const raw = fs72.readFileSync(filePath, "utf-8");
|
|
85160
85185
|
const parsed = JSON.parse(raw);
|
|
85161
85186
|
return parsed;
|
|
85162
85187
|
} catch (error93) {
|
|
@@ -85245,9 +85270,9 @@ function verifyFullAutoPhaseApproval(directory, sessionID, phase, config3) {
|
|
|
85245
85270
|
function phaseIsExplicitlyNonCode(directory, phase) {
|
|
85246
85271
|
try {
|
|
85247
85272
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
85248
|
-
if (!
|
|
85273
|
+
if (!fs72.existsSync(planPath))
|
|
85249
85274
|
return false;
|
|
85250
|
-
const raw =
|
|
85275
|
+
const raw = fs72.readFileSync(planPath, "utf-8");
|
|
85251
85276
|
const plan = JSON.parse(raw);
|
|
85252
85277
|
const phases = Array.isArray(plan.phases) ? plan.phases : [];
|
|
85253
85278
|
const entry = phases.find((p) => p.id === phase || p.phase === phase);
|
|
@@ -85287,20 +85312,20 @@ init_file_locks();
|
|
|
85287
85312
|
init_plan_schema();
|
|
85288
85313
|
init_ledger();
|
|
85289
85314
|
init_manager();
|
|
85290
|
-
import * as
|
|
85291
|
-
import * as
|
|
85315
|
+
import * as fs73 from "node:fs";
|
|
85316
|
+
import * as path95 from "node:path";
|
|
85292
85317
|
async function writeCheckpoint(directory) {
|
|
85293
85318
|
try {
|
|
85294
85319
|
const plan = await loadPlan(directory);
|
|
85295
85320
|
if (!plan)
|
|
85296
85321
|
return;
|
|
85297
|
-
const swarmDir =
|
|
85298
|
-
|
|
85299
|
-
const jsonPath =
|
|
85300
|
-
const mdPath =
|
|
85301
|
-
|
|
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");
|
|
85302
85327
|
const md = derivePlanMarkdown(plan);
|
|
85303
|
-
|
|
85328
|
+
fs73.writeFileSync(mdPath, md, "utf8");
|
|
85304
85329
|
} catch (error93) {
|
|
85305
85330
|
console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
85306
85331
|
}
|
|
@@ -85532,8 +85557,8 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85532
85557
|
let driftCheckEnabled = true;
|
|
85533
85558
|
let driftHasSpecMd = false;
|
|
85534
85559
|
try {
|
|
85535
|
-
const specMdPath =
|
|
85536
|
-
driftHasSpecMd =
|
|
85560
|
+
const specMdPath = path96.join(dir, ".swarm", "spec.md");
|
|
85561
|
+
driftHasSpecMd = fs74.existsSync(specMdPath);
|
|
85537
85562
|
const gatePlan = await loadPlan(dir);
|
|
85538
85563
|
if (gatePlan) {
|
|
85539
85564
|
const gatePlanId = derivePlanId(gatePlan);
|
|
@@ -85554,9 +85579,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85554
85579
|
} else {
|
|
85555
85580
|
let phaseType;
|
|
85556
85581
|
try {
|
|
85557
|
-
const planPath =
|
|
85558
|
-
if (
|
|
85559
|
-
const planRaw =
|
|
85582
|
+
const planPath = path96.join(dir, ".swarm", "plan.json");
|
|
85583
|
+
if (fs74.existsSync(planPath)) {
|
|
85584
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
85560
85585
|
const plan = JSON.parse(planRaw);
|
|
85561
85586
|
const targetPhase = plan.phases?.find((p) => p.id === phase);
|
|
85562
85587
|
phaseType = targetPhase?.type;
|
|
@@ -85567,11 +85592,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85567
85592
|
warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
|
|
85568
85593
|
} else {
|
|
85569
85594
|
try {
|
|
85570
|
-
const driftEvidencePath =
|
|
85595
|
+
const driftEvidencePath = path96.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
85571
85596
|
let driftVerdictFound = false;
|
|
85572
85597
|
let driftVerdictApproved = false;
|
|
85573
85598
|
try {
|
|
85574
|
-
const driftEvidenceContent =
|
|
85599
|
+
const driftEvidenceContent = fs74.readFileSync(driftEvidencePath, "utf-8");
|
|
85575
85600
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
85576
85601
|
const entries = driftEvidence.entries ?? [];
|
|
85577
85602
|
for (const entry of entries) {
|
|
@@ -85605,9 +85630,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85605
85630
|
let incompleteTaskCount = 0;
|
|
85606
85631
|
let planParseable = false;
|
|
85607
85632
|
try {
|
|
85608
|
-
const planPath =
|
|
85609
|
-
if (
|
|
85610
|
-
const planRaw =
|
|
85633
|
+
const planPath = path96.join(dir, ".swarm", "plan.json");
|
|
85634
|
+
if (fs74.existsSync(planPath)) {
|
|
85635
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
85611
85636
|
const plan = JSON.parse(planRaw);
|
|
85612
85637
|
planParseable = true;
|
|
85613
85638
|
const planPhase = plan.phases?.find((p) => p.id === phase);
|
|
@@ -85672,11 +85697,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85672
85697
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
85673
85698
|
const effective = getEffectiveGates(profile, overrides);
|
|
85674
85699
|
if (effective.hallucination_guard === true) {
|
|
85675
|
-
const hgPath =
|
|
85700
|
+
const hgPath = path96.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
85676
85701
|
let hgVerdictFound = false;
|
|
85677
85702
|
let hgVerdictApproved = false;
|
|
85678
85703
|
try {
|
|
85679
|
-
const hgContent =
|
|
85704
|
+
const hgContent = fs74.readFileSync(hgPath, "utf-8");
|
|
85680
85705
|
const hgBundle = JSON.parse(hgContent);
|
|
85681
85706
|
for (const entry of hgBundle.entries ?? []) {
|
|
85682
85707
|
if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
|
|
@@ -85744,11 +85769,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85744
85769
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
85745
85770
|
const effective = getEffectiveGates(profile, overrides);
|
|
85746
85771
|
if (effective.mutation_test === true) {
|
|
85747
|
-
const mgPath =
|
|
85772
|
+
const mgPath = path96.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
85748
85773
|
let mgVerdictFound = false;
|
|
85749
85774
|
let mgVerdict;
|
|
85750
85775
|
try {
|
|
85751
|
-
const mgContent =
|
|
85776
|
+
const mgContent = fs74.readFileSync(mgPath, "utf-8");
|
|
85752
85777
|
const mgBundle = JSON.parse(mgContent);
|
|
85753
85778
|
for (const entry of mgBundle.entries ?? []) {
|
|
85754
85779
|
if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
|
|
@@ -85818,14 +85843,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
85818
85843
|
const effective = getEffectiveGates(profile, overrides);
|
|
85819
85844
|
if (effective.council_mode === true) {
|
|
85820
85845
|
councilModeEnabled = true;
|
|
85821
|
-
const pcPath =
|
|
85846
|
+
const pcPath = path96.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
85822
85847
|
let pcVerdictFound = false;
|
|
85823
85848
|
let _pcVerdict;
|
|
85824
85849
|
let pcQuorumSize;
|
|
85825
85850
|
let pcTimestamp;
|
|
85826
85851
|
let pcPhaseNumber;
|
|
85827
85852
|
try {
|
|
85828
|
-
const pcContent =
|
|
85853
|
+
const pcContent = fs74.readFileSync(pcPath, "utf-8");
|
|
85829
85854
|
const pcBundle = JSON.parse(pcContent);
|
|
85830
85855
|
for (const entry of pcBundle.entries ?? []) {
|
|
85831
85856
|
if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
|
|
@@ -86026,11 +86051,11 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86026
86051
|
const effective = getEffectiveGates(profile, overrides);
|
|
86027
86052
|
if (effective.final_council === true) {
|
|
86028
86053
|
finalCouncilEnabled = true;
|
|
86029
|
-
const fcPath =
|
|
86054
|
+
const fcPath = path96.join(dir, ".swarm", "evidence", "final-council.json");
|
|
86030
86055
|
let fcVerdictFound = false;
|
|
86031
86056
|
let _fcVerdict;
|
|
86032
86057
|
try {
|
|
86033
|
-
const fcContent =
|
|
86058
|
+
const fcContent = fs74.readFileSync(fcPath, "utf-8");
|
|
86034
86059
|
const fcBundle = JSON.parse(fcContent);
|
|
86035
86060
|
for (const entry of fcBundle.entries ?? []) {
|
|
86036
86061
|
if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
|
|
@@ -86158,7 +86183,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86158
86183
|
}
|
|
86159
86184
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
86160
86185
|
try {
|
|
86161
|
-
const projectName =
|
|
86186
|
+
const projectName = path96.basename(dir);
|
|
86162
86187
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
86163
86188
|
if (curationResult) {
|
|
86164
86189
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -86238,7 +86263,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86238
86263
|
let phaseRequiredAgents;
|
|
86239
86264
|
try {
|
|
86240
86265
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86241
|
-
const planRaw =
|
|
86266
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86242
86267
|
const plan = JSON.parse(planRaw);
|
|
86243
86268
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
86244
86269
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -86253,7 +86278,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86253
86278
|
if (agentsMissing.length > 0) {
|
|
86254
86279
|
try {
|
|
86255
86280
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86256
|
-
const planRaw =
|
|
86281
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86257
86282
|
const plan = JSON.parse(planRaw);
|
|
86258
86283
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
86259
86284
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -86293,7 +86318,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86293
86318
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
86294
86319
|
try {
|
|
86295
86320
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86296
|
-
const planRaw =
|
|
86321
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86297
86322
|
const plan = JSON.parse(planRaw);
|
|
86298
86323
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
86299
86324
|
if (targetPhase) {
|
|
@@ -86347,7 +86372,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86347
86372
|
}
|
|
86348
86373
|
try {
|
|
86349
86374
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
86350
|
-
|
|
86375
|
+
fs74.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
86351
86376
|
`, "utf-8");
|
|
86352
86377
|
} catch (writeError) {
|
|
86353
86378
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -86422,12 +86447,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86422
86447
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
86423
86448
|
try {
|
|
86424
86449
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86425
|
-
const planRaw =
|
|
86450
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86426
86451
|
const plan2 = JSON.parse(planRaw);
|
|
86427
86452
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
86428
86453
|
if (phaseObj) {
|
|
86429
86454
|
phaseObj.status = "complete";
|
|
86430
|
-
|
|
86455
|
+
fs74.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
86431
86456
|
}
|
|
86432
86457
|
} catch {}
|
|
86433
86458
|
} else if (plan) {
|
|
@@ -86464,12 +86489,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
86464
86489
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
86465
86490
|
try {
|
|
86466
86491
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
86467
|
-
const planRaw =
|
|
86492
|
+
const planRaw = fs74.readFileSync(planPath, "utf-8");
|
|
86468
86493
|
const plan = JSON.parse(planRaw);
|
|
86469
86494
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
86470
86495
|
if (phaseObj) {
|
|
86471
86496
|
phaseObj.status = "complete";
|
|
86472
|
-
|
|
86497
|
+
fs74.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
86473
86498
|
}
|
|
86474
86499
|
} catch {}
|
|
86475
86500
|
}
|
|
@@ -86527,8 +86552,8 @@ init_discovery();
|
|
|
86527
86552
|
init_utils();
|
|
86528
86553
|
init_bun_compat();
|
|
86529
86554
|
init_create_tool();
|
|
86530
|
-
import * as
|
|
86531
|
-
import * as
|
|
86555
|
+
import * as fs75 from "node:fs";
|
|
86556
|
+
import * as path97 from "node:path";
|
|
86532
86557
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
86533
86558
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
86534
86559
|
function isValidEcosystem(value) {
|
|
@@ -86556,31 +86581,31 @@ function validateArgs3(args2) {
|
|
|
86556
86581
|
function detectEcosystems(directory) {
|
|
86557
86582
|
const ecosystems = [];
|
|
86558
86583
|
const cwd = directory;
|
|
86559
|
-
if (
|
|
86584
|
+
if (fs75.existsSync(path97.join(cwd, "package.json"))) {
|
|
86560
86585
|
ecosystems.push("npm");
|
|
86561
86586
|
}
|
|
86562
|
-
if (
|
|
86587
|
+
if (fs75.existsSync(path97.join(cwd, "pyproject.toml")) || fs75.existsSync(path97.join(cwd, "requirements.txt"))) {
|
|
86563
86588
|
ecosystems.push("pip");
|
|
86564
86589
|
}
|
|
86565
|
-
if (
|
|
86590
|
+
if (fs75.existsSync(path97.join(cwd, "Cargo.toml"))) {
|
|
86566
86591
|
ecosystems.push("cargo");
|
|
86567
86592
|
}
|
|
86568
|
-
if (
|
|
86593
|
+
if (fs75.existsSync(path97.join(cwd, "go.mod"))) {
|
|
86569
86594
|
ecosystems.push("go");
|
|
86570
86595
|
}
|
|
86571
86596
|
try {
|
|
86572
|
-
const files =
|
|
86597
|
+
const files = fs75.readdirSync(cwd);
|
|
86573
86598
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
86574
86599
|
ecosystems.push("dotnet");
|
|
86575
86600
|
}
|
|
86576
86601
|
} catch {}
|
|
86577
|
-
if (
|
|
86602
|
+
if (fs75.existsSync(path97.join(cwd, "Gemfile")) || fs75.existsSync(path97.join(cwd, "Gemfile.lock"))) {
|
|
86578
86603
|
ecosystems.push("ruby");
|
|
86579
86604
|
}
|
|
86580
|
-
if (
|
|
86605
|
+
if (fs75.existsSync(path97.join(cwd, "pubspec.yaml"))) {
|
|
86581
86606
|
ecosystems.push("dart");
|
|
86582
86607
|
}
|
|
86583
|
-
if (
|
|
86608
|
+
if (fs75.existsSync(path97.join(cwd, "composer.lock"))) {
|
|
86584
86609
|
ecosystems.push("composer");
|
|
86585
86610
|
}
|
|
86586
86611
|
return ecosystems;
|
|
@@ -87715,8 +87740,8 @@ var pkg_audit = createSwarmTool({
|
|
|
87715
87740
|
// src/tools/placeholder-scan.ts
|
|
87716
87741
|
init_zod();
|
|
87717
87742
|
init_manager2();
|
|
87718
|
-
import * as
|
|
87719
|
-
import * as
|
|
87743
|
+
import * as fs76 from "node:fs";
|
|
87744
|
+
import * as path98 from "node:path";
|
|
87720
87745
|
init_utils();
|
|
87721
87746
|
init_create_tool();
|
|
87722
87747
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -87839,7 +87864,7 @@ function isScaffoldFile(filePath) {
|
|
|
87839
87864
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
87840
87865
|
return true;
|
|
87841
87866
|
}
|
|
87842
|
-
const filename =
|
|
87867
|
+
const filename = path98.basename(filePath);
|
|
87843
87868
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
87844
87869
|
return true;
|
|
87845
87870
|
}
|
|
@@ -87856,7 +87881,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
87856
87881
|
if (regex.test(normalizedPath)) {
|
|
87857
87882
|
return true;
|
|
87858
87883
|
}
|
|
87859
|
-
const filename =
|
|
87884
|
+
const filename = path98.basename(filePath);
|
|
87860
87885
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
87861
87886
|
if (filenameRegex.test(filename)) {
|
|
87862
87887
|
return true;
|
|
@@ -87865,7 +87890,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
87865
87890
|
return false;
|
|
87866
87891
|
}
|
|
87867
87892
|
function isParserSupported(filePath) {
|
|
87868
|
-
const ext =
|
|
87893
|
+
const ext = path98.extname(filePath).toLowerCase();
|
|
87869
87894
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
87870
87895
|
}
|
|
87871
87896
|
function isPlanFile(filePath) {
|
|
@@ -88112,28 +88137,28 @@ async function placeholderScan(input, directory) {
|
|
|
88112
88137
|
let filesScanned = 0;
|
|
88113
88138
|
const filesWithFindings = new Set;
|
|
88114
88139
|
for (const filePath of changed_files) {
|
|
88115
|
-
const fullPath =
|
|
88116
|
-
const resolvedDirectory =
|
|
88117
|
-
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) {
|
|
88118
88143
|
continue;
|
|
88119
88144
|
}
|
|
88120
|
-
if (!
|
|
88145
|
+
if (!fs76.existsSync(fullPath)) {
|
|
88121
88146
|
continue;
|
|
88122
88147
|
}
|
|
88123
88148
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
88124
88149
|
continue;
|
|
88125
88150
|
}
|
|
88126
|
-
const relativeFilePath =
|
|
88151
|
+
const relativeFilePath = path98.relative(directory, fullPath).replace(/\\/g, "/");
|
|
88127
88152
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
88128
88153
|
continue;
|
|
88129
88154
|
}
|
|
88130
88155
|
let content;
|
|
88131
88156
|
try {
|
|
88132
|
-
const stat7 =
|
|
88157
|
+
const stat7 = fs76.statSync(fullPath);
|
|
88133
88158
|
if (stat7.size > MAX_FILE_SIZE) {
|
|
88134
88159
|
continue;
|
|
88135
88160
|
}
|
|
88136
|
-
content =
|
|
88161
|
+
content = fs76.readFileSync(fullPath, "utf-8");
|
|
88137
88162
|
} catch {
|
|
88138
88163
|
continue;
|
|
88139
88164
|
}
|
|
@@ -88194,8 +88219,8 @@ var placeholder_scan = createSwarmTool({
|
|
|
88194
88219
|
}
|
|
88195
88220
|
});
|
|
88196
88221
|
// src/tools/pre-check-batch.ts
|
|
88197
|
-
import * as
|
|
88198
|
-
import * as
|
|
88222
|
+
import * as fs80 from "node:fs";
|
|
88223
|
+
import * as path102 from "node:path";
|
|
88199
88224
|
init_zod();
|
|
88200
88225
|
init_manager2();
|
|
88201
88226
|
init_utils();
|
|
@@ -88335,8 +88360,8 @@ var _internals30 = {
|
|
|
88335
88360
|
init_zod();
|
|
88336
88361
|
init_manager2();
|
|
88337
88362
|
init_detector();
|
|
88338
|
-
import * as
|
|
88339
|
-
import * as
|
|
88363
|
+
import * as fs79 from "node:fs";
|
|
88364
|
+
import * as path101 from "node:path";
|
|
88340
88365
|
import { extname as extname18 } from "node:path";
|
|
88341
88366
|
|
|
88342
88367
|
// src/sast/rules/c.ts
|
|
@@ -89051,8 +89076,8 @@ function executeRulesSync(filePath, content, language) {
|
|
|
89051
89076
|
|
|
89052
89077
|
// src/sast/semgrep.ts
|
|
89053
89078
|
import * as child_process9 from "node:child_process";
|
|
89054
|
-
import * as
|
|
89055
|
-
import * as
|
|
89079
|
+
import * as fs77 from "node:fs";
|
|
89080
|
+
import * as path99 from "node:path";
|
|
89056
89081
|
var semgrepAvailableCache = null;
|
|
89057
89082
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
89058
89083
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
@@ -89239,14 +89264,14 @@ async function runSemgrep(options) {
|
|
|
89239
89264
|
}
|
|
89240
89265
|
function getRulesDirectory(projectRoot) {
|
|
89241
89266
|
if (projectRoot) {
|
|
89242
|
-
return
|
|
89267
|
+
return path99.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
89243
89268
|
}
|
|
89244
89269
|
return DEFAULT_RULES_DIR;
|
|
89245
89270
|
}
|
|
89246
89271
|
function hasBundledRules(projectRoot) {
|
|
89247
89272
|
const rulesDir = getRulesDirectory(projectRoot);
|
|
89248
89273
|
try {
|
|
89249
|
-
return
|
|
89274
|
+
return fs77.existsSync(rulesDir);
|
|
89250
89275
|
} catch {
|
|
89251
89276
|
return false;
|
|
89252
89277
|
}
|
|
@@ -89259,25 +89284,25 @@ init_create_tool();
|
|
|
89259
89284
|
// src/tools/sast-baseline.ts
|
|
89260
89285
|
init_utils2();
|
|
89261
89286
|
import * as crypto9 from "node:crypto";
|
|
89262
|
-
import * as
|
|
89263
|
-
import * as
|
|
89287
|
+
import * as fs78 from "node:fs";
|
|
89288
|
+
import * as path100 from "node:path";
|
|
89264
89289
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
89265
89290
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
89266
89291
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
89267
89292
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
89268
89293
|
function normalizeFindingPath(directory, file3) {
|
|
89269
|
-
const resolved =
|
|
89270
|
-
const rel =
|
|
89294
|
+
const resolved = path100.isAbsolute(file3) ? file3 : path100.resolve(directory, file3);
|
|
89295
|
+
const rel = path100.relative(path100.resolve(directory), resolved);
|
|
89271
89296
|
return rel.replace(/\\/g, "/");
|
|
89272
89297
|
}
|
|
89273
89298
|
function baselineRelPath(phase) {
|
|
89274
|
-
return
|
|
89299
|
+
return path100.join("evidence", String(phase), "sast-baseline.json");
|
|
89275
89300
|
}
|
|
89276
89301
|
function tempRelPath(phase) {
|
|
89277
|
-
return
|
|
89302
|
+
return path100.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
89278
89303
|
}
|
|
89279
89304
|
function lockRelPath(phase) {
|
|
89280
|
-
return
|
|
89305
|
+
return path100.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
89281
89306
|
}
|
|
89282
89307
|
function getLine(lines, idx) {
|
|
89283
89308
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -89294,7 +89319,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
|
|
|
89294
89319
|
}
|
|
89295
89320
|
const lineNum = finding.location.line;
|
|
89296
89321
|
try {
|
|
89297
|
-
const content =
|
|
89322
|
+
const content = fs78.readFileSync(finding.location.file, "utf-8");
|
|
89298
89323
|
const lines = content.split(`
|
|
89299
89324
|
`);
|
|
89300
89325
|
const idx = lineNum - 1;
|
|
@@ -89325,7 +89350,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
89325
89350
|
try {
|
|
89326
89351
|
if (relFile.startsWith(".."))
|
|
89327
89352
|
throw new Error("escapes workspace");
|
|
89328
|
-
const content =
|
|
89353
|
+
const content = fs78.readFileSync(finding.location.file, "utf-8");
|
|
89329
89354
|
const lines = content.split(`
|
|
89330
89355
|
`);
|
|
89331
89356
|
const idx = lineNum - 1;
|
|
@@ -89354,11 +89379,11 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
89354
89379
|
async function acquireLock(lockPath) {
|
|
89355
89380
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
89356
89381
|
try {
|
|
89357
|
-
const fd =
|
|
89358
|
-
|
|
89382
|
+
const fd = fs78.openSync(lockPath, "wx");
|
|
89383
|
+
fs78.closeSync(fd);
|
|
89359
89384
|
return () => {
|
|
89360
89385
|
try {
|
|
89361
|
-
|
|
89386
|
+
fs78.unlinkSync(lockPath);
|
|
89362
89387
|
} catch {}
|
|
89363
89388
|
};
|
|
89364
89389
|
} catch {
|
|
@@ -89398,13 +89423,13 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
89398
89423
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
89399
89424
|
};
|
|
89400
89425
|
}
|
|
89401
|
-
|
|
89402
|
-
|
|
89426
|
+
fs78.mkdirSync(path100.dirname(baselinePath), { recursive: true });
|
|
89427
|
+
fs78.mkdirSync(path100.dirname(tempPath), { recursive: true });
|
|
89403
89428
|
const releaseLock = await acquireLock(lockPath);
|
|
89404
89429
|
try {
|
|
89405
89430
|
let existing = null;
|
|
89406
89431
|
try {
|
|
89407
|
-
const raw =
|
|
89432
|
+
const raw = fs78.readFileSync(baselinePath, "utf-8");
|
|
89408
89433
|
const parsed = JSON.parse(raw);
|
|
89409
89434
|
if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
|
|
89410
89435
|
existing = parsed;
|
|
@@ -89464,8 +89489,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
89464
89489
|
message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
89465
89490
|
};
|
|
89466
89491
|
}
|
|
89467
|
-
|
|
89468
|
-
|
|
89492
|
+
fs78.writeFileSync(tempPath, json4, "utf-8");
|
|
89493
|
+
fs78.renameSync(tempPath, baselinePath);
|
|
89469
89494
|
return {
|
|
89470
89495
|
status: "merged",
|
|
89471
89496
|
path: baselinePath,
|
|
@@ -89496,8 +89521,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
89496
89521
|
message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
89497
89522
|
};
|
|
89498
89523
|
}
|
|
89499
|
-
|
|
89500
|
-
|
|
89524
|
+
fs78.writeFileSync(tempPath, json3, "utf-8");
|
|
89525
|
+
fs78.renameSync(tempPath, baselinePath);
|
|
89501
89526
|
return {
|
|
89502
89527
|
status: "written",
|
|
89503
89528
|
path: baselinePath,
|
|
@@ -89522,7 +89547,7 @@ function loadBaseline(directory, phase) {
|
|
|
89522
89547
|
};
|
|
89523
89548
|
}
|
|
89524
89549
|
try {
|
|
89525
|
-
const raw =
|
|
89550
|
+
const raw = fs78.readFileSync(baselinePath, "utf-8");
|
|
89526
89551
|
const parsed = JSON.parse(raw);
|
|
89527
89552
|
if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
|
|
89528
89553
|
return {
|
|
@@ -89570,17 +89595,17 @@ var SEVERITY_ORDER = {
|
|
|
89570
89595
|
};
|
|
89571
89596
|
function shouldSkipFile(filePath) {
|
|
89572
89597
|
try {
|
|
89573
|
-
const stats =
|
|
89598
|
+
const stats = fs79.statSync(filePath);
|
|
89574
89599
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
89575
89600
|
return { skip: true, reason: "file too large" };
|
|
89576
89601
|
}
|
|
89577
89602
|
if (stats.size === 0) {
|
|
89578
89603
|
return { skip: true, reason: "empty file" };
|
|
89579
89604
|
}
|
|
89580
|
-
const fd =
|
|
89605
|
+
const fd = fs79.openSync(filePath, "r");
|
|
89581
89606
|
const buffer = Buffer.alloc(8192);
|
|
89582
|
-
const bytesRead =
|
|
89583
|
-
|
|
89607
|
+
const bytesRead = fs79.readSync(fd, buffer, 0, 8192, 0);
|
|
89608
|
+
fs79.closeSync(fd);
|
|
89584
89609
|
if (bytesRead > 0) {
|
|
89585
89610
|
let nullCount = 0;
|
|
89586
89611
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -89619,7 +89644,7 @@ function countBySeverity(findings) {
|
|
|
89619
89644
|
}
|
|
89620
89645
|
function scanFileWithTierA(filePath, language) {
|
|
89621
89646
|
try {
|
|
89622
|
-
const content =
|
|
89647
|
+
const content = fs79.readFileSync(filePath, "utf-8");
|
|
89623
89648
|
const findings = executeRulesSync(filePath, content, language);
|
|
89624
89649
|
return findings.map((f) => ({
|
|
89625
89650
|
rule_id: f.rule_id,
|
|
@@ -89672,13 +89697,13 @@ async function sastScan(input, directory, config3) {
|
|
|
89672
89697
|
_filesSkipped++;
|
|
89673
89698
|
continue;
|
|
89674
89699
|
}
|
|
89675
|
-
const resolvedPath =
|
|
89676
|
-
const resolvedDirectory =
|
|
89677
|
-
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) {
|
|
89678
89703
|
_filesSkipped++;
|
|
89679
89704
|
continue;
|
|
89680
89705
|
}
|
|
89681
|
-
if (!
|
|
89706
|
+
if (!fs79.existsSync(resolvedPath)) {
|
|
89682
89707
|
_filesSkipped++;
|
|
89683
89708
|
continue;
|
|
89684
89709
|
}
|
|
@@ -89989,18 +90014,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
89989
90014
|
let resolved;
|
|
89990
90015
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
89991
90016
|
if (isWinAbs) {
|
|
89992
|
-
resolved =
|
|
89993
|
-
} else if (
|
|
89994
|
-
resolved =
|
|
90017
|
+
resolved = path102.win32.resolve(inputPath);
|
|
90018
|
+
} else if (path102.isAbsolute(inputPath)) {
|
|
90019
|
+
resolved = path102.resolve(inputPath);
|
|
89995
90020
|
} else {
|
|
89996
|
-
resolved =
|
|
90021
|
+
resolved = path102.resolve(baseDir, inputPath);
|
|
89997
90022
|
}
|
|
89998
|
-
const workspaceResolved =
|
|
90023
|
+
const workspaceResolved = path102.resolve(workspaceDir);
|
|
89999
90024
|
let relative22;
|
|
90000
90025
|
if (isWinAbs) {
|
|
90001
|
-
relative22 =
|
|
90026
|
+
relative22 = path102.win32.relative(workspaceResolved, resolved);
|
|
90002
90027
|
} else {
|
|
90003
|
-
relative22 =
|
|
90028
|
+
relative22 = path102.relative(workspaceResolved, resolved);
|
|
90004
90029
|
}
|
|
90005
90030
|
if (relative22.startsWith("..")) {
|
|
90006
90031
|
return "path traversal detected";
|
|
@@ -90065,7 +90090,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
90065
90090
|
if (typeof file3 !== "string") {
|
|
90066
90091
|
continue;
|
|
90067
90092
|
}
|
|
90068
|
-
const resolvedPath =
|
|
90093
|
+
const resolvedPath = path102.resolve(file3);
|
|
90069
90094
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
90070
90095
|
if (validationError) {
|
|
90071
90096
|
continue;
|
|
@@ -90222,7 +90247,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
90222
90247
|
skippedFiles++;
|
|
90223
90248
|
continue;
|
|
90224
90249
|
}
|
|
90225
|
-
const resolvedPath =
|
|
90250
|
+
const resolvedPath = path102.resolve(file3);
|
|
90226
90251
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
90227
90252
|
if (validationError) {
|
|
90228
90253
|
skippedFiles++;
|
|
@@ -90240,14 +90265,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
90240
90265
|
};
|
|
90241
90266
|
}
|
|
90242
90267
|
for (const file3 of validatedFiles) {
|
|
90243
|
-
const ext =
|
|
90268
|
+
const ext = path102.extname(file3).toLowerCase();
|
|
90244
90269
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
90245
90270
|
skippedFiles++;
|
|
90246
90271
|
continue;
|
|
90247
90272
|
}
|
|
90248
90273
|
let stat7;
|
|
90249
90274
|
try {
|
|
90250
|
-
stat7 =
|
|
90275
|
+
stat7 = fs80.statSync(file3);
|
|
90251
90276
|
} catch {
|
|
90252
90277
|
skippedFiles++;
|
|
90253
90278
|
continue;
|
|
@@ -90258,7 +90283,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
90258
90283
|
}
|
|
90259
90284
|
let content;
|
|
90260
90285
|
try {
|
|
90261
|
-
const buffer =
|
|
90286
|
+
const buffer = fs80.readFileSync(file3);
|
|
90262
90287
|
if (buffer.includes(0)) {
|
|
90263
90288
|
skippedFiles++;
|
|
90264
90289
|
continue;
|
|
@@ -90459,7 +90484,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
90459
90484
|
const preexistingFindings = [];
|
|
90460
90485
|
for (const finding of findings) {
|
|
90461
90486
|
const filePath = finding.location.file;
|
|
90462
|
-
const normalised =
|
|
90487
|
+
const normalised = path102.relative(directory, filePath).replace(/\\/g, "/");
|
|
90463
90488
|
const changedLines = changedLineRanges.get(normalised);
|
|
90464
90489
|
if (changedLines?.has(finding.location.line)) {
|
|
90465
90490
|
newFindings.push(finding);
|
|
@@ -90510,7 +90535,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
90510
90535
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
90511
90536
|
continue;
|
|
90512
90537
|
}
|
|
90513
|
-
changedFiles.push(
|
|
90538
|
+
changedFiles.push(path102.resolve(directory, file3));
|
|
90514
90539
|
}
|
|
90515
90540
|
if (changedFiles.length === 0) {
|
|
90516
90541
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -90711,7 +90736,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
90711
90736
|
};
|
|
90712
90737
|
return JSON.stringify(errorResult, null, 2);
|
|
90713
90738
|
}
|
|
90714
|
-
const resolvedDirectory =
|
|
90739
|
+
const resolvedDirectory = path102.resolve(typedArgs.directory);
|
|
90715
90740
|
const workspaceAnchor = resolvedDirectory;
|
|
90716
90741
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
90717
90742
|
if (dirError) {
|
|
@@ -90752,7 +90777,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
90752
90777
|
});
|
|
90753
90778
|
// src/tools/repo-map.ts
|
|
90754
90779
|
init_zod();
|
|
90755
|
-
import * as
|
|
90780
|
+
import * as path103 from "node:path";
|
|
90756
90781
|
init_path_security();
|
|
90757
90782
|
init_create_tool();
|
|
90758
90783
|
var VALID_ACTIONS = [
|
|
@@ -90777,7 +90802,7 @@ function validateFile(p) {
|
|
|
90777
90802
|
return "file contains control characters";
|
|
90778
90803
|
if (containsPathTraversal(p))
|
|
90779
90804
|
return "file contains path traversal";
|
|
90780
|
-
if (
|
|
90805
|
+
if (path103.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
90781
90806
|
return "file must be a workspace-relative path, not absolute";
|
|
90782
90807
|
}
|
|
90783
90808
|
return null;
|
|
@@ -90800,8 +90825,8 @@ function ok(action, payload) {
|
|
|
90800
90825
|
}
|
|
90801
90826
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
90802
90827
|
const normalized = input.replace(/\\/g, "/");
|
|
90803
|
-
if (
|
|
90804
|
-
const rel =
|
|
90828
|
+
if (path103.isAbsolute(normalized)) {
|
|
90829
|
+
const rel = path103.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
90805
90830
|
return normalizeGraphPath2(rel);
|
|
90806
90831
|
}
|
|
90807
90832
|
return normalizeGraphPath2(normalized);
|
|
@@ -90945,8 +90970,8 @@ var repo_map = createSwarmTool({
|
|
|
90945
90970
|
// src/tools/req-coverage.ts
|
|
90946
90971
|
init_zod();
|
|
90947
90972
|
init_create_tool();
|
|
90948
|
-
import * as
|
|
90949
|
-
import * as
|
|
90973
|
+
import * as fs81 from "node:fs";
|
|
90974
|
+
import * as path104 from "node:path";
|
|
90950
90975
|
var SPEC_FILE = ".swarm/spec.md";
|
|
90951
90976
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
90952
90977
|
var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -91005,19 +91030,19 @@ function extractObligationAndText(id, lineText) {
|
|
|
91005
91030
|
var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
91006
91031
|
function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
91007
91032
|
const touchedFiles = new Set;
|
|
91008
|
-
if (!
|
|
91033
|
+
if (!fs81.existsSync(evidenceDir) || !fs81.statSync(evidenceDir).isDirectory()) {
|
|
91009
91034
|
return [];
|
|
91010
91035
|
}
|
|
91011
91036
|
let entries;
|
|
91012
91037
|
try {
|
|
91013
|
-
entries =
|
|
91038
|
+
entries = fs81.readdirSync(evidenceDir);
|
|
91014
91039
|
} catch {
|
|
91015
91040
|
return [];
|
|
91016
91041
|
}
|
|
91017
91042
|
for (const entry of entries) {
|
|
91018
|
-
const entryPath =
|
|
91043
|
+
const entryPath = path104.join(evidenceDir, entry);
|
|
91019
91044
|
try {
|
|
91020
|
-
const stat7 =
|
|
91045
|
+
const stat7 = fs81.statSync(entryPath);
|
|
91021
91046
|
if (!stat7.isDirectory()) {
|
|
91022
91047
|
continue;
|
|
91023
91048
|
}
|
|
@@ -91031,14 +91056,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91031
91056
|
if (entryPhase !== String(phase)) {
|
|
91032
91057
|
continue;
|
|
91033
91058
|
}
|
|
91034
|
-
const evidenceFilePath =
|
|
91059
|
+
const evidenceFilePath = path104.join(entryPath, "evidence.json");
|
|
91035
91060
|
try {
|
|
91036
|
-
const resolvedPath =
|
|
91037
|
-
const evidenceDirResolved =
|
|
91038
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
91061
|
+
const resolvedPath = path104.resolve(evidenceFilePath);
|
|
91062
|
+
const evidenceDirResolved = path104.resolve(evidenceDir);
|
|
91063
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path104.sep)) {
|
|
91039
91064
|
continue;
|
|
91040
91065
|
}
|
|
91041
|
-
const stat7 =
|
|
91066
|
+
const stat7 = fs81.lstatSync(evidenceFilePath);
|
|
91042
91067
|
if (!stat7.isFile()) {
|
|
91043
91068
|
continue;
|
|
91044
91069
|
}
|
|
@@ -91050,7 +91075,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91050
91075
|
}
|
|
91051
91076
|
let content;
|
|
91052
91077
|
try {
|
|
91053
|
-
content =
|
|
91078
|
+
content = fs81.readFileSync(evidenceFilePath, "utf-8");
|
|
91054
91079
|
} catch {
|
|
91055
91080
|
continue;
|
|
91056
91081
|
}
|
|
@@ -91069,7 +91094,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91069
91094
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
91070
91095
|
for (const file3 of diffEntry.files_changed) {
|
|
91071
91096
|
if (typeof file3 === "string") {
|
|
91072
|
-
touchedFiles.add(
|
|
91097
|
+
touchedFiles.add(path104.resolve(cwd, file3));
|
|
91073
91098
|
}
|
|
91074
91099
|
}
|
|
91075
91100
|
}
|
|
@@ -91082,12 +91107,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91082
91107
|
}
|
|
91083
91108
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
91084
91109
|
try {
|
|
91085
|
-
const resolvedPath =
|
|
91086
|
-
const cwdResolved =
|
|
91110
|
+
const resolvedPath = path104.resolve(filePath);
|
|
91111
|
+
const cwdResolved = path104.resolve(cwd);
|
|
91087
91112
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
91088
91113
|
return false;
|
|
91089
91114
|
}
|
|
91090
|
-
const content =
|
|
91115
|
+
const content = fs81.readFileSync(resolvedPath, "utf-8");
|
|
91091
91116
|
for (const keyword of keywords) {
|
|
91092
91117
|
const regex = new RegExp(`\\b${keyword}\\b`, "i");
|
|
91093
91118
|
if (regex.test(content)) {
|
|
@@ -91217,10 +91242,10 @@ var req_coverage = createSwarmTool({
|
|
|
91217
91242
|
}, null, 2);
|
|
91218
91243
|
}
|
|
91219
91244
|
const cwd = inputDirectory || directory;
|
|
91220
|
-
const specPath =
|
|
91245
|
+
const specPath = path104.join(cwd, SPEC_FILE);
|
|
91221
91246
|
let specContent;
|
|
91222
91247
|
try {
|
|
91223
|
-
specContent =
|
|
91248
|
+
specContent = fs81.readFileSync(specPath, "utf-8");
|
|
91224
91249
|
} catch (readError) {
|
|
91225
91250
|
return JSON.stringify({
|
|
91226
91251
|
success: false,
|
|
@@ -91244,7 +91269,7 @@ var req_coverage = createSwarmTool({
|
|
|
91244
91269
|
message: "No FR requirements found in spec.md"
|
|
91245
91270
|
}, null, 2);
|
|
91246
91271
|
}
|
|
91247
|
-
const evidenceDir =
|
|
91272
|
+
const evidenceDir = path104.join(cwd, EVIDENCE_DIR4);
|
|
91248
91273
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
91249
91274
|
const analyzedRequirements = [];
|
|
91250
91275
|
let coveredCount = 0;
|
|
@@ -91270,12 +91295,12 @@ var req_coverage = createSwarmTool({
|
|
|
91270
91295
|
requirements: analyzedRequirements
|
|
91271
91296
|
};
|
|
91272
91297
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
91273
|
-
const reportPath =
|
|
91298
|
+
const reportPath = path104.join(evidenceDir, reportFilename);
|
|
91274
91299
|
try {
|
|
91275
|
-
if (!
|
|
91276
|
-
|
|
91300
|
+
if (!fs81.existsSync(evidenceDir)) {
|
|
91301
|
+
fs81.mkdirSync(evidenceDir, { recursive: true });
|
|
91277
91302
|
}
|
|
91278
|
-
|
|
91303
|
+
fs81.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
|
|
91279
91304
|
} catch (writeError) {
|
|
91280
91305
|
console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
91281
91306
|
}
|
|
@@ -91357,8 +91382,8 @@ init_plan_schema();
|
|
|
91357
91382
|
init_qa_gate_profile();
|
|
91358
91383
|
init_file_locks();
|
|
91359
91384
|
import * as crypto10 from "node:crypto";
|
|
91360
|
-
import * as
|
|
91361
|
-
import * as
|
|
91385
|
+
import * as fs82 from "node:fs";
|
|
91386
|
+
import * as path105 from "node:path";
|
|
91362
91387
|
init_ledger();
|
|
91363
91388
|
init_manager();
|
|
91364
91389
|
init_state();
|
|
@@ -91436,17 +91461,17 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91436
91461
|
};
|
|
91437
91462
|
}
|
|
91438
91463
|
if (args2.working_directory && fallbackDir) {
|
|
91439
|
-
const resolvedTarget =
|
|
91440
|
-
const resolvedRoot =
|
|
91464
|
+
const resolvedTarget = path105.resolve(args2.working_directory);
|
|
91465
|
+
const resolvedRoot = path105.resolve(fallbackDir);
|
|
91441
91466
|
let fallbackExists = false;
|
|
91442
91467
|
try {
|
|
91443
|
-
|
|
91468
|
+
fs82.accessSync(resolvedRoot, fs82.constants.F_OK);
|
|
91444
91469
|
fallbackExists = true;
|
|
91445
91470
|
} catch {
|
|
91446
91471
|
fallbackExists = false;
|
|
91447
91472
|
}
|
|
91448
91473
|
if (fallbackExists) {
|
|
91449
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
91474
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path105.sep);
|
|
91450
91475
|
if (isSubdirectory) {
|
|
91451
91476
|
return {
|
|
91452
91477
|
success: false,
|
|
@@ -91462,11 +91487,11 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91462
91487
|
let specMtime;
|
|
91463
91488
|
let specHash;
|
|
91464
91489
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
91465
|
-
const specPath =
|
|
91490
|
+
const specPath = path105.join(targetWorkspace, ".swarm", "spec.md");
|
|
91466
91491
|
try {
|
|
91467
|
-
const stat7 = await
|
|
91492
|
+
const stat7 = await fs82.promises.stat(specPath);
|
|
91468
91493
|
specMtime = stat7.mtime.toISOString();
|
|
91469
|
-
const content = await
|
|
91494
|
+
const content = await fs82.promises.readFile(specPath, "utf8");
|
|
91470
91495
|
specHash = crypto10.createHash("sha256").update(content).digest("hex");
|
|
91471
91496
|
} catch {
|
|
91472
91497
|
return {
|
|
@@ -91478,10 +91503,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91478
91503
|
}
|
|
91479
91504
|
}
|
|
91480
91505
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
91481
|
-
const contextPath =
|
|
91506
|
+
const contextPath = path105.join(targetWorkspace, ".swarm", "context.md");
|
|
91482
91507
|
let contextContent = "";
|
|
91483
91508
|
try {
|
|
91484
|
-
contextContent = await
|
|
91509
|
+
contextContent = await fs82.promises.readFile(contextPath, "utf8");
|
|
91485
91510
|
} catch {}
|
|
91486
91511
|
const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
|
|
91487
91512
|
if (!hasPendingSection) {
|
|
@@ -91631,14 +91656,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91631
91656
|
}
|
|
91632
91657
|
await writeCheckpoint(dir).catch(() => {});
|
|
91633
91658
|
try {
|
|
91634
|
-
const markerPath =
|
|
91659
|
+
const markerPath = path105.join(dir, ".swarm", ".plan-write-marker");
|
|
91635
91660
|
const marker = JSON.stringify({
|
|
91636
91661
|
source: "save_plan",
|
|
91637
91662
|
timestamp: new Date().toISOString(),
|
|
91638
91663
|
phases_count: plan.phases.length,
|
|
91639
91664
|
tasks_count: tasksCount
|
|
91640
91665
|
});
|
|
91641
|
-
await
|
|
91666
|
+
await fs82.promises.writeFile(markerPath, marker, "utf8");
|
|
91642
91667
|
} catch {}
|
|
91643
91668
|
const warnings = [];
|
|
91644
91669
|
let criticReviewFound = false;
|
|
@@ -91654,7 +91679,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91654
91679
|
return {
|
|
91655
91680
|
success: true,
|
|
91656
91681
|
message: "Plan saved successfully",
|
|
91657
|
-
plan_path:
|
|
91682
|
+
plan_path: path105.join(dir, ".swarm", "plan.json"),
|
|
91658
91683
|
phases_count: plan.phases.length,
|
|
91659
91684
|
tasks_count: tasksCount,
|
|
91660
91685
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -91706,8 +91731,8 @@ var save_plan = createSwarmTool({
|
|
|
91706
91731
|
// src/tools/sbom-generate.ts
|
|
91707
91732
|
init_zod();
|
|
91708
91733
|
init_manager2();
|
|
91709
|
-
import * as
|
|
91710
|
-
import * as
|
|
91734
|
+
import * as fs83 from "node:fs";
|
|
91735
|
+
import * as path106 from "node:path";
|
|
91711
91736
|
|
|
91712
91737
|
// src/sbom/detectors/index.ts
|
|
91713
91738
|
init_utils();
|
|
@@ -92555,9 +92580,9 @@ function findManifestFiles(rootDir) {
|
|
|
92555
92580
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
92556
92581
|
function searchDir(dir) {
|
|
92557
92582
|
try {
|
|
92558
|
-
const entries =
|
|
92583
|
+
const entries = fs83.readdirSync(dir, { withFileTypes: true });
|
|
92559
92584
|
for (const entry of entries) {
|
|
92560
|
-
const fullPath =
|
|
92585
|
+
const fullPath = path106.join(dir, entry.name);
|
|
92561
92586
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
92562
92587
|
continue;
|
|
92563
92588
|
}
|
|
@@ -92566,7 +92591,7 @@ function findManifestFiles(rootDir) {
|
|
|
92566
92591
|
} else if (entry.isFile()) {
|
|
92567
92592
|
for (const pattern of patterns) {
|
|
92568
92593
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
92569
|
-
manifestFiles.push(
|
|
92594
|
+
manifestFiles.push(path106.relative(rootDir, fullPath));
|
|
92570
92595
|
break;
|
|
92571
92596
|
}
|
|
92572
92597
|
}
|
|
@@ -92582,13 +92607,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
92582
92607
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
92583
92608
|
for (const dir of directories) {
|
|
92584
92609
|
try {
|
|
92585
|
-
const entries =
|
|
92610
|
+
const entries = fs83.readdirSync(dir, { withFileTypes: true });
|
|
92586
92611
|
for (const entry of entries) {
|
|
92587
|
-
const fullPath =
|
|
92612
|
+
const fullPath = path106.join(dir, entry.name);
|
|
92588
92613
|
if (entry.isFile()) {
|
|
92589
92614
|
for (const pattern of patterns) {
|
|
92590
92615
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
92591
|
-
found.push(
|
|
92616
|
+
found.push(path106.relative(workingDir, fullPath));
|
|
92592
92617
|
break;
|
|
92593
92618
|
}
|
|
92594
92619
|
}
|
|
@@ -92601,11 +92626,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
92601
92626
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
92602
92627
|
const dirs = new Set;
|
|
92603
92628
|
for (const file3 of changedFiles) {
|
|
92604
|
-
let currentDir =
|
|
92629
|
+
let currentDir = path106.dirname(file3);
|
|
92605
92630
|
while (true) {
|
|
92606
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
92607
|
-
dirs.add(
|
|
92608
|
-
const parent =
|
|
92631
|
+
if (currentDir && currentDir !== "." && currentDir !== path106.sep) {
|
|
92632
|
+
dirs.add(path106.join(workingDir, currentDir));
|
|
92633
|
+
const parent = path106.dirname(currentDir);
|
|
92609
92634
|
if (parent === currentDir)
|
|
92610
92635
|
break;
|
|
92611
92636
|
currentDir = parent;
|
|
@@ -92619,7 +92644,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
92619
92644
|
}
|
|
92620
92645
|
function ensureOutputDir(outputDir) {
|
|
92621
92646
|
try {
|
|
92622
|
-
|
|
92647
|
+
fs83.mkdirSync(outputDir, { recursive: true });
|
|
92623
92648
|
} catch (error93) {
|
|
92624
92649
|
if (!error93 || error93.code !== "EEXIST") {
|
|
92625
92650
|
throw error93;
|
|
@@ -92689,7 +92714,7 @@ var sbom_generate = createSwarmTool({
|
|
|
92689
92714
|
const changedFiles = obj.changed_files;
|
|
92690
92715
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
92691
92716
|
const workingDir = directory;
|
|
92692
|
-
const outputDir =
|
|
92717
|
+
const outputDir = path106.isAbsolute(relativeOutputDir) ? relativeOutputDir : path106.join(workingDir, relativeOutputDir);
|
|
92693
92718
|
let manifestFiles = [];
|
|
92694
92719
|
if (scope === "all") {
|
|
92695
92720
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -92712,11 +92737,11 @@ var sbom_generate = createSwarmTool({
|
|
|
92712
92737
|
const processedFiles = [];
|
|
92713
92738
|
for (const manifestFile of manifestFiles) {
|
|
92714
92739
|
try {
|
|
92715
|
-
const fullPath =
|
|
92716
|
-
if (!
|
|
92740
|
+
const fullPath = path106.isAbsolute(manifestFile) ? manifestFile : path106.join(workingDir, manifestFile);
|
|
92741
|
+
if (!fs83.existsSync(fullPath)) {
|
|
92717
92742
|
continue;
|
|
92718
92743
|
}
|
|
92719
|
-
const content =
|
|
92744
|
+
const content = fs83.readFileSync(fullPath, "utf-8");
|
|
92720
92745
|
const components = detectComponents(manifestFile, content);
|
|
92721
92746
|
processedFiles.push(manifestFile);
|
|
92722
92747
|
if (components.length > 0) {
|
|
@@ -92729,8 +92754,8 @@ var sbom_generate = createSwarmTool({
|
|
|
92729
92754
|
const bom = generateCycloneDX(allComponents);
|
|
92730
92755
|
const bomJson = serializeCycloneDX(bom);
|
|
92731
92756
|
const filename = generateSbomFilename();
|
|
92732
|
-
const outputPath =
|
|
92733
|
-
|
|
92757
|
+
const outputPath = path106.join(outputDir, filename);
|
|
92758
|
+
fs83.writeFileSync(outputPath, bomJson, "utf-8");
|
|
92734
92759
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
92735
92760
|
try {
|
|
92736
92761
|
const timestamp = new Date().toISOString();
|
|
@@ -92772,8 +92797,8 @@ var sbom_generate = createSwarmTool({
|
|
|
92772
92797
|
// src/tools/schema-drift.ts
|
|
92773
92798
|
init_zod();
|
|
92774
92799
|
init_create_tool();
|
|
92775
|
-
import * as
|
|
92776
|
-
import * as
|
|
92800
|
+
import * as fs84 from "node:fs";
|
|
92801
|
+
import * as path107 from "node:path";
|
|
92777
92802
|
var SPEC_CANDIDATES = [
|
|
92778
92803
|
"openapi.json",
|
|
92779
92804
|
"openapi.yaml",
|
|
@@ -92805,28 +92830,28 @@ function normalizePath4(p) {
|
|
|
92805
92830
|
}
|
|
92806
92831
|
function discoverSpecFile(cwd, specFileArg) {
|
|
92807
92832
|
if (specFileArg) {
|
|
92808
|
-
const resolvedPath =
|
|
92809
|
-
const normalizedCwd = cwd.endsWith(
|
|
92833
|
+
const resolvedPath = path107.resolve(cwd, specFileArg);
|
|
92834
|
+
const normalizedCwd = cwd.endsWith(path107.sep) ? cwd : cwd + path107.sep;
|
|
92810
92835
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
92811
92836
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
92812
92837
|
}
|
|
92813
|
-
const ext =
|
|
92838
|
+
const ext = path107.extname(resolvedPath).toLowerCase();
|
|
92814
92839
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
92815
92840
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
92816
92841
|
}
|
|
92817
|
-
const stats =
|
|
92842
|
+
const stats = fs84.statSync(resolvedPath);
|
|
92818
92843
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
92819
92844
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
92820
92845
|
}
|
|
92821
|
-
if (!
|
|
92846
|
+
if (!fs84.existsSync(resolvedPath)) {
|
|
92822
92847
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
92823
92848
|
}
|
|
92824
92849
|
return resolvedPath;
|
|
92825
92850
|
}
|
|
92826
92851
|
for (const candidate of SPEC_CANDIDATES) {
|
|
92827
|
-
const candidatePath =
|
|
92828
|
-
if (
|
|
92829
|
-
const stats =
|
|
92852
|
+
const candidatePath = path107.resolve(cwd, candidate);
|
|
92853
|
+
if (fs84.existsSync(candidatePath)) {
|
|
92854
|
+
const stats = fs84.statSync(candidatePath);
|
|
92830
92855
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
92831
92856
|
return candidatePath;
|
|
92832
92857
|
}
|
|
@@ -92835,8 +92860,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
92835
92860
|
return null;
|
|
92836
92861
|
}
|
|
92837
92862
|
function parseSpec(specFile) {
|
|
92838
|
-
const content =
|
|
92839
|
-
const ext =
|
|
92863
|
+
const content = fs84.readFileSync(specFile, "utf-8");
|
|
92864
|
+
const ext = path107.extname(specFile).toLowerCase();
|
|
92840
92865
|
if (ext === ".json") {
|
|
92841
92866
|
return parseJsonSpec(content);
|
|
92842
92867
|
}
|
|
@@ -92907,12 +92932,12 @@ function extractRoutes(cwd) {
|
|
|
92907
92932
|
function walkDir(dir) {
|
|
92908
92933
|
let entries;
|
|
92909
92934
|
try {
|
|
92910
|
-
entries =
|
|
92935
|
+
entries = fs84.readdirSync(dir, { withFileTypes: true });
|
|
92911
92936
|
} catch {
|
|
92912
92937
|
return;
|
|
92913
92938
|
}
|
|
92914
92939
|
for (const entry of entries) {
|
|
92915
|
-
const fullPath =
|
|
92940
|
+
const fullPath = path107.join(dir, entry.name);
|
|
92916
92941
|
if (entry.isSymbolicLink()) {
|
|
92917
92942
|
continue;
|
|
92918
92943
|
}
|
|
@@ -92922,7 +92947,7 @@ function extractRoutes(cwd) {
|
|
|
92922
92947
|
}
|
|
92923
92948
|
walkDir(fullPath);
|
|
92924
92949
|
} else if (entry.isFile()) {
|
|
92925
|
-
const ext =
|
|
92950
|
+
const ext = path107.extname(entry.name).toLowerCase();
|
|
92926
92951
|
const baseName = entry.name.toLowerCase();
|
|
92927
92952
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
92928
92953
|
continue;
|
|
@@ -92940,7 +92965,7 @@ function extractRoutes(cwd) {
|
|
|
92940
92965
|
}
|
|
92941
92966
|
function extractRoutesFromFile(filePath) {
|
|
92942
92967
|
const routes = [];
|
|
92943
|
-
const content =
|
|
92968
|
+
const content = fs84.readFileSync(filePath, "utf-8");
|
|
92944
92969
|
const lines = content.split(/\r?\n/);
|
|
92945
92970
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
92946
92971
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -93089,8 +93114,8 @@ init_zod();
|
|
|
93089
93114
|
init_bun_compat();
|
|
93090
93115
|
init_path_security();
|
|
93091
93116
|
init_create_tool();
|
|
93092
|
-
import * as
|
|
93093
|
-
import * as
|
|
93117
|
+
import * as fs85 from "node:fs";
|
|
93118
|
+
import * as path108 from "node:path";
|
|
93094
93119
|
var DEFAULT_MAX_RESULTS = 100;
|
|
93095
93120
|
var DEFAULT_MAX_LINES = 200;
|
|
93096
93121
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -93126,11 +93151,11 @@ function containsWindowsAttacks3(str) {
|
|
|
93126
93151
|
}
|
|
93127
93152
|
function isPathInWorkspace3(filePath, workspace) {
|
|
93128
93153
|
try {
|
|
93129
|
-
const resolvedPath =
|
|
93130
|
-
const realWorkspace =
|
|
93131
|
-
const realResolvedPath =
|
|
93132
|
-
const relativePath =
|
|
93133
|
-
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)) {
|
|
93134
93159
|
return false;
|
|
93135
93160
|
}
|
|
93136
93161
|
return true;
|
|
@@ -93143,12 +93168,12 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
93143
93168
|
}
|
|
93144
93169
|
function findRgInEnvPath() {
|
|
93145
93170
|
const searchPath = process.env.PATH ?? "";
|
|
93146
|
-
for (const dir of searchPath.split(
|
|
93171
|
+
for (const dir of searchPath.split(path108.delimiter)) {
|
|
93147
93172
|
if (!dir)
|
|
93148
93173
|
continue;
|
|
93149
93174
|
const isWindows = process.platform === "win32";
|
|
93150
|
-
const candidate =
|
|
93151
|
-
if (
|
|
93175
|
+
const candidate = path108.join(dir, isWindows ? "rg.exe" : "rg");
|
|
93176
|
+
if (fs85.existsSync(candidate))
|
|
93152
93177
|
return candidate;
|
|
93153
93178
|
}
|
|
93154
93179
|
return null;
|
|
@@ -93275,10 +93300,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
93275
93300
|
return files;
|
|
93276
93301
|
}
|
|
93277
93302
|
try {
|
|
93278
|
-
const entries =
|
|
93303
|
+
const entries = fs85.readdirSync(dir, { withFileTypes: true });
|
|
93279
93304
|
for (const entry of entries) {
|
|
93280
|
-
const fullPath =
|
|
93281
|
-
const relativePath =
|
|
93305
|
+
const fullPath = path108.join(dir, entry.name);
|
|
93306
|
+
const relativePath = path108.relative(workspace, fullPath);
|
|
93282
93307
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
93283
93308
|
continue;
|
|
93284
93309
|
}
|
|
@@ -93319,13 +93344,13 @@ async function fallbackSearch(opts) {
|
|
|
93319
93344
|
const matches = [];
|
|
93320
93345
|
let total = 0;
|
|
93321
93346
|
for (const file3 of files) {
|
|
93322
|
-
const fullPath =
|
|
93347
|
+
const fullPath = path108.join(opts.workspace, file3);
|
|
93323
93348
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
93324
93349
|
continue;
|
|
93325
93350
|
}
|
|
93326
93351
|
let stats;
|
|
93327
93352
|
try {
|
|
93328
|
-
stats =
|
|
93353
|
+
stats = fs85.statSync(fullPath);
|
|
93329
93354
|
if (stats.size > MAX_FILE_SIZE_BYTES10) {
|
|
93330
93355
|
continue;
|
|
93331
93356
|
}
|
|
@@ -93334,7 +93359,7 @@ async function fallbackSearch(opts) {
|
|
|
93334
93359
|
}
|
|
93335
93360
|
let content;
|
|
93336
93361
|
try {
|
|
93337
|
-
content =
|
|
93362
|
+
content = fs85.readFileSync(fullPath, "utf-8");
|
|
93338
93363
|
} catch {
|
|
93339
93364
|
continue;
|
|
93340
93365
|
}
|
|
@@ -93446,7 +93471,7 @@ var search = createSwarmTool({
|
|
|
93446
93471
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
93447
93472
|
}, null, 2);
|
|
93448
93473
|
}
|
|
93449
|
-
if (!
|
|
93474
|
+
if (!fs85.existsSync(directory)) {
|
|
93450
93475
|
return JSON.stringify({
|
|
93451
93476
|
error: true,
|
|
93452
93477
|
type: "unknown",
|
|
@@ -93626,7 +93651,7 @@ init_schema();
|
|
|
93626
93651
|
init_knowledge_store();
|
|
93627
93652
|
import { existsSync as existsSync64 } from "node:fs";
|
|
93628
93653
|
import { mkdir as mkdir17, rename as rename6, writeFile as writeFile14 } from "node:fs/promises";
|
|
93629
|
-
import * as
|
|
93654
|
+
import * as path110 from "node:path";
|
|
93630
93655
|
|
|
93631
93656
|
// src/hooks/skill-improver-llm-factory.ts
|
|
93632
93657
|
init_state();
|
|
@@ -93742,7 +93767,7 @@ init_skill_generator();
|
|
|
93742
93767
|
var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
|
|
93743
93768
|
import { existsSync as existsSync63 } from "node:fs";
|
|
93744
93769
|
import { mkdir as mkdir16, readFile as readFile15, rename as rename5, writeFile as writeFile13 } from "node:fs/promises";
|
|
93745
|
-
import * as
|
|
93770
|
+
import * as path109 from "node:path";
|
|
93746
93771
|
var LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
|
|
93747
93772
|
var LOCK_RETRY_OPTS = {
|
|
93748
93773
|
retries: {
|
|
@@ -93770,7 +93795,7 @@ async function acquireLock2(dir) {
|
|
|
93770
93795
|
}
|
|
93771
93796
|
}
|
|
93772
93797
|
function resolveQuotaPath(directory) {
|
|
93773
|
-
return
|
|
93798
|
+
return path109.join(directory, ".swarm", "skill-improver-quota.json");
|
|
93774
93799
|
}
|
|
93775
93800
|
function todayKey(window2, now = new Date) {
|
|
93776
93801
|
if (window2 === "utc") {
|
|
@@ -93796,7 +93821,7 @@ async function readState(filePath) {
|
|
|
93796
93821
|
}
|
|
93797
93822
|
}
|
|
93798
93823
|
async function writeState(filePath, state) {
|
|
93799
|
-
await mkdir16(
|
|
93824
|
+
await mkdir16(path109.dirname(filePath), { recursive: true });
|
|
93800
93825
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
93801
93826
|
await writeFile13(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
93802
93827
|
await rename5(tmp, filePath);
|
|
@@ -93819,10 +93844,10 @@ async function getQuotaState(directory, opts) {
|
|
|
93819
93844
|
}
|
|
93820
93845
|
async function reserveQuota(directory, opts) {
|
|
93821
93846
|
const filePath = resolveQuotaPath(directory);
|
|
93822
|
-
await mkdir16(
|
|
93847
|
+
await mkdir16(path109.dirname(filePath), { recursive: true });
|
|
93823
93848
|
let release = null;
|
|
93824
93849
|
try {
|
|
93825
|
-
release = await acquireLock2(
|
|
93850
|
+
release = await acquireLock2(path109.dirname(filePath));
|
|
93826
93851
|
const state = await getQuotaState(directory, opts);
|
|
93827
93852
|
if (state.calls_used + opts.nCalls > opts.maxCalls) {
|
|
93828
93853
|
return {
|
|
@@ -93849,10 +93874,10 @@ async function reserveQuota(directory, opts) {
|
|
|
93849
93874
|
}
|
|
93850
93875
|
async function releaseQuota(directory, opts) {
|
|
93851
93876
|
const filePath = resolveQuotaPath(directory);
|
|
93852
|
-
await mkdir16(
|
|
93877
|
+
await mkdir16(path109.dirname(filePath), { recursive: true });
|
|
93853
93878
|
let release = null;
|
|
93854
93879
|
try {
|
|
93855
|
-
release = await acquireLock2(
|
|
93880
|
+
release = await acquireLock2(path109.dirname(filePath));
|
|
93856
93881
|
const state = await getQuotaState(directory, opts);
|
|
93857
93882
|
const next = {
|
|
93858
93883
|
...state,
|
|
@@ -93875,7 +93900,7 @@ function timestampSlug(d) {
|
|
|
93875
93900
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
93876
93901
|
}
|
|
93877
93902
|
async function atomicWrite4(p, content) {
|
|
93878
|
-
await mkdir17(
|
|
93903
|
+
await mkdir17(path110.dirname(p), { recursive: true });
|
|
93879
93904
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
93880
93905
|
await writeFile14(tmp, content, "utf-8");
|
|
93881
93906
|
await rename6(tmp, p);
|
|
@@ -94075,8 +94100,8 @@ async function runSkillImprover(req) {
|
|
|
94075
94100
|
sourceKnowledgeIds: w.sourceKnowledgeIds
|
|
94076
94101
|
}));
|
|
94077
94102
|
}
|
|
94078
|
-
const proposalDir =
|
|
94079
|
-
const proposalFile =
|
|
94103
|
+
const proposalDir = path110.join(req.directory, ".swarm", "skill-improver", "proposals");
|
|
94104
|
+
const proposalFile = path110.join(proposalDir, `${timestampSlug(now)}.md`);
|
|
94080
94105
|
const finalBody = source === "llm" ? buildLLMProposalFrame({
|
|
94081
94106
|
body: body2,
|
|
94082
94107
|
targets,
|
|
@@ -94169,7 +94194,7 @@ init_config();
|
|
|
94169
94194
|
init_schema();
|
|
94170
94195
|
init_create_tool();
|
|
94171
94196
|
import { mkdir as mkdir18, rename as rename7, writeFile as writeFile15 } from "node:fs/promises";
|
|
94172
|
-
import * as
|
|
94197
|
+
import * as path111 from "node:path";
|
|
94173
94198
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
94174
94199
|
var spec_write = createSwarmTool({
|
|
94175
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.",
|
|
@@ -94210,14 +94235,14 @@ var spec_write = createSwarmTool({
|
|
|
94210
94235
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
94211
94236
|
}, null, 2);
|
|
94212
94237
|
}
|
|
94213
|
-
const target =
|
|
94214
|
-
await mkdir18(
|
|
94238
|
+
const target = path111.join(directory, ".swarm", "spec.md");
|
|
94239
|
+
await mkdir18(path111.dirname(target), { recursive: true });
|
|
94215
94240
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
94216
94241
|
let finalContent = content;
|
|
94217
94242
|
if (mode === "append") {
|
|
94218
94243
|
try {
|
|
94219
|
-
const
|
|
94220
|
-
const prior = await
|
|
94244
|
+
const fs86 = await import("node:fs/promises");
|
|
94245
|
+
const prior = await fs86.readFile(target, "utf-8");
|
|
94221
94246
|
finalContent = `${prior.replace(/\s+$/, "")}
|
|
94222
94247
|
|
|
94223
94248
|
${content}
|
|
@@ -94238,6 +94263,15 @@ ${content}
|
|
|
94238
94263
|
// src/tools/submit-phase-council-verdicts.ts
|
|
94239
94264
|
init_zod();
|
|
94240
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";
|
|
94241
94275
|
init_create_tool();
|
|
94242
94276
|
init_resolve_working_directory();
|
|
94243
94277
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -94340,6 +94374,12 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
94340
94374
|
}, null, 2);
|
|
94341
94375
|
}
|
|
94342
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);
|
|
94343
94383
|
return JSON.stringify({
|
|
94344
94384
|
success: true,
|
|
94345
94385
|
overallVerdict: synthesis.overallVerdict,
|
|
@@ -94350,6 +94390,7 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
94350
94390
|
advisoryFindingsCount: synthesis.advisoryFindings?.length ?? 0,
|
|
94351
94391
|
unresolvedConflictsCount: synthesis.unresolvedConflicts?.length ?? 0,
|
|
94352
94392
|
advisoryNotes: synthesis.advisoryNotes ?? [],
|
|
94393
|
+
mutationGapEmitted: mutationGapFinding !== null,
|
|
94353
94394
|
membersVoted,
|
|
94354
94395
|
membersAbsent,
|
|
94355
94396
|
quorumSize: membersVoted.length,
|
|
@@ -94359,11 +94400,132 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
94359
94400
|
}, null, 2);
|
|
94360
94401
|
}
|
|
94361
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
|
+
}
|
|
94362
94524
|
// src/tools/suggest-patch.ts
|
|
94363
94525
|
init_zod();
|
|
94364
94526
|
init_path_security();
|
|
94365
94527
|
init_create_tool();
|
|
94366
|
-
import * as
|
|
94528
|
+
import * as fs86 from "node:fs";
|
|
94367
94529
|
import * as path113 from "node:path";
|
|
94368
94530
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
94369
94531
|
function containsWindowsAttacks4(str) {
|
|
@@ -94379,11 +94541,11 @@ function containsWindowsAttacks4(str) {
|
|
|
94379
94541
|
function isPathInWorkspace4(filePath, workspace) {
|
|
94380
94542
|
try {
|
|
94381
94543
|
const resolvedPath = path113.resolve(workspace, filePath);
|
|
94382
|
-
if (!
|
|
94544
|
+
if (!fs86.existsSync(resolvedPath)) {
|
|
94383
94545
|
return true;
|
|
94384
94546
|
}
|
|
94385
|
-
const realWorkspace =
|
|
94386
|
-
const realResolvedPath =
|
|
94547
|
+
const realWorkspace = fs86.realpathSync(workspace);
|
|
94548
|
+
const realResolvedPath = fs86.realpathSync(resolvedPath);
|
|
94387
94549
|
const relativePath = path113.relative(realWorkspace, realResolvedPath);
|
|
94388
94550
|
if (relativePath.startsWith("..") || path113.isAbsolute(relativePath)) {
|
|
94389
94551
|
return false;
|
|
@@ -94557,7 +94719,7 @@ var suggestPatch = createSwarmTool({
|
|
|
94557
94719
|
message: "changes cannot be empty"
|
|
94558
94720
|
}, null, 2);
|
|
94559
94721
|
}
|
|
94560
|
-
if (!
|
|
94722
|
+
if (!fs86.existsSync(directory)) {
|
|
94561
94723
|
return JSON.stringify({
|
|
94562
94724
|
success: false,
|
|
94563
94725
|
error: true,
|
|
@@ -94594,7 +94756,7 @@ var suggestPatch = createSwarmTool({
|
|
|
94594
94756
|
continue;
|
|
94595
94757
|
}
|
|
94596
94758
|
const fullPath = path113.resolve(directory, change.file);
|
|
94597
|
-
if (!
|
|
94759
|
+
if (!fs86.existsSync(fullPath)) {
|
|
94598
94760
|
errors5.push({
|
|
94599
94761
|
success: false,
|
|
94600
94762
|
error: true,
|
|
@@ -94608,7 +94770,7 @@ var suggestPatch = createSwarmTool({
|
|
|
94608
94770
|
}
|
|
94609
94771
|
let content;
|
|
94610
94772
|
try {
|
|
94611
|
-
content =
|
|
94773
|
+
content = fs86.readFileSync(fullPath, "utf-8");
|
|
94612
94774
|
} catch (err3) {
|
|
94613
94775
|
errors5.push({
|
|
94614
94776
|
success: false,
|
|
@@ -94855,7 +95017,7 @@ var generate_mutants = createSwarmTool({
|
|
|
94855
95017
|
// src/tools/lint-spec.ts
|
|
94856
95018
|
init_spec_schema();
|
|
94857
95019
|
init_create_tool();
|
|
94858
|
-
import * as
|
|
95020
|
+
import * as fs87 from "node:fs";
|
|
94859
95021
|
import * as path114 from "node:path";
|
|
94860
95022
|
var SPEC_FILE_NAME = "spec.md";
|
|
94861
95023
|
var SWARM_DIR2 = ".swarm";
|
|
@@ -94910,7 +95072,7 @@ var lint_spec = createSwarmTool({
|
|
|
94910
95072
|
const errors5 = [];
|
|
94911
95073
|
const warnings = [];
|
|
94912
95074
|
const specPath = path114.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
94913
|
-
if (!
|
|
95075
|
+
if (!fs87.existsSync(specPath)) {
|
|
94914
95076
|
const result2 = {
|
|
94915
95077
|
valid: false,
|
|
94916
95078
|
specMtime: null,
|
|
@@ -94929,12 +95091,12 @@ var lint_spec = createSwarmTool({
|
|
|
94929
95091
|
}
|
|
94930
95092
|
let specMtime = null;
|
|
94931
95093
|
try {
|
|
94932
|
-
const stats =
|
|
95094
|
+
const stats = fs87.statSync(specPath);
|
|
94933
95095
|
specMtime = stats.mtime.toISOString();
|
|
94934
95096
|
} catch {}
|
|
94935
95097
|
let content;
|
|
94936
95098
|
try {
|
|
94937
|
-
content =
|
|
95099
|
+
content = fs87.readFileSync(specPath, "utf-8");
|
|
94938
95100
|
} catch (e) {
|
|
94939
95101
|
const result2 = {
|
|
94940
95102
|
valid: false,
|
|
@@ -94979,12 +95141,12 @@ var lint_spec = createSwarmTool({
|
|
|
94979
95141
|
});
|
|
94980
95142
|
// src/tools/mutation-test.ts
|
|
94981
95143
|
init_zod();
|
|
94982
|
-
import * as
|
|
95144
|
+
import * as fs88 from "node:fs";
|
|
94983
95145
|
import * as path116 from "node:path";
|
|
94984
95146
|
|
|
94985
95147
|
// src/mutation/engine.ts
|
|
94986
95148
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
94987
|
-
import { unlinkSync as
|
|
95149
|
+
import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync23 } from "node:fs";
|
|
94988
95150
|
import * as path115 from "node:path";
|
|
94989
95151
|
|
|
94990
95152
|
// src/mutation/equivalence.ts
|
|
@@ -95127,7 +95289,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
95127
95289
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
95128
95290
|
patchFile = path115.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
95129
95291
|
try {
|
|
95130
|
-
|
|
95292
|
+
writeFileSync23(patchFile, patch.patch);
|
|
95131
95293
|
} catch (writeErr) {
|
|
95132
95294
|
error93 = `Failed to write patch file: ${writeErr}`;
|
|
95133
95295
|
outcome = "error";
|
|
@@ -95223,7 +95385,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
95223
95385
|
revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
|
|
95224
95386
|
}
|
|
95225
95387
|
try {
|
|
95226
|
-
|
|
95388
|
+
unlinkSync15(patchFile);
|
|
95227
95389
|
} catch (_unlinkErr) {}
|
|
95228
95390
|
}
|
|
95229
95391
|
}
|
|
@@ -95525,7 +95687,7 @@ var mutation_test = createSwarmTool({
|
|
|
95525
95687
|
for (const filePath of uniquePaths) {
|
|
95526
95688
|
try {
|
|
95527
95689
|
const resolvedPath = path116.resolve(cwd, filePath);
|
|
95528
|
-
sourceFiles.set(filePath,
|
|
95690
|
+
sourceFiles.set(filePath, fs88.readFileSync(resolvedPath, "utf-8"));
|
|
95529
95691
|
} catch {}
|
|
95530
95692
|
}
|
|
95531
95693
|
const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
|
|
@@ -95543,7 +95705,7 @@ var mutation_test = createSwarmTool({
|
|
|
95543
95705
|
init_zod();
|
|
95544
95706
|
init_manager2();
|
|
95545
95707
|
init_detector();
|
|
95546
|
-
import * as
|
|
95708
|
+
import * as fs89 from "node:fs";
|
|
95547
95709
|
import * as path117 from "node:path";
|
|
95548
95710
|
init_create_tool();
|
|
95549
95711
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
@@ -95653,7 +95815,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
95653
95815
|
}
|
|
95654
95816
|
let content;
|
|
95655
95817
|
try {
|
|
95656
|
-
content =
|
|
95818
|
+
content = fs89.readFileSync(fullPath, "utf8");
|
|
95657
95819
|
} catch {
|
|
95658
95820
|
result.skipped_reason = "file_read_error";
|
|
95659
95821
|
skippedCount++;
|
|
@@ -95764,7 +95926,7 @@ init_zod();
|
|
|
95764
95926
|
init_utils();
|
|
95765
95927
|
init_create_tool();
|
|
95766
95928
|
init_path_security();
|
|
95767
|
-
import * as
|
|
95929
|
+
import * as fs90 from "node:fs";
|
|
95768
95930
|
import * as path118 from "node:path";
|
|
95769
95931
|
var MAX_TEXT_LENGTH = 200;
|
|
95770
95932
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
@@ -95855,7 +96017,7 @@ function isSupportedExtension(filePath) {
|
|
|
95855
96017
|
function findSourceFiles3(dir, files = []) {
|
|
95856
96018
|
let entries;
|
|
95857
96019
|
try {
|
|
95858
|
-
entries =
|
|
96020
|
+
entries = fs90.readdirSync(dir);
|
|
95859
96021
|
} catch {
|
|
95860
96022
|
return files;
|
|
95861
96023
|
}
|
|
@@ -95867,7 +96029,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
95867
96029
|
const fullPath = path118.join(dir, entry);
|
|
95868
96030
|
let stat7;
|
|
95869
96031
|
try {
|
|
95870
|
-
stat7 =
|
|
96032
|
+
stat7 = fs90.statSync(fullPath);
|
|
95871
96033
|
} catch {
|
|
95872
96034
|
continue;
|
|
95873
96035
|
}
|
|
@@ -95960,7 +96122,7 @@ var todo_extract = createSwarmTool({
|
|
|
95960
96122
|
return JSON.stringify(errorResult, null, 2);
|
|
95961
96123
|
}
|
|
95962
96124
|
const scanPath = resolvedPath;
|
|
95963
|
-
if (!
|
|
96125
|
+
if (!fs90.existsSync(scanPath)) {
|
|
95964
96126
|
const errorResult = {
|
|
95965
96127
|
error: `path not found: ${pathsInput}`,
|
|
95966
96128
|
total: 0,
|
|
@@ -95970,7 +96132,7 @@ var todo_extract = createSwarmTool({
|
|
|
95970
96132
|
return JSON.stringify(errorResult, null, 2);
|
|
95971
96133
|
}
|
|
95972
96134
|
const filesToScan = [];
|
|
95973
|
-
const stat7 =
|
|
96135
|
+
const stat7 = fs90.statSync(scanPath);
|
|
95974
96136
|
if (stat7.isFile()) {
|
|
95975
96137
|
if (isSupportedExtension(scanPath)) {
|
|
95976
96138
|
filesToScan.push(scanPath);
|
|
@@ -95989,11 +96151,11 @@ var todo_extract = createSwarmTool({
|
|
|
95989
96151
|
const allEntries = [];
|
|
95990
96152
|
for (const filePath of filesToScan) {
|
|
95991
96153
|
try {
|
|
95992
|
-
const fileStat =
|
|
96154
|
+
const fileStat = fs90.statSync(filePath);
|
|
95993
96155
|
if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
|
|
95994
96156
|
continue;
|
|
95995
96157
|
}
|
|
95996
|
-
const content =
|
|
96158
|
+
const content = fs90.readFileSync(filePath, "utf-8");
|
|
95997
96159
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
95998
96160
|
allEntries.push(...entries);
|
|
95999
96161
|
} catch {}
|
|
@@ -96024,17 +96186,17 @@ init_loader();
|
|
|
96024
96186
|
init_schema();
|
|
96025
96187
|
init_qa_gate_profile();
|
|
96026
96188
|
init_gate_evidence();
|
|
96027
|
-
import * as
|
|
96189
|
+
import * as fs93 from "node:fs";
|
|
96028
96190
|
import * as path121 from "node:path";
|
|
96029
96191
|
|
|
96030
96192
|
// src/hooks/diff-scope.ts
|
|
96031
96193
|
init_bun_compat();
|
|
96032
|
-
import * as
|
|
96194
|
+
import * as fs92 from "node:fs";
|
|
96033
96195
|
import * as path120 from "node:path";
|
|
96034
96196
|
|
|
96035
96197
|
// src/utils/gitignore-warning.ts
|
|
96036
96198
|
init_bun_compat();
|
|
96037
|
-
import * as
|
|
96199
|
+
import * as fs91 from "node:fs";
|
|
96038
96200
|
import * as path119 from "node:path";
|
|
96039
96201
|
var _internals36 = { bunSpawn };
|
|
96040
96202
|
var _swarmGitExcludedChecked = false;
|
|
@@ -96112,13 +96274,13 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
96112
96274
|
const excludePath = path119.isAbsolute(excludeRelPath) ? excludeRelPath : path119.join(directory, excludeRelPath);
|
|
96113
96275
|
if (checkIgnoreExitCode !== 0) {
|
|
96114
96276
|
try {
|
|
96115
|
-
|
|
96277
|
+
fs91.mkdirSync(path119.dirname(excludePath), { recursive: true });
|
|
96116
96278
|
let existing = "";
|
|
96117
96279
|
try {
|
|
96118
|
-
existing =
|
|
96280
|
+
existing = fs91.readFileSync(excludePath, "utf8");
|
|
96119
96281
|
} catch {}
|
|
96120
96282
|
if (!fileCoversSwarm(existing)) {
|
|
96121
|
-
|
|
96283
|
+
fs91.appendFileSync(excludePath, `
|
|
96122
96284
|
# opencode-swarm local runtime state
|
|
96123
96285
|
.swarm/
|
|
96124
96286
|
`, "utf8");
|
|
@@ -96157,9 +96319,9 @@ var _internals37 = { bunSpawn };
|
|
|
96157
96319
|
function getDeclaredScope(taskId, directory) {
|
|
96158
96320
|
try {
|
|
96159
96321
|
const planPath = path120.join(directory, ".swarm", "plan.json");
|
|
96160
|
-
if (!
|
|
96322
|
+
if (!fs92.existsSync(planPath))
|
|
96161
96323
|
return null;
|
|
96162
|
-
const raw =
|
|
96324
|
+
const raw = fs92.readFileSync(planPath, "utf-8");
|
|
96163
96325
|
const plan = JSON.parse(raw);
|
|
96164
96326
|
for (const phase of plan.phases ?? []) {
|
|
96165
96327
|
for (const task of phase.tasks ?? []) {
|
|
@@ -96308,7 +96470,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
96308
96470
|
const resolvedDir2 = workingDirectory;
|
|
96309
96471
|
try {
|
|
96310
96472
|
const planPath = path121.join(resolvedDir2, ".swarm", "plan.json");
|
|
96311
|
-
const planRaw =
|
|
96473
|
+
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
96312
96474
|
const plan = JSON.parse(planRaw);
|
|
96313
96475
|
for (const planPhase of plan.phases ?? []) {
|
|
96314
96476
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -96375,7 +96537,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
96375
96537
|
try {
|
|
96376
96538
|
const resolvedDir2 = workingDirectory;
|
|
96377
96539
|
const planPath = path121.join(resolvedDir2, ".swarm", "plan.json");
|
|
96378
|
-
const planRaw =
|
|
96540
|
+
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
96379
96541
|
const plan = JSON.parse(planRaw);
|
|
96380
96542
|
for (const planPhase of plan.phases ?? []) {
|
|
96381
96543
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -96572,9 +96734,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
96572
96734
|
}
|
|
96573
96735
|
const resolvedDir = path121.resolve(normalizedDir);
|
|
96574
96736
|
try {
|
|
96575
|
-
const realPath =
|
|
96737
|
+
const realPath = fs93.realpathSync(resolvedDir);
|
|
96576
96738
|
const planPath = path121.join(realPath, ".swarm", "plan.json");
|
|
96577
|
-
if (!
|
|
96739
|
+
if (!fs93.existsSync(planPath)) {
|
|
96578
96740
|
return {
|
|
96579
96741
|
success: false,
|
|
96580
96742
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -96606,21 +96768,21 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
96606
96768
|
if (args2.status === "in_progress") {
|
|
96607
96769
|
try {
|
|
96608
96770
|
const evidencePath = path121.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
96609
|
-
|
|
96610
|
-
const fd =
|
|
96771
|
+
fs93.mkdirSync(path121.dirname(evidencePath), { recursive: true });
|
|
96772
|
+
const fd = fs93.openSync(evidencePath, "wx");
|
|
96611
96773
|
let writeOk = false;
|
|
96612
96774
|
try {
|
|
96613
|
-
|
|
96775
|
+
fs93.writeSync(fd, JSON.stringify({
|
|
96614
96776
|
taskId: args2.task_id,
|
|
96615
96777
|
required_gates: ["reviewer", "test_engineer"],
|
|
96616
96778
|
gates: {}
|
|
96617
96779
|
}, null, 2));
|
|
96618
96780
|
writeOk = true;
|
|
96619
96781
|
} finally {
|
|
96620
|
-
|
|
96782
|
+
fs93.closeSync(fd);
|
|
96621
96783
|
if (!writeOk) {
|
|
96622
96784
|
try {
|
|
96623
|
-
|
|
96785
|
+
fs93.unlinkSync(evidencePath);
|
|
96624
96786
|
} catch {}
|
|
96625
96787
|
}
|
|
96626
96788
|
}
|
|
@@ -96631,7 +96793,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
96631
96793
|
let phaseRequiresReviewer = true;
|
|
96632
96794
|
try {
|
|
96633
96795
|
const planPath = path121.join(directory, ".swarm", "plan.json");
|
|
96634
|
-
const planRaw =
|
|
96796
|
+
const planRaw = fs93.readFileSync(planPath, "utf-8");
|
|
96635
96797
|
const plan = JSON.parse(planRaw);
|
|
96636
96798
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
96637
96799
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -96941,7 +97103,7 @@ init_utils2();
|
|
|
96941
97103
|
init_ledger();
|
|
96942
97104
|
init_manager();
|
|
96943
97105
|
init_create_tool();
|
|
96944
|
-
import
|
|
97106
|
+
import fs94 from "node:fs";
|
|
96945
97107
|
import path122 from "node:path";
|
|
96946
97108
|
function normalizeVerdict(verdict) {
|
|
96947
97109
|
switch (verdict) {
|
|
@@ -97003,10 +97165,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
97003
97165
|
}
|
|
97004
97166
|
const evidenceDir = path122.dirname(validatedPath);
|
|
97005
97167
|
try {
|
|
97006
|
-
await
|
|
97168
|
+
await fs94.promises.mkdir(evidenceDir, { recursive: true });
|
|
97007
97169
|
const tempPath = path122.join(evidenceDir, `.${filename}.tmp`);
|
|
97008
|
-
await
|
|
97009
|
-
await
|
|
97170
|
+
await fs94.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97171
|
+
await fs94.promises.rename(tempPath, validatedPath);
|
|
97010
97172
|
let snapshotInfo;
|
|
97011
97173
|
let snapshotError;
|
|
97012
97174
|
let qaProfileLocked;
|
|
@@ -97101,7 +97263,7 @@ init_zod();
|
|
|
97101
97263
|
init_utils2();
|
|
97102
97264
|
init_manager();
|
|
97103
97265
|
init_create_tool();
|
|
97104
|
-
import
|
|
97266
|
+
import fs95 from "node:fs";
|
|
97105
97267
|
import path123 from "node:path";
|
|
97106
97268
|
function normalizeVerdict2(verdict) {
|
|
97107
97269
|
switch (verdict) {
|
|
@@ -97166,10 +97328,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
97166
97328
|
}
|
|
97167
97329
|
const evidenceDir = path123.dirname(validatedPath);
|
|
97168
97330
|
try {
|
|
97169
|
-
await
|
|
97331
|
+
await fs95.promises.mkdir(evidenceDir, { recursive: true });
|
|
97170
97332
|
const tempPath = path123.join(evidenceDir, `.${filename}.tmp`);
|
|
97171
|
-
await
|
|
97172
|
-
await
|
|
97333
|
+
await fs95.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97334
|
+
await fs95.promises.rename(tempPath, validatedPath);
|
|
97173
97335
|
return JSON.stringify({
|
|
97174
97336
|
success: true,
|
|
97175
97337
|
phase,
|
|
@@ -97213,7 +97375,7 @@ var write_final_council_evidence = createSwarmTool({
|
|
|
97213
97375
|
init_zod();
|
|
97214
97376
|
init_utils2();
|
|
97215
97377
|
init_create_tool();
|
|
97216
|
-
import
|
|
97378
|
+
import fs96 from "node:fs";
|
|
97217
97379
|
import path124 from "node:path";
|
|
97218
97380
|
function normalizeVerdict3(verdict) {
|
|
97219
97381
|
switch (verdict) {
|
|
@@ -97275,10 +97437,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
97275
97437
|
}
|
|
97276
97438
|
const evidenceDir = path124.dirname(validatedPath);
|
|
97277
97439
|
try {
|
|
97278
|
-
await
|
|
97440
|
+
await fs96.promises.mkdir(evidenceDir, { recursive: true });
|
|
97279
97441
|
const tempPath = path124.join(evidenceDir, `.${filename}.tmp`);
|
|
97280
|
-
await
|
|
97281
|
-
await
|
|
97442
|
+
await fs96.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97443
|
+
await fs96.promises.rename(tempPath, validatedPath);
|
|
97282
97444
|
return JSON.stringify({
|
|
97283
97445
|
success: true,
|
|
97284
97446
|
phase,
|
|
@@ -97324,7 +97486,7 @@ var write_hallucination_evidence = createSwarmTool({
|
|
|
97324
97486
|
init_zod();
|
|
97325
97487
|
init_utils2();
|
|
97326
97488
|
init_create_tool();
|
|
97327
|
-
import
|
|
97489
|
+
import fs97 from "node:fs";
|
|
97328
97490
|
import path125 from "node:path";
|
|
97329
97491
|
function normalizeVerdict4(verdict) {
|
|
97330
97492
|
switch (verdict) {
|
|
@@ -97412,10 +97574,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
97412
97574
|
}
|
|
97413
97575
|
const evidenceDir = path125.dirname(validatedPath);
|
|
97414
97576
|
try {
|
|
97415
|
-
await
|
|
97577
|
+
await fs97.promises.mkdir(evidenceDir, { recursive: true });
|
|
97416
97578
|
const tempPath = path125.join(evidenceDir, `.${filename}.tmp`);
|
|
97417
|
-
await
|
|
97418
|
-
await
|
|
97579
|
+
await fs97.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
97580
|
+
await fs97.promises.rename(tempPath, validatedPath);
|
|
97419
97581
|
return JSON.stringify({
|
|
97420
97582
|
success: true,
|
|
97421
97583
|
phase,
|
|
@@ -97901,15 +98063,19 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
97901
98063
|
...opencodeConfig.command || {},
|
|
97902
98064
|
swarm: {
|
|
97903
98065
|
template: "/swarm $ARGUMENTS",
|
|
97904
|
-
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]"
|
|
97905
98067
|
},
|
|
97906
98068
|
"swarm-status": {
|
|
97907
98069
|
template: "/swarm status",
|
|
97908
98070
|
description: "Use /swarm status to show current swarm status and active phase"
|
|
97909
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
|
+
},
|
|
97910
98076
|
"swarm-plan": {
|
|
97911
98077
|
template: "/swarm plan $ARGUMENTS",
|
|
97912
|
-
description: "
|
|
98078
|
+
description: "Deprecated alias for /swarm show-plan"
|
|
97913
98079
|
},
|
|
97914
98080
|
"swarm-agents": {
|
|
97915
98081
|
template: "/swarm agents",
|
|
@@ -97989,7 +98155,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
97989
98155
|
},
|
|
97990
98156
|
"swarm-council": {
|
|
97991
98157
|
template: "/swarm council $ARGUMENTS",
|
|
97992
|
-
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]"
|
|
97993
98159
|
},
|
|
97994
98160
|
"swarm-pr-review": {
|
|
97995
98161
|
template: "/swarm pr-review $ARGUMENTS",
|
|
@@ -98051,9 +98217,13 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
98051
98217
|
template: "/swarm evidence summary",
|
|
98052
98218
|
description: "Use /swarm evidence summary to generate evidence summaries"
|
|
98053
98219
|
},
|
|
98220
|
+
"swarm-finalize": {
|
|
98221
|
+
template: "/swarm finalize",
|
|
98222
|
+
description: "Use /swarm finalize to archive the swarm project and close active state"
|
|
98223
|
+
},
|
|
98054
98224
|
"swarm-close": {
|
|
98055
98225
|
template: "/swarm close",
|
|
98056
|
-
description: "
|
|
98226
|
+
description: "Deprecated alias for /swarm finalize"
|
|
98057
98227
|
},
|
|
98058
98228
|
"swarm-acknowledge-spec-drift": {
|
|
98059
98229
|
template: "/swarm acknowledge-spec-drift",
|