opencode-swarm 6.30.2 → 6.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +25 -12
- package/dist/config/schema.d.ts +22 -0
- package/dist/hooks/curator-drift-advisory.test.d.ts +1 -0
- package/dist/hooks/curator-drift.d.ts +1 -1
- package/dist/hooks/delegation-ledger.d.ts +37 -0
- package/dist/hooks/delegation-ledger.test.d.ts +11 -0
- package/dist/hooks/scope-guard-throw-behavior.test.d.ts +15 -0
- package/dist/hooks/scope-guard.adversarial.test.d.ts +1 -0
- package/dist/hooks/scope-guard.d.ts +43 -0
- package/dist/hooks/scope-guard.test.d.ts +14 -0
- package/dist/hooks/self-review.d.ts +14 -0
- package/dist/hooks/self-review.test.d.ts +14 -0
- package/dist/hooks/slop-detector.adversarial.test.d.ts +1 -0
- package/dist/hooks/watchdog.integration.test.d.ts +9 -0
- package/dist/index.js +918 -236
- package/dist/tools/curator-analyze.d.ts +7 -0
- package/dist/tools/curator-analyze.test.d.ts +1 -0
- package/dist/tools/diff.d.ts +2 -2
- package/dist/tools/gitingest.d.ts +2 -2
- package/dist/tools/imports.d.ts +2 -2
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/knowledge-add.d.ts +2 -0
- package/dist/tools/knowledge-recall.d.ts +2 -0
- package/dist/tools/knowledge-remove.d.ts +2 -0
- package/dist/tools/knowledge-tools.integration.test.d.ts +1 -0
- package/dist/tools/lint.d.ts +1 -1
- package/dist/tools/phase-complete.d.ts +1 -1
- package/dist/tools/pre-check-batch.d.ts +1 -1
- package/dist/tools/retrieve-summary.d.ts +2 -2
- package/dist/tools/secretscan.d.ts +2 -2
- package/dist/tools/test-runner.d.ts +1 -1
- package/dist/tools/update-task-status.adversarial.test.d.ts +13 -0
- package/dist/tools/update-task-status.test.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14437,7 +14437,7 @@ function resolveGuardrailsConfig(config2, agentName) {
|
|
|
14437
14437
|
};
|
|
14438
14438
|
return resolved;
|
|
14439
14439
|
}
|
|
14440
|
-
var KNOWN_SWARM_PREFIXES, SEPARATORS, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, CuratorConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PluginConfigSchema;
|
|
14440
|
+
var KNOWN_SWARM_PREFIXES, SEPARATORS, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, CuratorConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PluginConfigSchema;
|
|
14441
14441
|
var init_schema = __esm(() => {
|
|
14442
14442
|
init_zod();
|
|
14443
14443
|
init_constants();
|
|
@@ -14807,6 +14807,15 @@ var init_schema = __esm(() => {
|
|
|
14807
14807
|
}).optional(),
|
|
14808
14808
|
profiles: exports_external.record(exports_external.string(), GuardrailsProfileSchema).optional()
|
|
14809
14809
|
});
|
|
14810
|
+
WatchdogConfigSchema = exports_external.object({
|
|
14811
|
+
scope_guard: exports_external.boolean().default(true),
|
|
14812
|
+
skip_in_turbo: exports_external.boolean().default(false),
|
|
14813
|
+
delegation_ledger: exports_external.boolean().default(true)
|
|
14814
|
+
});
|
|
14815
|
+
SelfReviewConfigSchema = exports_external.object({
|
|
14816
|
+
enabled: exports_external.boolean().default(true),
|
|
14817
|
+
skip_in_turbo: exports_external.boolean().default(true)
|
|
14818
|
+
});
|
|
14810
14819
|
ToolFilterConfigSchema = exports_external.object({
|
|
14811
14820
|
enabled: exports_external.boolean().default(true),
|
|
14812
14821
|
overrides: exports_external.record(exports_external.string(), exports_external.array(exports_external.string())).default({})
|
|
@@ -14878,7 +14887,8 @@ var init_schema = __esm(() => {
|
|
|
14878
14887
|
enabled: exports_external.boolean().default(true),
|
|
14879
14888
|
classThreshold: exports_external.number().int().min(1).default(3),
|
|
14880
14889
|
commentStripThreshold: exports_external.number().int().min(1).default(5),
|
|
14881
|
-
diffLineThreshold: exports_external.number().int().min(10).default(200)
|
|
14890
|
+
diffLineThreshold: exports_external.number().int().min(10).default(200),
|
|
14891
|
+
importHygieneThreshold: exports_external.number().int().min(1).default(2)
|
|
14882
14892
|
});
|
|
14883
14893
|
IncrementalVerifyConfigSchema = exports_external.object({
|
|
14884
14894
|
enabled: exports_external.boolean().default(true),
|
|
@@ -14905,6 +14915,8 @@ var init_schema = __esm(() => {
|
|
|
14905
14915
|
gates: GateConfigSchema.optional(),
|
|
14906
14916
|
context_budget: ContextBudgetConfigSchema.optional(),
|
|
14907
14917
|
guardrails: GuardrailsConfigSchema.optional(),
|
|
14918
|
+
watchdog: WatchdogConfigSchema.optional(),
|
|
14919
|
+
self_review: SelfReviewConfigSchema.optional(),
|
|
14908
14920
|
tool_filter: ToolFilterConfigSchema.optional(),
|
|
14909
14921
|
plan_cursor: PlanCursorConfigSchema.optional(),
|
|
14910
14922
|
evidence: EvidenceConfigSchema.optional(),
|
|
@@ -33414,14 +33426,14 @@ function detectAdditionalLinter(cwd) {
|
|
|
33414
33426
|
return null;
|
|
33415
33427
|
}
|
|
33416
33428
|
async function detectAvailableLinter(directory) {
|
|
33417
|
-
const
|
|
33418
|
-
const projectDir = directory
|
|
33429
|
+
const _DETECT_TIMEOUT = 2000;
|
|
33430
|
+
const projectDir = directory || process.cwd();
|
|
33419
33431
|
const isWindows = process.platform === "win32";
|
|
33420
33432
|
const biomeBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "biome.EXE") : path22.join(projectDir, "node_modules", ".bin", "biome");
|
|
33421
33433
|
const eslintBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path22.join(projectDir, "node_modules", ".bin", "eslint");
|
|
33422
33434
|
return _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
33423
33435
|
}
|
|
33424
|
-
async function _detectAvailableLinter(
|
|
33436
|
+
async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
33425
33437
|
const DETECT_TIMEOUT = 2000;
|
|
33426
33438
|
try {
|
|
33427
33439
|
const biomeProc = Bun.spawn(["npx", "biome", "--version"], {
|
|
@@ -33962,6 +33974,7 @@ async function runSecretscan(directory) {
|
|
|
33962
33974
|
var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan;
|
|
33963
33975
|
var init_secretscan = __esm(() => {
|
|
33964
33976
|
init_dist();
|
|
33977
|
+
init_create_tool();
|
|
33965
33978
|
MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
33966
33979
|
MAX_CONTENT_BYTES = 50 * 1024;
|
|
33967
33980
|
BINARY_SIGNATURES = [
|
|
@@ -34134,19 +34147,20 @@ var init_secretscan = __esm(() => {
|
|
|
34134
34147
|
}
|
|
34135
34148
|
];
|
|
34136
34149
|
O_NOFOLLOW = process.platform !== "win32" ? fs11.constants.O_NOFOLLOW : undefined;
|
|
34137
|
-
secretscan =
|
|
34150
|
+
secretscan = createSwarmTool({
|
|
34138
34151
|
description: "Scan directory for potential secrets (API keys, tokens, passwords) using regex patterns and entropy heuristics. Returns metadata-only findings with redacted previews - NEVER returns raw secrets. Excludes common directories (node_modules, .git, dist, etc.) by default. Supports glob patterns (e.g. **/.svelte-kit/**, **/*.test.ts) and reads .secretscanignore at the scan root.",
|
|
34139
34152
|
args: {
|
|
34140
34153
|
directory: tool.schema.string().describe('Directory to scan for secrets (e.g., "." or "./src")'),
|
|
34141
34154
|
exclude: tool.schema.array(tool.schema.string()).optional().describe("Patterns to exclude: plain directory names (e.g. node_modules), relative paths, or globs (e.g. **/.svelte-kit/**, **/*.test.ts). Added to default exclusions.")
|
|
34142
34155
|
},
|
|
34143
|
-
async execute(args2,
|
|
34156
|
+
async execute(args2, _directory, _ctx) {
|
|
34157
|
+
const typedArgs = args2;
|
|
34144
34158
|
let directory;
|
|
34145
34159
|
let exclude;
|
|
34146
34160
|
try {
|
|
34147
|
-
if (
|
|
34148
|
-
directory =
|
|
34149
|
-
exclude =
|
|
34161
|
+
if (typedArgs && typeof typedArgs === "object") {
|
|
34162
|
+
directory = typedArgs.directory;
|
|
34163
|
+
exclude = typedArgs.exclude;
|
|
34150
34164
|
}
|
|
34151
34165
|
} catch {}
|
|
34152
34166
|
if (directory === undefined) {
|
|
@@ -35001,7 +35015,7 @@ function parseTestOutput(framework, output) {
|
|
|
35001
35015
|
return { totals, coveragePercent };
|
|
35002
35016
|
}
|
|
35003
35017
|
async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
35004
|
-
const command = buildTestCommand(framework, scope, files, coverage, cwd
|
|
35018
|
+
const command = buildTestCommand(framework, scope, files, coverage, cwd);
|
|
35005
35019
|
if (!command) {
|
|
35006
35020
|
return {
|
|
35007
35021
|
success: false,
|
|
@@ -35026,7 +35040,7 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
35026
35040
|
const proc = Bun.spawn(command, {
|
|
35027
35041
|
stdout: "pipe",
|
|
35028
35042
|
stderr: "pipe",
|
|
35029
|
-
cwd
|
|
35043
|
+
cwd
|
|
35030
35044
|
});
|
|
35031
35045
|
const exitPromise = proc.exited;
|
|
35032
35046
|
const timeoutPromise = new Promise((resolve8) => setTimeout(() => {
|
|
@@ -35558,7 +35572,7 @@ async function runLintCheck(dir, linter, timeoutMs) {
|
|
|
35558
35572
|
async function runTestsCheck(_dir, scope, timeoutMs) {
|
|
35559
35573
|
const startTime = Date.now();
|
|
35560
35574
|
try {
|
|
35561
|
-
const result = await runTests("none", scope, [], false, timeoutMs);
|
|
35575
|
+
const result = await runTests("none", scope, [], false, timeoutMs, _dir);
|
|
35562
35576
|
if (!result.success) {
|
|
35563
35577
|
return {
|
|
35564
35578
|
type: "tests",
|
|
@@ -37581,8 +37595,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37581
37595
|
var moduleRtn;
|
|
37582
37596
|
var Module = moduleArg;
|
|
37583
37597
|
var readyPromiseResolve, readyPromiseReject;
|
|
37584
|
-
var readyPromise = new Promise((
|
|
37585
|
-
readyPromiseResolve =
|
|
37598
|
+
var readyPromise = new Promise((resolve16, reject) => {
|
|
37599
|
+
readyPromiseResolve = resolve16;
|
|
37586
37600
|
readyPromiseReject = reject;
|
|
37587
37601
|
});
|
|
37588
37602
|
var ENVIRONMENT_IS_WEB = typeof window == "object";
|
|
@@ -37604,11 +37618,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37604
37618
|
throw toThrow;
|
|
37605
37619
|
}, "quit_");
|
|
37606
37620
|
var scriptDirectory = "";
|
|
37607
|
-
function locateFile(
|
|
37621
|
+
function locateFile(path47) {
|
|
37608
37622
|
if (Module["locateFile"]) {
|
|
37609
|
-
return Module["locateFile"](
|
|
37623
|
+
return Module["locateFile"](path47, scriptDirectory);
|
|
37610
37624
|
}
|
|
37611
|
-
return scriptDirectory +
|
|
37625
|
+
return scriptDirectory + path47;
|
|
37612
37626
|
}
|
|
37613
37627
|
__name(locateFile, "locateFile");
|
|
37614
37628
|
var readAsync, readBinary;
|
|
@@ -37662,13 +37676,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37662
37676
|
}
|
|
37663
37677
|
readAsync = /* @__PURE__ */ __name(async (url3) => {
|
|
37664
37678
|
if (isFileURI(url3)) {
|
|
37665
|
-
return new Promise((
|
|
37679
|
+
return new Promise((resolve16, reject) => {
|
|
37666
37680
|
var xhr = new XMLHttpRequest;
|
|
37667
37681
|
xhr.open("GET", url3, true);
|
|
37668
37682
|
xhr.responseType = "arraybuffer";
|
|
37669
37683
|
xhr.onload = () => {
|
|
37670
37684
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
37671
|
-
|
|
37685
|
+
resolve16(xhr.response);
|
|
37672
37686
|
return;
|
|
37673
37687
|
}
|
|
37674
37688
|
reject(xhr.status);
|
|
@@ -37888,10 +37902,10 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37888
37902
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
37889
37903
|
var info2 = getWasmImports();
|
|
37890
37904
|
if (Module["instantiateWasm"]) {
|
|
37891
|
-
return new Promise((
|
|
37905
|
+
return new Promise((resolve16, reject) => {
|
|
37892
37906
|
Module["instantiateWasm"](info2, (mod, inst) => {
|
|
37893
37907
|
receiveInstance(mod, inst);
|
|
37894
|
-
|
|
37908
|
+
resolve16(mod.exports);
|
|
37895
37909
|
});
|
|
37896
37910
|
});
|
|
37897
37911
|
}
|
|
@@ -39356,7 +39370,7 @@ var init_runtime = __esm(() => {
|
|
|
39356
39370
|
});
|
|
39357
39371
|
|
|
39358
39372
|
// src/index.ts
|
|
39359
|
-
import * as
|
|
39373
|
+
import * as path57 from "path";
|
|
39360
39374
|
|
|
39361
39375
|
// src/agents/index.ts
|
|
39362
39376
|
init_config();
|
|
@@ -39664,8 +39678,6 @@ function planStatusToWorkflowState(status) {
|
|
|
39664
39678
|
return "coder_delegated";
|
|
39665
39679
|
case "completed":
|
|
39666
39680
|
return "complete";
|
|
39667
|
-
case "pending":
|
|
39668
|
-
case "blocked":
|
|
39669
39681
|
default:
|
|
39670
39682
|
return "idle";
|
|
39671
39683
|
}
|
|
@@ -39679,10 +39691,10 @@ function evidenceToWorkflowState(evidence) {
|
|
|
39679
39691
|
return "complete";
|
|
39680
39692
|
}
|
|
39681
39693
|
}
|
|
39682
|
-
if (gates
|
|
39694
|
+
if (gates.test_engineer != null) {
|
|
39683
39695
|
return "tests_run";
|
|
39684
39696
|
}
|
|
39685
|
-
if (gates
|
|
39697
|
+
if (gates.reviewer != null) {
|
|
39686
39698
|
return "reviewer_run";
|
|
39687
39699
|
}
|
|
39688
39700
|
if (Object.keys(gates).length > 0) {
|
|
@@ -42765,7 +42777,10 @@ class PlanSyncWorker {
|
|
|
42765
42777
|
lastStat = null;
|
|
42766
42778
|
disposed = false;
|
|
42767
42779
|
constructor(options = {}) {
|
|
42768
|
-
|
|
42780
|
+
if (!options.directory) {
|
|
42781
|
+
console.warn("[plan-sync-worker] No directory provided, falling back to process.cwd()");
|
|
42782
|
+
}
|
|
42783
|
+
this.directory = options.directory || process.cwd();
|
|
42769
42784
|
this.debounceMs = options.debounceMs ?? 300;
|
|
42770
42785
|
this.pollIntervalMs = options.pollIntervalMs ?? 2000;
|
|
42771
42786
|
this.syncTimeoutMs = options.syncTimeoutMs ?? 30000;
|
|
@@ -49210,6 +49225,7 @@ function createCompactionCustomizerHook(config3, directory) {
|
|
|
49210
49225
|
output.context.push(`[SWARM PATTERNS] ${patterns}`);
|
|
49211
49226
|
}
|
|
49212
49227
|
}
|
|
49228
|
+
output.context.push("[KNOWLEDGE TOOLS] You have persistent knowledge tools: knowledge_recall (search for relevant past decisions), knowledge_add (store a new lesson), knowledge_remove (delete outdated entries). Use knowledge_recall when past context would help.");
|
|
49213
49229
|
})
|
|
49214
49230
|
};
|
|
49215
49231
|
}
|
|
@@ -49870,10 +49886,11 @@ function createGuardrailsHooks(directoryOrConfig, config3) {
|
|
|
49870
49886
|
let directory;
|
|
49871
49887
|
let guardrailsConfig;
|
|
49872
49888
|
if (directoryOrConfig && typeof directoryOrConfig === "object" && "enabled" in directoryOrConfig) {
|
|
49889
|
+
console.warn("[guardrails] Legacy call without directory, falling back to process.cwd()");
|
|
49873
49890
|
directory = process.cwd();
|
|
49874
49891
|
guardrailsConfig = directoryOrConfig;
|
|
49875
49892
|
} else {
|
|
49876
|
-
directory = directoryOrConfig
|
|
49893
|
+
directory = directoryOrConfig || process.cwd();
|
|
49877
49894
|
guardrailsConfig = config3;
|
|
49878
49895
|
}
|
|
49879
49896
|
if (guardrailsConfig?.enabled === false) {
|
|
@@ -49925,9 +49942,27 @@ function createGuardrailsHooks(directoryOrConfig, config3) {
|
|
|
49925
49942
|
const agentName2 = typeof loopArgs?.subagent_type === "string" ? loopArgs.subagent_type : "agent";
|
|
49926
49943
|
const loopSession = swarmState.agentSessions.get(input.sessionID);
|
|
49927
49944
|
if (loopSession) {
|
|
49945
|
+
const loopPattern = loopResult.pattern;
|
|
49946
|
+
const modifiedFiles = loopSession.modifiedFilesThisCoderTask ?? [];
|
|
49947
|
+
const accomplishmentSummary = modifiedFiles.length > 0 ? `Modified ${modifiedFiles.length} file(s): ${modifiedFiles.slice(0, 3).join(", ")}${modifiedFiles.length > 3 ? "..." : ""}` : "No files modified yet";
|
|
49948
|
+
const alternativeSuggestions = {
|
|
49949
|
+
coder: "Try a different task spec, simplify the constraint, or escalate to user",
|
|
49950
|
+
reviewer: "Try a different review dimension or escalate to user",
|
|
49951
|
+
test_engineer: "Run a specific test file with targeted scope",
|
|
49952
|
+
explorer: "Narrow the search scope or check a specific file directly"
|
|
49953
|
+
};
|
|
49954
|
+
const cleanAgent = stripKnownSwarmPrefix(agentName2).toLowerCase();
|
|
49955
|
+
const suggestion = alternativeSuggestions[cleanAgent] ?? "Try a different agent, different instructions, or escalate to the user";
|
|
49928
49956
|
loopSession.loopWarningPending = {
|
|
49929
49957
|
agent: agentName2,
|
|
49930
|
-
message:
|
|
49958
|
+
message: [
|
|
49959
|
+
`LOOP DETECTED: Pattern "${loopPattern}" repeated 3 times.`,
|
|
49960
|
+
`Agent: ${agentName2}`,
|
|
49961
|
+
`Accomplished: ${accomplishmentSummary}`,
|
|
49962
|
+
`Suggested action: ${suggestion}`,
|
|
49963
|
+
`If still stuck after trying alternatives, escalate to the user.`
|
|
49964
|
+
].join(`
|
|
49965
|
+
`),
|
|
49931
49966
|
timestamp: Date.now()
|
|
49932
49967
|
};
|
|
49933
49968
|
}
|
|
@@ -50326,7 +50361,7 @@ ${pending.message}
|
|
|
50326
50361
|
${joined}
|
|
50327
50362
|
[/ADVISORIES]
|
|
50328
50363
|
|
|
50329
|
-
|
|
50364
|
+
${textPart2.text}`;
|
|
50330
50365
|
}
|
|
50331
50366
|
session.pendingAdvisoryMessages = [];
|
|
50332
50367
|
} else if (!isArchitectSession && session && (session.pendingAdvisoryMessages?.length ?? 0) > 0) {
|
|
@@ -51346,7 +51381,7 @@ function createPipelineTrackerHook(config3, directory) {
|
|
|
51346
51381
|
return;
|
|
51347
51382
|
let phaseNumber = null;
|
|
51348
51383
|
try {
|
|
51349
|
-
const plan = await loadPlan(directory
|
|
51384
|
+
const plan = await loadPlan(directory || process.cwd());
|
|
51350
51385
|
if (plan) {
|
|
51351
51386
|
const phaseString = extractCurrentPhaseFromPlan2(plan);
|
|
51352
51387
|
phaseNumber = parsePhaseNumber(phaseString);
|
|
@@ -52993,6 +53028,97 @@ function createDarkMatterDetectorHook(directory) {
|
|
|
52993
53028
|
return safeHook(hook);
|
|
52994
53029
|
}
|
|
52995
53030
|
|
|
53031
|
+
// src/hooks/delegation-ledger.ts
|
|
53032
|
+
var ledgerBySession = new Map;
|
|
53033
|
+
var callStartTimes = new Map;
|
|
53034
|
+
function createDelegationLedgerHook(config3, _directory, injectAdvisory) {
|
|
53035
|
+
const enabled = config3.enabled ?? true;
|
|
53036
|
+
return {
|
|
53037
|
+
toolAfter: async (input, output) => {
|
|
53038
|
+
if (!enabled)
|
|
53039
|
+
return;
|
|
53040
|
+
const sessionId = input.sessionID;
|
|
53041
|
+
const startKey = `${sessionId}:${input.callID}`;
|
|
53042
|
+
const startTime = callStartTimes.get(startKey) ?? Date.now();
|
|
53043
|
+
callStartTimes.delete(startKey);
|
|
53044
|
+
const duration_ms = Date.now() - startTime;
|
|
53045
|
+
const args2 = input.args ?? {};
|
|
53046
|
+
const file3 = typeof args2.path === "string" ? args2.path : typeof args2.filePath === "string" ? args2.filePath : typeof args2.file === "string" ? args2.file : undefined;
|
|
53047
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
53048
|
+
const agentName = swarmState.activeAgent?.get(sessionId) ?? session?.agentName ?? "unknown";
|
|
53049
|
+
const outputStr = String(output.output ?? "");
|
|
53050
|
+
const success3 = !outputStr.startsWith("Error:") && !outputStr.startsWith("error: ");
|
|
53051
|
+
const entry = {
|
|
53052
|
+
agent: agentName,
|
|
53053
|
+
tool: input.tool,
|
|
53054
|
+
file: file3,
|
|
53055
|
+
duration_ms,
|
|
53056
|
+
success: success3,
|
|
53057
|
+
timestamp: Date.now()
|
|
53058
|
+
};
|
|
53059
|
+
const existing = ledgerBySession.get(sessionId) ?? [];
|
|
53060
|
+
existing.push(entry);
|
|
53061
|
+
ledgerBySession.set(sessionId, existing);
|
|
53062
|
+
},
|
|
53063
|
+
onArchitectResume: (architectSessionId) => {
|
|
53064
|
+
if (!enabled)
|
|
53065
|
+
return;
|
|
53066
|
+
const allEntries = [];
|
|
53067
|
+
for (const [sessionId, entries] of ledgerBySession) {
|
|
53068
|
+
if (sessionId === architectSessionId)
|
|
53069
|
+
continue;
|
|
53070
|
+
allEntries.push(...entries);
|
|
53071
|
+
}
|
|
53072
|
+
if (allEntries.length === 0)
|
|
53073
|
+
return;
|
|
53074
|
+
for (const sessionId of ledgerBySession.keys()) {
|
|
53075
|
+
if (sessionId !== architectSessionId) {
|
|
53076
|
+
ledgerBySession.delete(sessionId);
|
|
53077
|
+
}
|
|
53078
|
+
}
|
|
53079
|
+
const toolCallCount = allEntries.length;
|
|
53080
|
+
const filesModified = [
|
|
53081
|
+
...new Set(allEntries.filter((e) => isWriteTool2(e.tool) && e.file).map((e) => e.file))
|
|
53082
|
+
];
|
|
53083
|
+
const filesRead = [
|
|
53084
|
+
...new Set(allEntries.filter((e) => isReadTool(e.tool) && e.file).map((e) => e.file))
|
|
53085
|
+
];
|
|
53086
|
+
const failedCalls = allEntries.filter((e) => !e.success).length;
|
|
53087
|
+
const scopeViolations = allEntries.filter((e) => e.tool.includes("scope")).length;
|
|
53088
|
+
const summary = [
|
|
53089
|
+
`DELEGATION SUMMARY:`,
|
|
53090
|
+
` Tool calls: ${toolCallCount}${failedCalls > 0 ? ` (${failedCalls} failed)` : ""}`,
|
|
53091
|
+
filesModified.length > 0 ? ` Files modified: ${filesModified.slice(0, 5).join(", ")}${filesModified.length > 5 ? ` (+${filesModified.length - 5} more)` : ""}` : null,
|
|
53092
|
+
filesRead.length > 0 ? ` Files read: ${filesRead.slice(0, 5).join(", ")}${filesRead.length > 5 ? ` (+${filesRead.length - 5} more)` : ""}` : null,
|
|
53093
|
+
scopeViolations > 0 ? ` \u26A0\uFE0F ${scopeViolations} scope violation(s) detected` : null
|
|
53094
|
+
].filter(Boolean).join(`
|
|
53095
|
+
`);
|
|
53096
|
+
try {
|
|
53097
|
+
injectAdvisory(architectSessionId, summary);
|
|
53098
|
+
} catch {}
|
|
53099
|
+
}
|
|
53100
|
+
};
|
|
53101
|
+
}
|
|
53102
|
+
var WRITE_TOOL_PATTERNS = [
|
|
53103
|
+
"write",
|
|
53104
|
+
"edit",
|
|
53105
|
+
"patch",
|
|
53106
|
+
"create",
|
|
53107
|
+
"insert",
|
|
53108
|
+
"replace",
|
|
53109
|
+
"append",
|
|
53110
|
+
"prepend"
|
|
53111
|
+
];
|
|
53112
|
+
function isWriteTool2(toolName) {
|
|
53113
|
+
const normalized = toolName.replace(/^[^:]+[:.]/, "").toLowerCase();
|
|
53114
|
+
return WRITE_TOOL_PATTERNS.some((p) => normalized.includes(p));
|
|
53115
|
+
}
|
|
53116
|
+
var READ_TOOL_PATTERNS = ["read", "cat", "view", "fetch", "get"];
|
|
53117
|
+
function isReadTool(toolName) {
|
|
53118
|
+
const normalized = toolName.replace(/^[^:]+[:.]/, "").toLowerCase();
|
|
53119
|
+
return READ_TOOL_PATTERNS.some((p) => normalized.includes(p));
|
|
53120
|
+
}
|
|
53121
|
+
|
|
52996
53122
|
// src/hooks/incremental-verify.ts
|
|
52997
53123
|
import * as fs21 from "fs";
|
|
52998
53124
|
import * as path34 from "path";
|
|
@@ -53851,7 +53977,7 @@ async function writeDriftReport(directory, report) {
|
|
|
53851
53977
|
}
|
|
53852
53978
|
return filePath;
|
|
53853
53979
|
}
|
|
53854
|
-
async function runCriticDriftCheck(directory, phase, curatorResult, config3) {
|
|
53980
|
+
async function runCriticDriftCheck(directory, phase, curatorResult, config3, injectAdvisory) {
|
|
53855
53981
|
try {
|
|
53856
53982
|
const planMd = await readSwarmFileAsync(directory, "plan.md");
|
|
53857
53983
|
const specMd = await readSwarmFileAsync(directory, "spec.md");
|
|
@@ -53911,6 +54037,12 @@ async function runCriticDriftCheck(directory, phase, curatorResult, config3) {
|
|
|
53911
54037
|
drift_score: driftScore,
|
|
53912
54038
|
report_path: reportPath
|
|
53913
54039
|
});
|
|
54040
|
+
if (injectAdvisory && alignment !== "ALIGNED" && driftScore > 0) {
|
|
54041
|
+
try {
|
|
54042
|
+
const advisoryText = `CURATOR DRIFT DETECTED (phase ${phase}, score ${driftScore.toFixed(2)}): ${injectionSummary.slice(0, 300)}. Review .swarm/${DRIFT_REPORT_PREFIX}${phase}.json and address spec alignment before proceeding.`;
|
|
54043
|
+
injectAdvisory(advisoryText);
|
|
54044
|
+
} catch {}
|
|
54045
|
+
}
|
|
53914
54046
|
const injectionText = injectionSummary;
|
|
53915
54047
|
return {
|
|
53916
54048
|
phase,
|
|
@@ -54110,9 +54242,127 @@ ${injectionText}`;
|
|
|
54110
54242
|
});
|
|
54111
54243
|
}
|
|
54112
54244
|
|
|
54245
|
+
// src/hooks/scope-guard.ts
|
|
54246
|
+
init_constants();
|
|
54247
|
+
init_schema();
|
|
54248
|
+
import * as path37 from "path";
|
|
54249
|
+
var WRITE_TOOLS = new Set([
|
|
54250
|
+
"write",
|
|
54251
|
+
"edit",
|
|
54252
|
+
"patch",
|
|
54253
|
+
"apply_patch",
|
|
54254
|
+
"create_file",
|
|
54255
|
+
"insert",
|
|
54256
|
+
"replace",
|
|
54257
|
+
"append",
|
|
54258
|
+
"prepend"
|
|
54259
|
+
]);
|
|
54260
|
+
function createScopeGuardHook(config3, _directory, injectAdvisory) {
|
|
54261
|
+
const enabled = config3.enabled ?? true;
|
|
54262
|
+
const _skipInTurbo = config3.skip_in_turbo ?? false;
|
|
54263
|
+
return {
|
|
54264
|
+
toolBefore: async (input, output) => {
|
|
54265
|
+
if (!enabled)
|
|
54266
|
+
return;
|
|
54267
|
+
const toolName = input.tool.replace(/^[^:]+[:.]/, "");
|
|
54268
|
+
if (!WRITE_TOOLS.has(toolName))
|
|
54269
|
+
return;
|
|
54270
|
+
const sessionId = input.sessionID;
|
|
54271
|
+
const activeAgent = swarmState.activeAgent.get(sessionId);
|
|
54272
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
54273
|
+
const agentName = activeAgent ?? session?.agentName ?? "unknown";
|
|
54274
|
+
const isArchitect2 = stripKnownSwarmPrefix(agentName) === ORCHESTRATOR_NAME;
|
|
54275
|
+
if (isArchitect2)
|
|
54276
|
+
return;
|
|
54277
|
+
const declaredScope = session?.declaredCoderScope;
|
|
54278
|
+
if (!declaredScope || declaredScope.length === 0)
|
|
54279
|
+
return;
|
|
54280
|
+
const argsObj = output.args;
|
|
54281
|
+
const rawFilePath = argsObj?.path ?? argsObj?.filePath ?? argsObj?.file;
|
|
54282
|
+
if (typeof rawFilePath !== "string" || !rawFilePath)
|
|
54283
|
+
return;
|
|
54284
|
+
const filePath = rawFilePath.replace(/[\r\n\t]/g, "_").split(String.fromCharCode(27)).join("_").replace(/\[[\d;]*m/g, "");
|
|
54285
|
+
if (!isFileInScope(filePath, declaredScope)) {
|
|
54286
|
+
const taskId = session?.currentTaskId ?? "unknown";
|
|
54287
|
+
const violationMessage = `SCOPE VIOLATION: ${agentName} attempted to modify '${filePath}' which is not in declared scope for task ${taskId}. Declared scope: [${declaredScope.slice(0, 3).join(", ")}${declaredScope.length > 3 ? "..." : ""}]`;
|
|
54288
|
+
if (session) {
|
|
54289
|
+
session.lastScopeViolation = violationMessage;
|
|
54290
|
+
session.scopeViolationDetected = true;
|
|
54291
|
+
}
|
|
54292
|
+
if (injectAdvisory) {
|
|
54293
|
+
for (const [archSessionId, archSession] of swarmState.agentSessions) {
|
|
54294
|
+
const archAgent = swarmState.activeAgent.get(archSessionId) ?? archSession.agentName;
|
|
54295
|
+
if (stripKnownSwarmPrefix(archAgent) === ORCHESTRATOR_NAME) {
|
|
54296
|
+
try {
|
|
54297
|
+
injectAdvisory(archSessionId, `[SCOPE GUARD] ${violationMessage}`);
|
|
54298
|
+
} catch {}
|
|
54299
|
+
break;
|
|
54300
|
+
}
|
|
54301
|
+
}
|
|
54302
|
+
}
|
|
54303
|
+
throw new Error(violationMessage);
|
|
54304
|
+
}
|
|
54305
|
+
}
|
|
54306
|
+
};
|
|
54307
|
+
}
|
|
54308
|
+
function isFileInScope(filePath, scopeEntries) {
|
|
54309
|
+
const resolvedFile = path37.resolve(filePath);
|
|
54310
|
+
return scopeEntries.some((scope) => {
|
|
54311
|
+
const resolvedScope = path37.resolve(scope);
|
|
54312
|
+
if (resolvedFile === resolvedScope)
|
|
54313
|
+
return true;
|
|
54314
|
+
const rel = path37.relative(resolvedScope, resolvedFile);
|
|
54315
|
+
return rel.length > 0 && !rel.startsWith("..") && !path37.isAbsolute(rel);
|
|
54316
|
+
});
|
|
54317
|
+
}
|
|
54318
|
+
|
|
54319
|
+
// src/hooks/self-review.ts
|
|
54320
|
+
init_constants();
|
|
54321
|
+
init_schema();
|
|
54322
|
+
function createSelfReviewHook(config3, injectAdvisory) {
|
|
54323
|
+
const enabled = config3.enabled ?? true;
|
|
54324
|
+
const skipInTurbo = config3.skip_in_turbo ?? true;
|
|
54325
|
+
return {
|
|
54326
|
+
toolAfter: async (input, output) => {
|
|
54327
|
+
if (!enabled)
|
|
54328
|
+
return;
|
|
54329
|
+
const toolName = input.tool.replace(/^[^:]+[:.]/, "");
|
|
54330
|
+
if (toolName !== "update_task_status")
|
|
54331
|
+
return;
|
|
54332
|
+
const args2 = output.args;
|
|
54333
|
+
if (args2?.status !== "in_progress")
|
|
54334
|
+
return;
|
|
54335
|
+
const taskId = typeof args2?.task_id === "string" ? args2.task_id : "unknown";
|
|
54336
|
+
const sessionId = input.sessionID;
|
|
54337
|
+
const agentName = swarmState.activeAgent.get(sessionId) ?? swarmState.agentSessions.get(sessionId)?.agentName ?? "";
|
|
54338
|
+
if (stripKnownSwarmPrefix(agentName) !== ORCHESTRATOR_NAME)
|
|
54339
|
+
return;
|
|
54340
|
+
if (skipInTurbo) {
|
|
54341
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
54342
|
+
if (session && session.turboMode === true)
|
|
54343
|
+
return;
|
|
54344
|
+
}
|
|
54345
|
+
const advisory = [
|
|
54346
|
+
`[SELF-REVIEW] Task ${taskId} is now delegated to coder.`,
|
|
54347
|
+
`After coder completes, review for:`,
|
|
54348
|
+
` \u2022 Broken conditionals (inverted if/else, wrong comparisons)`,
|
|
54349
|
+
` \u2022 Off-by-one errors (array bounds, loop indices)`,
|
|
54350
|
+
` \u2022 Assumptions contradicting existing codebase patterns`,
|
|
54351
|
+
` \u2022 Missing error handling (uncaught exceptions, unhandled promises)`,
|
|
54352
|
+
` \u2022 Scope creep (changes outside the declared task spec)`,
|
|
54353
|
+
`Delegate to critic with self-review focus before marking complete.`
|
|
54354
|
+
].join(`
|
|
54355
|
+
`);
|
|
54356
|
+
try {
|
|
54357
|
+
injectAdvisory(sessionId, advisory);
|
|
54358
|
+
} catch {}
|
|
54359
|
+
}
|
|
54360
|
+
};
|
|
54361
|
+
}
|
|
54362
|
+
|
|
54113
54363
|
// src/hooks/slop-detector.ts
|
|
54114
54364
|
import * as fs23 from "fs";
|
|
54115
|
-
import * as
|
|
54365
|
+
import * as path38 from "path";
|
|
54116
54366
|
var WRITE_EDIT_TOOLS = new Set([
|
|
54117
54367
|
"write",
|
|
54118
54368
|
"edit",
|
|
@@ -54162,7 +54412,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
54162
54412
|
break;
|
|
54163
54413
|
if (entry.isSymbolicLink())
|
|
54164
54414
|
continue;
|
|
54165
|
-
const full =
|
|
54415
|
+
const full = path38.join(dir, entry.name);
|
|
54166
54416
|
if (entry.isDirectory()) {
|
|
54167
54417
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
54168
54418
|
continue;
|
|
@@ -54177,7 +54427,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
54177
54427
|
return results;
|
|
54178
54428
|
}
|
|
54179
54429
|
function checkDeadExports(content, projectDir, startTime) {
|
|
54180
|
-
const hasPackageJson = fs23.existsSync(
|
|
54430
|
+
const hasPackageJson = fs23.existsSync(path38.join(projectDir, "package.json"));
|
|
54181
54431
|
if (!hasPackageJson)
|
|
54182
54432
|
return null;
|
|
54183
54433
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -54217,6 +54467,61 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
54217
54467
|
detail: `New exports not found in any import: ${deadExports.slice(0, 3).join(", ")}. Verify these are intentionally exported.`
|
|
54218
54468
|
};
|
|
54219
54469
|
}
|
|
54470
|
+
function checkStaleImports(content, threshold) {
|
|
54471
|
+
const lines = content.split(`
|
|
54472
|
+
`);
|
|
54473
|
+
const importLines = [];
|
|
54474
|
+
const importIdentifiers = [];
|
|
54475
|
+
const namedImportRe = /^(?:\+)?import\s*\{([^}]+)\}\s*from\s*['"][^'"]+['"]/;
|
|
54476
|
+
const defaultImportRe = /^(?:\+)?import\s+(\w+)\s+from\s*['"][^'"]+['"]/;
|
|
54477
|
+
const nsImportRe = /^(?:\+)?import\s+\*\s+as\s+(\w+)\s+from\s*['"][^'"]+['"]/;
|
|
54478
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
54479
|
+
const line = lines[i2].replace(/^[+-]/, "");
|
|
54480
|
+
const trimmed = line.trim();
|
|
54481
|
+
if (trimmed.startsWith("export {") || trimmed.startsWith("export type {"))
|
|
54482
|
+
continue;
|
|
54483
|
+
const named = namedImportRe.exec(trimmed);
|
|
54484
|
+
if (named) {
|
|
54485
|
+
importLines.push(i2);
|
|
54486
|
+
for (const part of named[1].split(",")) {
|
|
54487
|
+
const cleaned = part.trim().replace(/^type\s+/, "").split(/\s+as\s+/).pop()?.trim();
|
|
54488
|
+
if (cleaned && /^\w+$/.test(cleaned) && cleaned.length >= 2) {
|
|
54489
|
+
importIdentifiers.push(cleaned);
|
|
54490
|
+
}
|
|
54491
|
+
}
|
|
54492
|
+
continue;
|
|
54493
|
+
}
|
|
54494
|
+
const ns = nsImportRe.exec(trimmed);
|
|
54495
|
+
if (ns?.[1]) {
|
|
54496
|
+
importLines.push(i2);
|
|
54497
|
+
importIdentifiers.push(ns[1]);
|
|
54498
|
+
continue;
|
|
54499
|
+
}
|
|
54500
|
+
const def = defaultImportRe.exec(trimmed);
|
|
54501
|
+
if (def?.[1] && def[1] !== "type") {
|
|
54502
|
+
importLines.push(i2);
|
|
54503
|
+
importIdentifiers.push(def[1]);
|
|
54504
|
+
}
|
|
54505
|
+
}
|
|
54506
|
+
if (importIdentifiers.length === 0)
|
|
54507
|
+
return null;
|
|
54508
|
+
const bodyLines = lines.filter((_, i2) => !importLines.includes(i2));
|
|
54509
|
+
const body2 = bodyLines.join(`
|
|
54510
|
+
`);
|
|
54511
|
+
const staleImports = [];
|
|
54512
|
+
for (const id of importIdentifiers) {
|
|
54513
|
+
const usageRe = new RegExp(`\\b${id}\\b`);
|
|
54514
|
+
if (!usageRe.test(body2)) {
|
|
54515
|
+
staleImports.push(id);
|
|
54516
|
+
}
|
|
54517
|
+
}
|
|
54518
|
+
if (staleImports.length < threshold)
|
|
54519
|
+
return null;
|
|
54520
|
+
return {
|
|
54521
|
+
type: "stale_import",
|
|
54522
|
+
detail: `${staleImports.length} unused import identifier(s): ${staleImports.slice(0, 3).join(", ")}${staleImports.length > 3 ? "..." : ""}. Remove stale imports.`
|
|
54523
|
+
};
|
|
54524
|
+
}
|
|
54220
54525
|
function createSlopDetectorHook(config3, projectDir, injectSystemMessage) {
|
|
54221
54526
|
return {
|
|
54222
54527
|
toolAfter: async (input, output) => {
|
|
@@ -54259,6 +54564,11 @@ function createSlopDetectorHook(config3, projectDir, injectSystemMessage) {
|
|
|
54259
54564
|
findings.push(dead);
|
|
54260
54565
|
} catch {}
|
|
54261
54566
|
}
|
|
54567
|
+
try {
|
|
54568
|
+
const stale = checkStaleImports(content, config3.importHygieneThreshold ?? 2);
|
|
54569
|
+
if (stale)
|
|
54570
|
+
findings.push(stale);
|
|
54571
|
+
} catch {}
|
|
54262
54572
|
if (findings.length === 0)
|
|
54263
54573
|
return;
|
|
54264
54574
|
const findingText = findings.map((f) => ` \u2022 ${f.type}: ${f.detail}`).join(`
|
|
@@ -54640,7 +54950,7 @@ var build_check = createSwarmTool({
|
|
|
54640
54950
|
init_dist();
|
|
54641
54951
|
init_create_tool();
|
|
54642
54952
|
import * as fs25 from "fs";
|
|
54643
|
-
import * as
|
|
54953
|
+
import * as path39 from "path";
|
|
54644
54954
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
54645
54955
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
54646
54956
|
function isValidTaskId3(taskId) {
|
|
@@ -54657,9 +54967,9 @@ function isValidTaskId3(taskId) {
|
|
|
54657
54967
|
return TASK_ID_PATTERN2.test(taskId);
|
|
54658
54968
|
}
|
|
54659
54969
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
54660
|
-
const normalizedWorkspace =
|
|
54661
|
-
const swarmPath =
|
|
54662
|
-
const normalizedPath =
|
|
54970
|
+
const normalizedWorkspace = path39.resolve(workspaceRoot);
|
|
54971
|
+
const swarmPath = path39.join(normalizedWorkspace, ".swarm", "evidence");
|
|
54972
|
+
const normalizedPath = path39.resolve(filePath);
|
|
54663
54973
|
return normalizedPath.startsWith(swarmPath);
|
|
54664
54974
|
}
|
|
54665
54975
|
function readEvidenceFile(evidencePath) {
|
|
@@ -54720,7 +55030,7 @@ var check_gate_status = createSwarmTool({
|
|
|
54720
55030
|
};
|
|
54721
55031
|
return JSON.stringify(errorResult, null, 2);
|
|
54722
55032
|
}
|
|
54723
|
-
const evidencePath =
|
|
55033
|
+
const evidencePath = path39.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
54724
55034
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
54725
55035
|
const errorResult = {
|
|
54726
55036
|
taskId: taskIdInput,
|
|
@@ -54780,7 +55090,7 @@ var check_gate_status = createSwarmTool({
|
|
|
54780
55090
|
init_dist();
|
|
54781
55091
|
init_create_tool();
|
|
54782
55092
|
import * as fs26 from "fs";
|
|
54783
|
-
import * as
|
|
55093
|
+
import * as path40 from "path";
|
|
54784
55094
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
54785
55095
|
var DEFAULT_DAYS = 90;
|
|
54786
55096
|
var DEFAULT_TOP_N = 20;
|
|
@@ -54924,7 +55234,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
54924
55234
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
54925
55235
|
const filteredChurn = new Map;
|
|
54926
55236
|
for (const [file3, count] of churnMap) {
|
|
54927
|
-
const ext =
|
|
55237
|
+
const ext = path40.extname(file3).toLowerCase();
|
|
54928
55238
|
if (extSet.has(ext)) {
|
|
54929
55239
|
filteredChurn.set(file3, count);
|
|
54930
55240
|
}
|
|
@@ -54935,7 +55245,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
54935
55245
|
for (const [file3, churnCount] of filteredChurn) {
|
|
54936
55246
|
let fullPath = file3;
|
|
54937
55247
|
if (!fs26.existsSync(fullPath)) {
|
|
54938
|
-
fullPath =
|
|
55248
|
+
fullPath = path40.join(cwd, file3);
|
|
54939
55249
|
}
|
|
54940
55250
|
const complexity = getComplexityForFile(fullPath);
|
|
54941
55251
|
if (complexity !== null) {
|
|
@@ -55080,10 +55390,71 @@ var complexity_hotspots = createSwarmTool({
|
|
|
55080
55390
|
}
|
|
55081
55391
|
}
|
|
55082
55392
|
});
|
|
55393
|
+
// src/tools/curator-analyze.ts
|
|
55394
|
+
init_dist();
|
|
55395
|
+
init_config();
|
|
55396
|
+
init_schema();
|
|
55397
|
+
init_create_tool();
|
|
55398
|
+
var curator_analyze = createSwarmTool({
|
|
55399
|
+
description: "Run curator phase analysis and optionally apply knowledge recommendations. " + "Call this after reviewing a phase to apply knowledge updates. " + "If recommendations is provided, applies them via applyCuratorKnowledgeUpdates.",
|
|
55400
|
+
args: {
|
|
55401
|
+
phase: tool.schema.number().int().min(1).describe("Phase number to analyze"),
|
|
55402
|
+
recommendations: tool.schema.array(tool.schema.object({
|
|
55403
|
+
action: tool.schema.enum([
|
|
55404
|
+
"promote",
|
|
55405
|
+
"archive",
|
|
55406
|
+
"flag_contradiction"
|
|
55407
|
+
]),
|
|
55408
|
+
entry_id: tool.schema.string().optional(),
|
|
55409
|
+
lesson: tool.schema.string(),
|
|
55410
|
+
reason: tool.schema.string()
|
|
55411
|
+
})).optional().describe("Knowledge recommendations to apply. If omitted, only collects digest data.")
|
|
55412
|
+
},
|
|
55413
|
+
execute: async (args2, directory) => {
|
|
55414
|
+
const typedArgs = args2;
|
|
55415
|
+
try {
|
|
55416
|
+
if (!Number.isInteger(typedArgs.phase) || typedArgs.phase < 1) {
|
|
55417
|
+
return JSON.stringify({ error: "phase must be a positive integer >= 1" }, null, 2);
|
|
55418
|
+
}
|
|
55419
|
+
if (typedArgs.recommendations) {
|
|
55420
|
+
const validActions = ["promote", "archive", "flag_contradiction"];
|
|
55421
|
+
for (const rec of typedArgs.recommendations) {
|
|
55422
|
+
if (!validActions.includes(rec.action)) {
|
|
55423
|
+
return JSON.stringify({
|
|
55424
|
+
error: `Invalid recommendation action: ${rec.action}`
|
|
55425
|
+
}, null, 2);
|
|
55426
|
+
}
|
|
55427
|
+
}
|
|
55428
|
+
}
|
|
55429
|
+
const { config: config3 } = loadPluginConfigWithMeta(directory);
|
|
55430
|
+
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
55431
|
+
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
55432
|
+
const curatorResult = await runCuratorPhase(directory, typedArgs.phase, [], curatorConfig, {});
|
|
55433
|
+
let applied = 0;
|
|
55434
|
+
let skipped = 0;
|
|
55435
|
+
if (typedArgs.recommendations && typedArgs.recommendations.length > 0) {
|
|
55436
|
+
const result = await applyCuratorKnowledgeUpdates(directory, typedArgs.recommendations, knowledgeConfig);
|
|
55437
|
+
applied = result.applied;
|
|
55438
|
+
skipped = result.skipped;
|
|
55439
|
+
}
|
|
55440
|
+
return JSON.stringify({
|
|
55441
|
+
phase_digest: curatorResult.digest,
|
|
55442
|
+
compliance_count: curatorResult.compliance.length,
|
|
55443
|
+
applied,
|
|
55444
|
+
skipped
|
|
55445
|
+
}, null, 2);
|
|
55446
|
+
} catch (error93) {
|
|
55447
|
+
return JSON.stringify({
|
|
55448
|
+
error: String(error93),
|
|
55449
|
+
phase: typedArgs.phase
|
|
55450
|
+
}, null, 2);
|
|
55451
|
+
}
|
|
55452
|
+
}
|
|
55453
|
+
});
|
|
55083
55454
|
// src/tools/declare-scope.ts
|
|
55084
55455
|
init_tool();
|
|
55085
55456
|
import * as fs27 from "fs";
|
|
55086
|
-
import * as
|
|
55457
|
+
import * as path41 from "path";
|
|
55087
55458
|
init_create_tool();
|
|
55088
55459
|
function validateTaskIdFormat(taskId) {
|
|
55089
55460
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -55162,8 +55533,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
55162
55533
|
};
|
|
55163
55534
|
}
|
|
55164
55535
|
}
|
|
55165
|
-
normalizedDir =
|
|
55166
|
-
const pathParts = normalizedDir.split(
|
|
55536
|
+
normalizedDir = path41.normalize(args2.working_directory);
|
|
55537
|
+
const pathParts = normalizedDir.split(path41.sep);
|
|
55167
55538
|
if (pathParts.includes("..")) {
|
|
55168
55539
|
return {
|
|
55169
55540
|
success: false,
|
|
@@ -55173,10 +55544,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
55173
55544
|
]
|
|
55174
55545
|
};
|
|
55175
55546
|
}
|
|
55176
|
-
const resolvedDir =
|
|
55547
|
+
const resolvedDir = path41.resolve(normalizedDir);
|
|
55177
55548
|
try {
|
|
55178
55549
|
const realPath = fs27.realpathSync(resolvedDir);
|
|
55179
|
-
const planPath2 =
|
|
55550
|
+
const planPath2 = path41.join(realPath, ".swarm", "plan.json");
|
|
55180
55551
|
if (!fs27.existsSync(planPath2)) {
|
|
55181
55552
|
return {
|
|
55182
55553
|
success: false,
|
|
@@ -55196,8 +55567,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
55196
55567
|
};
|
|
55197
55568
|
}
|
|
55198
55569
|
}
|
|
55199
|
-
|
|
55200
|
-
|
|
55570
|
+
if (!fallbackDir) {
|
|
55571
|
+
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
55572
|
+
}
|
|
55573
|
+
const directory = normalizedDir || fallbackDir || process.cwd();
|
|
55574
|
+
const planPath = path41.resolve(directory, ".swarm", "plan.json");
|
|
55201
55575
|
if (!fs27.existsSync(planPath)) {
|
|
55202
55576
|
return {
|
|
55203
55577
|
success: false,
|
|
@@ -55260,6 +55634,7 @@ var declare_scope = createSwarmTool({
|
|
|
55260
55634
|
});
|
|
55261
55635
|
// src/tools/diff.ts
|
|
55262
55636
|
init_dist();
|
|
55637
|
+
init_create_tool();
|
|
55263
55638
|
import { execFileSync } from "child_process";
|
|
55264
55639
|
var MAX_DIFF_LINES = 500;
|
|
55265
55640
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -55287,34 +55662,35 @@ function validateBase(base) {
|
|
|
55287
55662
|
function validatePaths(paths) {
|
|
55288
55663
|
if (!paths)
|
|
55289
55664
|
return null;
|
|
55290
|
-
for (const
|
|
55291
|
-
if (!
|
|
55665
|
+
for (const path42 of paths) {
|
|
55666
|
+
if (!path42 || path42.length === 0) {
|
|
55292
55667
|
return "empty path not allowed";
|
|
55293
55668
|
}
|
|
55294
|
-
if (
|
|
55669
|
+
if (path42.length > MAX_PATH_LENGTH) {
|
|
55295
55670
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
55296
55671
|
}
|
|
55297
|
-
if (SHELL_METACHARACTERS2.test(
|
|
55672
|
+
if (SHELL_METACHARACTERS2.test(path42)) {
|
|
55298
55673
|
return "path contains shell metacharacters";
|
|
55299
55674
|
}
|
|
55300
|
-
if (
|
|
55675
|
+
if (path42.startsWith("-")) {
|
|
55301
55676
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
55302
55677
|
}
|
|
55303
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
55678
|
+
if (CONTROL_CHAR_PATTERN2.test(path42)) {
|
|
55304
55679
|
return "path contains control characters";
|
|
55305
55680
|
}
|
|
55306
55681
|
}
|
|
55307
55682
|
return null;
|
|
55308
55683
|
}
|
|
55309
|
-
var diff =
|
|
55684
|
+
var diff = createSwarmTool({
|
|
55310
55685
|
description: "Analyze git diff for changed files, exports, interfaces, and function signatures. Returns structured output with contract change detection.",
|
|
55311
55686
|
args: {
|
|
55312
55687
|
base: tool.schema.string().optional().describe('Base ref to diff against (default: HEAD). Use "staged" for staged changes, "unstaged" for working tree changes.'),
|
|
55313
55688
|
paths: tool.schema.array(tool.schema.string()).optional().describe("Optional file paths to restrict diff scope.")
|
|
55314
55689
|
},
|
|
55315
|
-
async execute(args2,
|
|
55690
|
+
async execute(args2, directory, _ctx) {
|
|
55691
|
+
const typedArgs = args2;
|
|
55316
55692
|
try {
|
|
55317
|
-
if (!
|
|
55693
|
+
if (!directory || typeof directory !== "string" || directory.trim() === "") {
|
|
55318
55694
|
const errorResult = {
|
|
55319
55695
|
error: "project directory is required but was not provided",
|
|
55320
55696
|
files: [],
|
|
@@ -55323,7 +55699,7 @@ var diff = tool({
|
|
|
55323
55699
|
};
|
|
55324
55700
|
return JSON.stringify(errorResult, null, 2);
|
|
55325
55701
|
}
|
|
55326
|
-
const base =
|
|
55702
|
+
const base = typedArgs.base ?? "HEAD";
|
|
55327
55703
|
const baseValidationError = validateBase(base);
|
|
55328
55704
|
if (baseValidationError) {
|
|
55329
55705
|
const errorResult = {
|
|
@@ -55334,7 +55710,7 @@ var diff = tool({
|
|
|
55334
55710
|
};
|
|
55335
55711
|
return JSON.stringify(errorResult, null, 2);
|
|
55336
55712
|
}
|
|
55337
|
-
const pathsValidationError = validatePaths(
|
|
55713
|
+
const pathsValidationError = validatePaths(typedArgs.paths);
|
|
55338
55714
|
if (pathsValidationError) {
|
|
55339
55715
|
const errorResult = {
|
|
55340
55716
|
error: `invalid paths: ${pathsValidationError}`,
|
|
@@ -55354,21 +55730,21 @@ var diff = tool({
|
|
|
55354
55730
|
}
|
|
55355
55731
|
const numstatArgs = [...gitArgs, "--numstat"];
|
|
55356
55732
|
const fullDiffArgs = [...gitArgs, "-U3"];
|
|
55357
|
-
if (
|
|
55358
|
-
numstatArgs.push("--", ...
|
|
55359
|
-
fullDiffArgs.push("--", ...
|
|
55733
|
+
if (typedArgs.paths?.length) {
|
|
55734
|
+
numstatArgs.push("--", ...typedArgs.paths);
|
|
55735
|
+
fullDiffArgs.push("--", ...typedArgs.paths);
|
|
55360
55736
|
}
|
|
55361
55737
|
const numstatOutput = execFileSync("git", numstatArgs, {
|
|
55362
55738
|
encoding: "utf-8",
|
|
55363
55739
|
timeout: DIFF_TIMEOUT_MS,
|
|
55364
55740
|
maxBuffer: MAX_BUFFER_BYTES,
|
|
55365
|
-
cwd:
|
|
55741
|
+
cwd: directory
|
|
55366
55742
|
});
|
|
55367
55743
|
const fullDiffOutput = execFileSync("git", fullDiffArgs, {
|
|
55368
55744
|
encoding: "utf-8",
|
|
55369
55745
|
timeout: DIFF_TIMEOUT_MS,
|
|
55370
55746
|
maxBuffer: MAX_BUFFER_BYTES,
|
|
55371
|
-
cwd:
|
|
55747
|
+
cwd: directory
|
|
55372
55748
|
});
|
|
55373
55749
|
const files = [];
|
|
55374
55750
|
const numstatLines = numstatOutput.split(`
|
|
@@ -55380,8 +55756,8 @@ var diff = tool({
|
|
|
55380
55756
|
if (parts2.length >= 3) {
|
|
55381
55757
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
55382
55758
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
55383
|
-
const
|
|
55384
|
-
files.push({ path:
|
|
55759
|
+
const path42 = parts2[2];
|
|
55760
|
+
files.push({ path: path42, additions, deletions });
|
|
55385
55761
|
}
|
|
55386
55762
|
}
|
|
55387
55763
|
const contractChanges = [];
|
|
@@ -55611,7 +55987,7 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
55611
55987
|
init_dist();
|
|
55612
55988
|
init_create_tool();
|
|
55613
55989
|
import * as fs28 from "fs";
|
|
55614
|
-
import * as
|
|
55990
|
+
import * as path42 from "path";
|
|
55615
55991
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
55616
55992
|
var MAX_EVIDENCE_FILES = 1000;
|
|
55617
55993
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -55641,9 +56017,9 @@ function validateRequiredTypes(input) {
|
|
|
55641
56017
|
return null;
|
|
55642
56018
|
}
|
|
55643
56019
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
55644
|
-
const normalizedCwd =
|
|
55645
|
-
const swarmPath =
|
|
55646
|
-
const normalizedPath =
|
|
56020
|
+
const normalizedCwd = path42.resolve(cwd);
|
|
56021
|
+
const swarmPath = path42.join(normalizedCwd, ".swarm");
|
|
56022
|
+
const normalizedPath = path42.resolve(filePath);
|
|
55647
56023
|
return normalizedPath.startsWith(swarmPath);
|
|
55648
56024
|
}
|
|
55649
56025
|
function parseCompletedTasks(planContent) {
|
|
@@ -55673,10 +56049,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
55673
56049
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
55674
56050
|
continue;
|
|
55675
56051
|
}
|
|
55676
|
-
const filePath =
|
|
56052
|
+
const filePath = path42.join(evidenceDir, filename);
|
|
55677
56053
|
try {
|
|
55678
|
-
const resolvedPath =
|
|
55679
|
-
const evidenceDirResolved =
|
|
56054
|
+
const resolvedPath = path42.resolve(filePath);
|
|
56055
|
+
const evidenceDirResolved = path42.resolve(evidenceDir);
|
|
55680
56056
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
55681
56057
|
continue;
|
|
55682
56058
|
}
|
|
@@ -55794,7 +56170,7 @@ var evidence_check = createSwarmTool({
|
|
|
55794
56170
|
return JSON.stringify(errorResult, null, 2);
|
|
55795
56171
|
}
|
|
55796
56172
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
55797
|
-
const planPath =
|
|
56173
|
+
const planPath = path42.join(cwd, PLAN_FILE);
|
|
55798
56174
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
55799
56175
|
const errorResult = {
|
|
55800
56176
|
error: "plan file path validation failed",
|
|
@@ -55826,7 +56202,7 @@ var evidence_check = createSwarmTool({
|
|
|
55826
56202
|
};
|
|
55827
56203
|
return JSON.stringify(result2, null, 2);
|
|
55828
56204
|
}
|
|
55829
|
-
const evidenceDir =
|
|
56205
|
+
const evidenceDir = path42.join(cwd, EVIDENCE_DIR2);
|
|
55830
56206
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
55831
56207
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
55832
56208
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -55844,7 +56220,7 @@ var evidence_check = createSwarmTool({
|
|
|
55844
56220
|
init_tool();
|
|
55845
56221
|
init_create_tool();
|
|
55846
56222
|
import * as fs29 from "fs";
|
|
55847
|
-
import * as
|
|
56223
|
+
import * as path43 from "path";
|
|
55848
56224
|
var EXT_MAP = {
|
|
55849
56225
|
python: ".py",
|
|
55850
56226
|
py: ".py",
|
|
@@ -55925,12 +56301,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
55925
56301
|
if (prefix) {
|
|
55926
56302
|
filename = `${prefix}_${filename}`;
|
|
55927
56303
|
}
|
|
55928
|
-
let filepath =
|
|
55929
|
-
const base =
|
|
55930
|
-
const ext =
|
|
56304
|
+
let filepath = path43.join(targetDir, filename);
|
|
56305
|
+
const base = path43.basename(filepath, path43.extname(filepath));
|
|
56306
|
+
const ext = path43.extname(filepath);
|
|
55931
56307
|
let counter = 1;
|
|
55932
56308
|
while (fs29.existsSync(filepath)) {
|
|
55933
|
-
filepath =
|
|
56309
|
+
filepath = path43.join(targetDir, `${base}_${counter}${ext}`);
|
|
55934
56310
|
counter++;
|
|
55935
56311
|
}
|
|
55936
56312
|
try {
|
|
@@ -55960,10 +56336,11 @@ Errors:
|
|
|
55960
56336
|
});
|
|
55961
56337
|
// src/tools/gitingest.ts
|
|
55962
56338
|
init_dist();
|
|
56339
|
+
init_create_tool();
|
|
55963
56340
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
55964
56341
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
55965
56342
|
var GITINGEST_MAX_RETRIES = 2;
|
|
55966
|
-
var delay = (ms) => new Promise((
|
|
56343
|
+
var delay = (ms) => new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
55967
56344
|
async function fetchGitingest(args2) {
|
|
55968
56345
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
55969
56346
|
try {
|
|
@@ -56033,7 +56410,7 @@ ${data.content}`;
|
|
|
56033
56410
|
}
|
|
56034
56411
|
throw new Error("gitingest request failed after retries");
|
|
56035
56412
|
}
|
|
56036
|
-
var gitingest =
|
|
56413
|
+
var gitingest = createSwarmTool({
|
|
56037
56414
|
description: "Fetch a GitHub repository's full content via gitingest.com. Returns summary, directory tree, and file contents optimized for LLM analysis. Use when you need to understand an external repository's structure or code.",
|
|
56038
56415
|
args: {
|
|
56039
56416
|
url: tool.schema.string().describe("GitHub repository URL (e.g., https://github.com/owner/repo)"),
|
|
@@ -56041,14 +56418,16 @@ var gitingest = tool({
|
|
|
56041
56418
|
pattern: tool.schema.string().optional().describe("Glob pattern to filter files (e.g., '*.ts' or 'src/**/*.py')"),
|
|
56042
56419
|
patternType: tool.schema.enum(["include", "exclude"]).optional().describe("Whether pattern includes or excludes matching files (default: exclude)")
|
|
56043
56420
|
},
|
|
56044
|
-
async execute(args2,
|
|
56045
|
-
|
|
56421
|
+
async execute(args2, _directory, _ctx) {
|
|
56422
|
+
const typedArgs = args2;
|
|
56423
|
+
return fetchGitingest(typedArgs);
|
|
56046
56424
|
}
|
|
56047
56425
|
});
|
|
56048
56426
|
// src/tools/imports.ts
|
|
56049
56427
|
init_dist();
|
|
56428
|
+
init_create_tool();
|
|
56050
56429
|
import * as fs30 from "fs";
|
|
56051
|
-
import * as
|
|
56430
|
+
import * as path44 from "path";
|
|
56052
56431
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
56053
56432
|
var MAX_SYMBOL_LENGTH = 256;
|
|
56054
56433
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
@@ -56102,7 +56481,7 @@ function validateSymbolInput(symbol3) {
|
|
|
56102
56481
|
return null;
|
|
56103
56482
|
}
|
|
56104
56483
|
function isBinaryFile2(filePath, buffer) {
|
|
56105
|
-
const ext =
|
|
56484
|
+
const ext = path44.extname(filePath).toLowerCase();
|
|
56106
56485
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
56107
56486
|
return false;
|
|
56108
56487
|
}
|
|
@@ -56126,15 +56505,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56126
56505
|
const imports = [];
|
|
56127
56506
|
let _resolvedTarget;
|
|
56128
56507
|
try {
|
|
56129
|
-
_resolvedTarget =
|
|
56508
|
+
_resolvedTarget = path44.resolve(targetFile);
|
|
56130
56509
|
} catch {
|
|
56131
56510
|
_resolvedTarget = targetFile;
|
|
56132
56511
|
}
|
|
56133
|
-
const targetBasename =
|
|
56512
|
+
const targetBasename = path44.basename(targetFile, path44.extname(targetFile));
|
|
56134
56513
|
const targetWithExt = targetFile;
|
|
56135
56514
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
56136
|
-
const normalizedTargetWithExt =
|
|
56137
|
-
const normalizedTargetWithoutExt =
|
|
56515
|
+
const normalizedTargetWithExt = path44.normalize(targetWithExt).replace(/\\/g, "/");
|
|
56516
|
+
const normalizedTargetWithoutExt = path44.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
56138
56517
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
56139
56518
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
56140
56519
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -56157,9 +56536,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56157
56536
|
}
|
|
56158
56537
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
56159
56538
|
let isMatch = false;
|
|
56160
|
-
const _targetDir =
|
|
56161
|
-
const targetExt =
|
|
56162
|
-
const targetBasenameNoExt =
|
|
56539
|
+
const _targetDir = path44.dirname(targetFile);
|
|
56540
|
+
const targetExt = path44.extname(targetFile);
|
|
56541
|
+
const targetBasenameNoExt = path44.basename(targetFile, targetExt);
|
|
56163
56542
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
56164
56543
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
56165
56544
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -56227,10 +56606,10 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56227
56606
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
56228
56607
|
for (const entry of entries) {
|
|
56229
56608
|
if (SKIP_DIRECTORIES2.has(entry)) {
|
|
56230
|
-
stats.skippedDirs.push(
|
|
56609
|
+
stats.skippedDirs.push(path44.join(dir, entry));
|
|
56231
56610
|
continue;
|
|
56232
56611
|
}
|
|
56233
|
-
const fullPath =
|
|
56612
|
+
const fullPath = path44.join(dir, entry);
|
|
56234
56613
|
let stat2;
|
|
56235
56614
|
try {
|
|
56236
56615
|
stat2 = fs30.statSync(fullPath);
|
|
@@ -56244,7 +56623,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56244
56623
|
if (stat2.isDirectory()) {
|
|
56245
56624
|
findSourceFiles(fullPath, files, stats);
|
|
56246
56625
|
} else if (stat2.isFile()) {
|
|
56247
|
-
const ext =
|
|
56626
|
+
const ext = path44.extname(fullPath).toLowerCase();
|
|
56248
56627
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
56249
56628
|
files.push(fullPath);
|
|
56250
56629
|
}
|
|
@@ -56252,19 +56631,20 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56252
56631
|
}
|
|
56253
56632
|
return files;
|
|
56254
56633
|
}
|
|
56255
|
-
var imports =
|
|
56634
|
+
var imports = createSwarmTool({
|
|
56256
56635
|
description: "Find all consumers that import from a given file. Returns JSON with file path, line numbers, and import metadata for each consumer. Useful for understanding dependency relationships.",
|
|
56257
56636
|
args: {
|
|
56258
56637
|
file: tool.schema.string().describe('Source file path to find importers for (e.g., "./src/utils.ts")'),
|
|
56259
56638
|
symbol: tool.schema.string().optional().describe('Optional specific symbol to filter imports (e.g., "MyClass")')
|
|
56260
56639
|
},
|
|
56261
|
-
async execute(args2,
|
|
56640
|
+
async execute(args2, _directory, _ctx) {
|
|
56641
|
+
const typedArgs = args2;
|
|
56262
56642
|
let file3;
|
|
56263
56643
|
let symbol3;
|
|
56264
56644
|
try {
|
|
56265
|
-
if (
|
|
56266
|
-
file3 =
|
|
56267
|
-
symbol3 =
|
|
56645
|
+
if (typedArgs && typeof typedArgs === "object") {
|
|
56646
|
+
file3 = typedArgs.file;
|
|
56647
|
+
symbol3 = typedArgs.symbol;
|
|
56268
56648
|
}
|
|
56269
56649
|
} catch {}
|
|
56270
56650
|
if (file3 === undefined) {
|
|
@@ -56300,7 +56680,7 @@ var imports = tool({
|
|
|
56300
56680
|
return JSON.stringify(errorResult, null, 2);
|
|
56301
56681
|
}
|
|
56302
56682
|
try {
|
|
56303
|
-
const targetFile =
|
|
56683
|
+
const targetFile = path44.resolve(file3);
|
|
56304
56684
|
if (!fs30.existsSync(targetFile)) {
|
|
56305
56685
|
const errorResult = {
|
|
56306
56686
|
error: `target file not found: ${file3}`,
|
|
@@ -56322,7 +56702,7 @@ var imports = tool({
|
|
|
56322
56702
|
};
|
|
56323
56703
|
return JSON.stringify(errorResult, null, 2);
|
|
56324
56704
|
}
|
|
56325
|
-
const baseDir =
|
|
56705
|
+
const baseDir = path44.dirname(targetFile);
|
|
56326
56706
|
const scanStats = {
|
|
56327
56707
|
skippedDirs: [],
|
|
56328
56708
|
skippedFiles: 0,
|
|
@@ -56405,13 +56785,120 @@ var imports = tool({
|
|
|
56405
56785
|
}
|
|
56406
56786
|
}
|
|
56407
56787
|
});
|
|
56788
|
+
// src/tools/knowledge-add.ts
|
|
56789
|
+
init_dist();
|
|
56790
|
+
init_create_tool();
|
|
56791
|
+
var VALID_CATEGORIES2 = [
|
|
56792
|
+
"process",
|
|
56793
|
+
"architecture",
|
|
56794
|
+
"tooling",
|
|
56795
|
+
"security",
|
|
56796
|
+
"testing",
|
|
56797
|
+
"debugging",
|
|
56798
|
+
"performance",
|
|
56799
|
+
"integration",
|
|
56800
|
+
"other"
|
|
56801
|
+
];
|
|
56802
|
+
var knowledgeAdd = createSwarmTool({
|
|
56803
|
+
description: "Store a new lesson in the knowledge base for future reference. The lesson will be available for retrieval via knowledge_recall.",
|
|
56804
|
+
args: {
|
|
56805
|
+
lesson: tool.schema.string().min(15).max(280).describe("The lesson to store (15-280 characters)"),
|
|
56806
|
+
category: tool.schema.enum(VALID_CATEGORIES2).describe("Knowledge category for the lesson"),
|
|
56807
|
+
tags: tool.schema.array(tool.schema.string()).optional().describe("Optional tags for better searchability"),
|
|
56808
|
+
scope: tool.schema.string().optional().describe("Scope of the lesson (global or stack:<name>)")
|
|
56809
|
+
},
|
|
56810
|
+
execute: async (args2, directory) => {
|
|
56811
|
+
let lessonInput;
|
|
56812
|
+
let categoryInput;
|
|
56813
|
+
let tagsInput;
|
|
56814
|
+
let scopeInput;
|
|
56815
|
+
try {
|
|
56816
|
+
if (args2 && typeof args2 === "object") {
|
|
56817
|
+
const obj = args2;
|
|
56818
|
+
lessonInput = obj.lesson;
|
|
56819
|
+
categoryInput = obj.category;
|
|
56820
|
+
tagsInput = obj.tags;
|
|
56821
|
+
scopeInput = obj.scope;
|
|
56822
|
+
}
|
|
56823
|
+
} catch {}
|
|
56824
|
+
if (typeof lessonInput !== "string") {
|
|
56825
|
+
return JSON.stringify({
|
|
56826
|
+
success: false,
|
|
56827
|
+
error: "lesson must be a string"
|
|
56828
|
+
});
|
|
56829
|
+
}
|
|
56830
|
+
const lesson = lessonInput;
|
|
56831
|
+
if (lesson.length < 15 || lesson.length > 280) {
|
|
56832
|
+
return JSON.stringify({
|
|
56833
|
+
success: false,
|
|
56834
|
+
error: "lesson must be between 15 and 280 characters"
|
|
56835
|
+
});
|
|
56836
|
+
}
|
|
56837
|
+
if (typeof categoryInput !== "string") {
|
|
56838
|
+
return JSON.stringify({
|
|
56839
|
+
success: false,
|
|
56840
|
+
error: "category must be a string"
|
|
56841
|
+
});
|
|
56842
|
+
}
|
|
56843
|
+
const category = categoryInput;
|
|
56844
|
+
if (!VALID_CATEGORIES2.includes(category)) {
|
|
56845
|
+
return JSON.stringify({
|
|
56846
|
+
success: false,
|
|
56847
|
+
error: `category must be one of: ${VALID_CATEGORIES2.join(", ")}`
|
|
56848
|
+
});
|
|
56849
|
+
}
|
|
56850
|
+
let tags = [];
|
|
56851
|
+
if (tagsInput !== undefined) {
|
|
56852
|
+
if (Array.isArray(tagsInput)) {
|
|
56853
|
+
tags = tagsInput.filter((t) => typeof t === "string").slice(0, 20);
|
|
56854
|
+
}
|
|
56855
|
+
}
|
|
56856
|
+
const scope = typeof scopeInput === "string" && scopeInput.length > 0 ? scopeInput : "global";
|
|
56857
|
+
const entry = {
|
|
56858
|
+
id: crypto.randomUUID(),
|
|
56859
|
+
tier: "swarm",
|
|
56860
|
+
lesson,
|
|
56861
|
+
category,
|
|
56862
|
+
tags,
|
|
56863
|
+
scope,
|
|
56864
|
+
confidence: 0.5,
|
|
56865
|
+
status: "candidate",
|
|
56866
|
+
confirmed_by: [],
|
|
56867
|
+
project_name: "",
|
|
56868
|
+
retrieval_outcomes: {
|
|
56869
|
+
applied_count: 0,
|
|
56870
|
+
succeeded_after_count: 0,
|
|
56871
|
+
failed_after_count: 0
|
|
56872
|
+
},
|
|
56873
|
+
schema_version: 1,
|
|
56874
|
+
created_at: new Date().toISOString(),
|
|
56875
|
+
updated_at: new Date().toISOString(),
|
|
56876
|
+
auto_generated: true,
|
|
56877
|
+
hive_eligible: false
|
|
56878
|
+
};
|
|
56879
|
+
try {
|
|
56880
|
+
await appendKnowledge(resolveSwarmKnowledgePath(directory), entry);
|
|
56881
|
+
} catch (err2) {
|
|
56882
|
+
const message = err2 instanceof Error ? err2.message : "Unknown error";
|
|
56883
|
+
return JSON.stringify({
|
|
56884
|
+
success: false,
|
|
56885
|
+
error: message
|
|
56886
|
+
});
|
|
56887
|
+
}
|
|
56888
|
+
return JSON.stringify({
|
|
56889
|
+
success: true,
|
|
56890
|
+
id: entry.id,
|
|
56891
|
+
category
|
|
56892
|
+
});
|
|
56893
|
+
}
|
|
56894
|
+
});
|
|
56408
56895
|
// src/tools/knowledge-query.ts
|
|
56409
56896
|
init_dist();
|
|
56410
56897
|
import { existsSync as existsSync28 } from "fs";
|
|
56411
56898
|
init_create_tool();
|
|
56412
56899
|
var DEFAULT_LIMIT = 10;
|
|
56413
56900
|
var MAX_LESSON_LENGTH = 200;
|
|
56414
|
-
var
|
|
56901
|
+
var VALID_CATEGORIES3 = [
|
|
56415
56902
|
"process",
|
|
56416
56903
|
"architecture",
|
|
56417
56904
|
"tooling",
|
|
@@ -56446,7 +56933,7 @@ function validateCategoryInput(category) {
|
|
|
56446
56933
|
if (typeof category !== "string")
|
|
56447
56934
|
return null;
|
|
56448
56935
|
const normalized = category.toLowerCase().trim();
|
|
56449
|
-
if (
|
|
56936
|
+
if (VALID_CATEGORIES3.includes(normalized)) {
|
|
56450
56937
|
return normalized;
|
|
56451
56938
|
}
|
|
56452
56939
|
return null;
|
|
@@ -56634,6 +57121,147 @@ var knowledge_query = createSwarmTool({
|
|
|
56634
57121
|
`);
|
|
56635
57122
|
}
|
|
56636
57123
|
});
|
|
57124
|
+
// src/tools/knowledge-recall.ts
|
|
57125
|
+
init_dist();
|
|
57126
|
+
init_create_tool();
|
|
57127
|
+
var knowledgeRecall = createSwarmTool({
|
|
57128
|
+
description: "Search the knowledge base for relevant past decisions, patterns, and lessons learned. Returns ranked results by semantic similarity.",
|
|
57129
|
+
args: {
|
|
57130
|
+
query: tool.schema.string().min(3).describe("Natural language search query"),
|
|
57131
|
+
top_n: tool.schema.number().int().min(1).max(20).optional().describe("Maximum results to return (default: 5)"),
|
|
57132
|
+
tier: tool.schema.enum(["all", "swarm", "hive"]).optional().describe("Knowledge tier to search (default: 'all')")
|
|
57133
|
+
},
|
|
57134
|
+
execute: async (args2, directory) => {
|
|
57135
|
+
let queryInput;
|
|
57136
|
+
let topNInput;
|
|
57137
|
+
let tierInput;
|
|
57138
|
+
try {
|
|
57139
|
+
if (args2 && typeof args2 === "object") {
|
|
57140
|
+
const obj = args2;
|
|
57141
|
+
queryInput = obj.query;
|
|
57142
|
+
topNInput = obj.top_n;
|
|
57143
|
+
tierInput = obj.tier;
|
|
57144
|
+
}
|
|
57145
|
+
} catch {}
|
|
57146
|
+
if (typeof queryInput !== "string" || queryInput.length < 3) {
|
|
57147
|
+
return JSON.stringify({
|
|
57148
|
+
results: [],
|
|
57149
|
+
total: 0,
|
|
57150
|
+
error: "query must be a string with at least 3 characters"
|
|
57151
|
+
});
|
|
57152
|
+
}
|
|
57153
|
+
let topN = 5;
|
|
57154
|
+
if (topNInput !== undefined) {
|
|
57155
|
+
if (typeof topNInput === "number" && Number.isInteger(topNInput)) {
|
|
57156
|
+
topN = Math.max(1, Math.min(20, topNInput));
|
|
57157
|
+
}
|
|
57158
|
+
}
|
|
57159
|
+
let tier = "all";
|
|
57160
|
+
if (tierInput !== undefined && typeof tierInput === "string") {
|
|
57161
|
+
if (tierInput === "swarm" || tierInput === "hive") {
|
|
57162
|
+
tier = tierInput;
|
|
57163
|
+
}
|
|
57164
|
+
}
|
|
57165
|
+
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
57166
|
+
const hivePath = resolveHiveKnowledgePath();
|
|
57167
|
+
const [swarmEntries, hiveEntries] = await Promise.all([
|
|
57168
|
+
readKnowledge(swarmPath),
|
|
57169
|
+
readKnowledge(hivePath)
|
|
57170
|
+
]);
|
|
57171
|
+
let entries = [];
|
|
57172
|
+
if (tier === "all" || tier === "swarm") {
|
|
57173
|
+
entries = entries.concat(swarmEntries);
|
|
57174
|
+
}
|
|
57175
|
+
if (tier === "all" || tier === "hive") {
|
|
57176
|
+
entries = entries.concat(hiveEntries);
|
|
57177
|
+
}
|
|
57178
|
+
if (entries.length === 0) {
|
|
57179
|
+
const result2 = { results: [], total: 0 };
|
|
57180
|
+
return JSON.stringify(result2);
|
|
57181
|
+
}
|
|
57182
|
+
const normalizedQuery = normalize2(queryInput);
|
|
57183
|
+
const queryBigrams = wordBigrams(normalizedQuery);
|
|
57184
|
+
const scoredEntries = entries.map((entry) => {
|
|
57185
|
+
const entryText = `${entry.lesson} ${entry.tags.join(" ")} ${entry.category}`;
|
|
57186
|
+
const entryBigrams = wordBigrams(entryText);
|
|
57187
|
+
const textScore = jaccardBigram(queryBigrams, entryBigrams);
|
|
57188
|
+
const boost = entry.status === "established" ? 0.1 : entry.status === "promoted" ? 0.05 : 0;
|
|
57189
|
+
const finalScore = textScore + boost;
|
|
57190
|
+
return {
|
|
57191
|
+
id: entry.id,
|
|
57192
|
+
confidence: entry.confidence,
|
|
57193
|
+
category: entry.category,
|
|
57194
|
+
lesson: entry.lesson,
|
|
57195
|
+
score: finalScore
|
|
57196
|
+
};
|
|
57197
|
+
});
|
|
57198
|
+
scoredEntries.sort((a, b) => b.score - a.score);
|
|
57199
|
+
const topResults = scoredEntries.slice(0, topN);
|
|
57200
|
+
const result = {
|
|
57201
|
+
results: topResults,
|
|
57202
|
+
total: topResults.length
|
|
57203
|
+
};
|
|
57204
|
+
return JSON.stringify(result);
|
|
57205
|
+
}
|
|
57206
|
+
});
|
|
57207
|
+
// src/tools/knowledge-remove.ts
|
|
57208
|
+
init_dist();
|
|
57209
|
+
init_create_tool();
|
|
57210
|
+
var knowledgeRemove = createSwarmTool({
|
|
57211
|
+
description: "Delete an outdated knowledge entry by ID. Double-deletion is idempotent \u2014 removing a non-existent entry returns a clear message without error.",
|
|
57212
|
+
args: {
|
|
57213
|
+
id: tool.schema.string().min(1).describe("UUID of the knowledge entry to remove")
|
|
57214
|
+
},
|
|
57215
|
+
execute: async (args2, directory) => {
|
|
57216
|
+
let idInput;
|
|
57217
|
+
try {
|
|
57218
|
+
if (args2 && typeof args2 === "object") {
|
|
57219
|
+
const obj = args2;
|
|
57220
|
+
idInput = obj.id;
|
|
57221
|
+
}
|
|
57222
|
+
} catch {}
|
|
57223
|
+
if (typeof idInput !== "string" || idInput.length < 1) {
|
|
57224
|
+
return JSON.stringify({
|
|
57225
|
+
success: false,
|
|
57226
|
+
error: "id must be a non-empty string"
|
|
57227
|
+
});
|
|
57228
|
+
}
|
|
57229
|
+
const id = idInput;
|
|
57230
|
+
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
57231
|
+
let entries;
|
|
57232
|
+
try {
|
|
57233
|
+
entries = await readKnowledge(swarmPath);
|
|
57234
|
+
} catch (err2) {
|
|
57235
|
+
const message = err2 instanceof Error ? err2.message : "Unknown error";
|
|
57236
|
+
return JSON.stringify({
|
|
57237
|
+
success: false,
|
|
57238
|
+
error: message
|
|
57239
|
+
});
|
|
57240
|
+
}
|
|
57241
|
+
const originalCount = entries.length;
|
|
57242
|
+
entries = entries.filter((entry) => entry.id !== id);
|
|
57243
|
+
if (entries.length === originalCount) {
|
|
57244
|
+
return JSON.stringify({
|
|
57245
|
+
success: false,
|
|
57246
|
+
message: "entry not found"
|
|
57247
|
+
});
|
|
57248
|
+
}
|
|
57249
|
+
try {
|
|
57250
|
+
await rewriteKnowledge(swarmPath, entries);
|
|
57251
|
+
} catch (err2) {
|
|
57252
|
+
const message = err2 instanceof Error ? err2.message : "Unknown error";
|
|
57253
|
+
return JSON.stringify({
|
|
57254
|
+
success: false,
|
|
57255
|
+
error: message
|
|
57256
|
+
});
|
|
57257
|
+
}
|
|
57258
|
+
return JSON.stringify({
|
|
57259
|
+
success: true,
|
|
57260
|
+
removed: 1,
|
|
57261
|
+
remaining: entries.length
|
|
57262
|
+
});
|
|
57263
|
+
}
|
|
57264
|
+
});
|
|
56637
57265
|
|
|
56638
57266
|
// src/tools/index.ts
|
|
56639
57267
|
init_lint();
|
|
@@ -56644,7 +57272,7 @@ init_config();
|
|
|
56644
57272
|
init_schema();
|
|
56645
57273
|
init_manager();
|
|
56646
57274
|
import * as fs31 from "fs";
|
|
56647
|
-
import * as
|
|
57275
|
+
import * as path45 from "path";
|
|
56648
57276
|
init_utils2();
|
|
56649
57277
|
init_create_tool();
|
|
56650
57278
|
function safeWarn(message, error93) {
|
|
@@ -56701,7 +57329,7 @@ function collectCrossSessionDispatchedAgents(phaseReferenceTimestamp, callerSess
|
|
|
56701
57329
|
function isValidRetroEntry(entry, phase) {
|
|
56702
57330
|
return entry.type === "retrospective" && "phase_number" in entry && entry.phase_number === phase && "verdict" in entry && entry.verdict === "pass";
|
|
56703
57331
|
}
|
|
56704
|
-
async function executePhaseComplete(args2, workingDirectory) {
|
|
57332
|
+
async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
56705
57333
|
const phase = Number(args2.phase);
|
|
56706
57334
|
const summary = args2.summary;
|
|
56707
57335
|
const sessionID = args2.sessionID;
|
|
@@ -56729,7 +57357,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56729
57357
|
const phaseReferenceTimestamp = session.lastPhaseCompleteTimestamp ?? 0;
|
|
56730
57358
|
const crossSessionResult = collectCrossSessionDispatchedAgents(phaseReferenceTimestamp, sessionID);
|
|
56731
57359
|
const agentsDispatched = Array.from(crossSessionResult.agents).sort();
|
|
56732
|
-
const dir = workingDirectory
|
|
57360
|
+
const dir = workingDirectory || directory || process.cwd();
|
|
56733
57361
|
const { config: config3 } = loadPluginConfigWithMeta(dir);
|
|
56734
57362
|
let phaseCompleteConfig;
|
|
56735
57363
|
try {
|
|
@@ -56862,7 +57490,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56862
57490
|
};
|
|
56863
57491
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
56864
57492
|
try {
|
|
56865
|
-
const projectName =
|
|
57493
|
+
const projectName = path45.basename(dir);
|
|
56866
57494
|
await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
56867
57495
|
} catch (error93) {
|
|
56868
57496
|
safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
@@ -56874,7 +57502,17 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56874
57502
|
if (curatorConfig.enabled && curatorConfig.phase_enabled) {
|
|
56875
57503
|
const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {});
|
|
56876
57504
|
await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, knowledgeConfig);
|
|
56877
|
-
await runCriticDriftCheck(dir, phase, curatorResult, curatorConfig);
|
|
57505
|
+
const driftResult = await runCriticDriftCheck(dir, phase, curatorResult, curatorConfig);
|
|
57506
|
+
const callerSessionState = swarmState.agentSessions.get(sessionID);
|
|
57507
|
+
if (callerSessionState) {
|
|
57508
|
+
callerSessionState.pendingAdvisoryMessages ??= [];
|
|
57509
|
+
const digestSummary = curatorResult.digest?.summary ? curatorResult.digest.summary.slice(0, 200) : "Phase analysis complete";
|
|
57510
|
+
const complianceNote = curatorResult.compliance.length > 0 ? ` (${curatorResult.compliance.length} compliance observation(s))` : "";
|
|
57511
|
+
callerSessionState.pendingAdvisoryMessages.push(`[CURATOR] Phase ${phase} digest: ${digestSummary}${complianceNote}. Call curator_analyze with recommendations to apply knowledge updates from this phase.`);
|
|
57512
|
+
if (driftResult.report.drift_score > 0) {
|
|
57513
|
+
callerSessionState.pendingAdvisoryMessages.push(`[CURATOR DRIFT DETECTED (phase ${phase}, score ${driftResult.report.drift_score})]: ${driftResult.injection_text.slice(0, 300)}. Review ${driftResult.report_path} and address spec alignment before proceeding.`);
|
|
57514
|
+
}
|
|
57515
|
+
}
|
|
56878
57516
|
if (curatorResult.compliance.length > 0 && !curatorConfig.suppress_warnings) {
|
|
56879
57517
|
const complianceLines = curatorResult.compliance.map((obs) => `[${obs.severity.toUpperCase()}] ${obs.description}`).slice(0, 5);
|
|
56880
57518
|
complianceWarnings = complianceLines;
|
|
@@ -57002,7 +57640,7 @@ var phase_complete = createSwarmTool({
|
|
|
57002
57640
|
warnings: ["Failed to parse arguments"]
|
|
57003
57641
|
}, null, 2);
|
|
57004
57642
|
}
|
|
57005
|
-
return executePhaseComplete(phaseCompleteArgs, directory);
|
|
57643
|
+
return executePhaseComplete(phaseCompleteArgs, undefined, directory);
|
|
57006
57644
|
}
|
|
57007
57645
|
});
|
|
57008
57646
|
// src/tools/pkg-audit.ts
|
|
@@ -57011,7 +57649,7 @@ init_discovery();
|
|
|
57011
57649
|
init_utils();
|
|
57012
57650
|
init_create_tool();
|
|
57013
57651
|
import * as fs32 from "fs";
|
|
57014
|
-
import * as
|
|
57652
|
+
import * as path46 from "path";
|
|
57015
57653
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
57016
57654
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
57017
57655
|
function isValidEcosystem(value) {
|
|
@@ -57029,16 +57667,16 @@ function validateArgs3(args2) {
|
|
|
57029
57667
|
function detectEcosystems(directory) {
|
|
57030
57668
|
const ecosystems = [];
|
|
57031
57669
|
const cwd = directory;
|
|
57032
|
-
if (fs32.existsSync(
|
|
57670
|
+
if (fs32.existsSync(path46.join(cwd, "package.json"))) {
|
|
57033
57671
|
ecosystems.push("npm");
|
|
57034
57672
|
}
|
|
57035
|
-
if (fs32.existsSync(
|
|
57673
|
+
if (fs32.existsSync(path46.join(cwd, "pyproject.toml")) || fs32.existsSync(path46.join(cwd, "requirements.txt"))) {
|
|
57036
57674
|
ecosystems.push("pip");
|
|
57037
57675
|
}
|
|
57038
|
-
if (fs32.existsSync(
|
|
57676
|
+
if (fs32.existsSync(path46.join(cwd, "Cargo.toml"))) {
|
|
57039
57677
|
ecosystems.push("cargo");
|
|
57040
57678
|
}
|
|
57041
|
-
if (fs32.existsSync(
|
|
57679
|
+
if (fs32.existsSync(path46.join(cwd, "go.mod"))) {
|
|
57042
57680
|
ecosystems.push("go");
|
|
57043
57681
|
}
|
|
57044
57682
|
try {
|
|
@@ -57047,10 +57685,10 @@ function detectEcosystems(directory) {
|
|
|
57047
57685
|
ecosystems.push("dotnet");
|
|
57048
57686
|
}
|
|
57049
57687
|
} catch {}
|
|
57050
|
-
if (fs32.existsSync(
|
|
57688
|
+
if (fs32.existsSync(path46.join(cwd, "Gemfile")) || fs32.existsSync(path46.join(cwd, "Gemfile.lock"))) {
|
|
57051
57689
|
ecosystems.push("ruby");
|
|
57052
57690
|
}
|
|
57053
|
-
if (fs32.existsSync(
|
|
57691
|
+
if (fs32.existsSync(path46.join(cwd, "pubspec.yaml"))) {
|
|
57054
57692
|
ecosystems.push("dart");
|
|
57055
57693
|
}
|
|
57056
57694
|
return ecosystems;
|
|
@@ -57063,7 +57701,7 @@ async function runNpmAudit(directory) {
|
|
|
57063
57701
|
stderr: "pipe",
|
|
57064
57702
|
cwd: directory
|
|
57065
57703
|
});
|
|
57066
|
-
const timeoutPromise = new Promise((
|
|
57704
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), AUDIT_TIMEOUT_MS));
|
|
57067
57705
|
const result = await Promise.race([
|
|
57068
57706
|
Promise.all([
|
|
57069
57707
|
new Response(proc.stdout).text(),
|
|
@@ -57186,7 +57824,7 @@ async function runPipAudit(directory) {
|
|
|
57186
57824
|
stderr: "pipe",
|
|
57187
57825
|
cwd: directory
|
|
57188
57826
|
});
|
|
57189
|
-
const timeoutPromise = new Promise((
|
|
57827
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), AUDIT_TIMEOUT_MS));
|
|
57190
57828
|
const result = await Promise.race([
|
|
57191
57829
|
Promise.all([
|
|
57192
57830
|
new Response(proc.stdout).text(),
|
|
@@ -57317,7 +57955,7 @@ async function runCargoAudit(directory) {
|
|
|
57317
57955
|
stderr: "pipe",
|
|
57318
57956
|
cwd: directory
|
|
57319
57957
|
});
|
|
57320
|
-
const timeoutPromise = new Promise((
|
|
57958
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), AUDIT_TIMEOUT_MS));
|
|
57321
57959
|
const result = await Promise.race([
|
|
57322
57960
|
Promise.all([
|
|
57323
57961
|
new Response(proc.stdout).text(),
|
|
@@ -57444,7 +58082,7 @@ async function runGoAudit(directory) {
|
|
|
57444
58082
|
stderr: "pipe",
|
|
57445
58083
|
cwd: directory
|
|
57446
58084
|
});
|
|
57447
|
-
const timeoutPromise = new Promise((
|
|
58085
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), AUDIT_TIMEOUT_MS));
|
|
57448
58086
|
const result = await Promise.race([
|
|
57449
58087
|
Promise.all([
|
|
57450
58088
|
new Response(proc.stdout).text(),
|
|
@@ -57580,7 +58218,7 @@ async function runDotnetAudit(directory) {
|
|
|
57580
58218
|
stderr: "pipe",
|
|
57581
58219
|
cwd: directory
|
|
57582
58220
|
});
|
|
57583
|
-
const timeoutPromise = new Promise((
|
|
58221
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), AUDIT_TIMEOUT_MS));
|
|
57584
58222
|
const result = await Promise.race([
|
|
57585
58223
|
Promise.all([
|
|
57586
58224
|
new Response(proc.stdout).text(),
|
|
@@ -57699,7 +58337,7 @@ async function runBundleAudit(directory) {
|
|
|
57699
58337
|
stderr: "pipe",
|
|
57700
58338
|
cwd: directory
|
|
57701
58339
|
});
|
|
57702
|
-
const timeoutPromise = new Promise((
|
|
58340
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), AUDIT_TIMEOUT_MS));
|
|
57703
58341
|
const result = await Promise.race([
|
|
57704
58342
|
Promise.all([
|
|
57705
58343
|
new Response(proc.stdout).text(),
|
|
@@ -57846,7 +58484,7 @@ async function runDartAudit(directory) {
|
|
|
57846
58484
|
stderr: "pipe",
|
|
57847
58485
|
cwd: directory
|
|
57848
58486
|
});
|
|
57849
|
-
const timeoutPromise = new Promise((
|
|
58487
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), AUDIT_TIMEOUT_MS));
|
|
57850
58488
|
const result = await Promise.race([
|
|
57851
58489
|
Promise.all([
|
|
57852
58490
|
new Response(proc.stdout).text(),
|
|
@@ -58113,7 +58751,7 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
58113
58751
|
// src/tools/pre-check-batch.ts
|
|
58114
58752
|
init_dist();
|
|
58115
58753
|
import * as fs35 from "fs";
|
|
58116
|
-
import * as
|
|
58754
|
+
import * as path49 from "path";
|
|
58117
58755
|
|
|
58118
58756
|
// node_modules/yocto-queue/index.js
|
|
58119
58757
|
class Node2 {
|
|
@@ -58204,26 +58842,26 @@ function pLimit(concurrency) {
|
|
|
58204
58842
|
activeCount--;
|
|
58205
58843
|
resumeNext();
|
|
58206
58844
|
};
|
|
58207
|
-
const run2 = async (function_,
|
|
58845
|
+
const run2 = async (function_, resolve16, arguments_2) => {
|
|
58208
58846
|
const result = (async () => function_(...arguments_2))();
|
|
58209
|
-
|
|
58847
|
+
resolve16(result);
|
|
58210
58848
|
try {
|
|
58211
58849
|
await result;
|
|
58212
58850
|
} catch {}
|
|
58213
58851
|
next();
|
|
58214
58852
|
};
|
|
58215
|
-
const enqueue = (function_,
|
|
58853
|
+
const enqueue = (function_, resolve16, reject, arguments_2) => {
|
|
58216
58854
|
const queueItem = { reject };
|
|
58217
58855
|
new Promise((internalResolve) => {
|
|
58218
58856
|
queueItem.run = internalResolve;
|
|
58219
58857
|
queue.enqueue(queueItem);
|
|
58220
|
-
}).then(run2.bind(undefined, function_,
|
|
58858
|
+
}).then(run2.bind(undefined, function_, resolve16, arguments_2));
|
|
58221
58859
|
if (activeCount < concurrency) {
|
|
58222
58860
|
resumeNext();
|
|
58223
58861
|
}
|
|
58224
58862
|
};
|
|
58225
|
-
const generator = (function_, ...arguments_2) => new Promise((
|
|
58226
|
-
enqueue(function_,
|
|
58863
|
+
const generator = (function_, ...arguments_2) => new Promise((resolve16, reject) => {
|
|
58864
|
+
enqueue(function_, resolve16, reject, arguments_2);
|
|
58227
58865
|
});
|
|
58228
58866
|
Object.defineProperties(generator, {
|
|
58229
58867
|
activeCount: {
|
|
@@ -58281,7 +58919,7 @@ init_manager();
|
|
|
58281
58919
|
|
|
58282
58920
|
// src/quality/metrics.ts
|
|
58283
58921
|
import * as fs33 from "fs";
|
|
58284
|
-
import * as
|
|
58922
|
+
import * as path47 from "path";
|
|
58285
58923
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
58286
58924
|
var MIN_DUPLICATION_LINES = 10;
|
|
58287
58925
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -58333,7 +58971,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
58333
58971
|
let totalComplexity = 0;
|
|
58334
58972
|
const analyzedFiles = [];
|
|
58335
58973
|
for (const file3 of files) {
|
|
58336
|
-
const fullPath =
|
|
58974
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58337
58975
|
if (!fs33.existsSync(fullPath)) {
|
|
58338
58976
|
continue;
|
|
58339
58977
|
}
|
|
@@ -58456,7 +59094,7 @@ function countGoExports(content) {
|
|
|
58456
59094
|
function getExportCountForFile(filePath) {
|
|
58457
59095
|
try {
|
|
58458
59096
|
const content = fs33.readFileSync(filePath, "utf-8");
|
|
58459
|
-
const ext =
|
|
59097
|
+
const ext = path47.extname(filePath).toLowerCase();
|
|
58460
59098
|
switch (ext) {
|
|
58461
59099
|
case ".ts":
|
|
58462
59100
|
case ".tsx":
|
|
@@ -58482,7 +59120,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58482
59120
|
let totalExports = 0;
|
|
58483
59121
|
const analyzedFiles = [];
|
|
58484
59122
|
for (const file3 of files) {
|
|
58485
|
-
const fullPath =
|
|
59123
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58486
59124
|
if (!fs33.existsSync(fullPath)) {
|
|
58487
59125
|
continue;
|
|
58488
59126
|
}
|
|
@@ -58516,7 +59154,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58516
59154
|
let duplicateLines = 0;
|
|
58517
59155
|
const analyzedFiles = [];
|
|
58518
59156
|
for (const file3 of files) {
|
|
58519
|
-
const fullPath =
|
|
59157
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58520
59158
|
if (!fs33.existsSync(fullPath)) {
|
|
58521
59159
|
continue;
|
|
58522
59160
|
}
|
|
@@ -58549,8 +59187,8 @@ function countCodeLines(content) {
|
|
|
58549
59187
|
return lines.length;
|
|
58550
59188
|
}
|
|
58551
59189
|
function isTestFile(filePath) {
|
|
58552
|
-
const basename8 =
|
|
58553
|
-
const _ext =
|
|
59190
|
+
const basename8 = path47.basename(filePath);
|
|
59191
|
+
const _ext = path47.extname(filePath).toLowerCase();
|
|
58554
59192
|
const testPatterns = [
|
|
58555
59193
|
".test.",
|
|
58556
59194
|
".spec.",
|
|
@@ -58631,8 +59269,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58631
59269
|
}
|
|
58632
59270
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58633
59271
|
}
|
|
58634
|
-
function matchesGlobSegment(
|
|
58635
|
-
const normalizedPath =
|
|
59272
|
+
function matchesGlobSegment(path48, glob) {
|
|
59273
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58636
59274
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58637
59275
|
if (normalizedPath.includes("//")) {
|
|
58638
59276
|
return false;
|
|
@@ -58663,8 +59301,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58663
59301
|
function hasGlobstar(glob) {
|
|
58664
59302
|
return glob.includes("**");
|
|
58665
59303
|
}
|
|
58666
|
-
function globMatches(
|
|
58667
|
-
const normalizedPath =
|
|
59304
|
+
function globMatches(path48, glob) {
|
|
59305
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58668
59306
|
if (!glob || glob === "") {
|
|
58669
59307
|
if (normalizedPath.includes("//")) {
|
|
58670
59308
|
return false;
|
|
@@ -58700,7 +59338,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58700
59338
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58701
59339
|
let testLines = 0;
|
|
58702
59340
|
let codeLines = 0;
|
|
58703
|
-
const srcDir =
|
|
59341
|
+
const srcDir = path47.join(workingDir, "src");
|
|
58704
59342
|
if (fs33.existsSync(srcDir)) {
|
|
58705
59343
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58706
59344
|
codeLines += lines;
|
|
@@ -58708,14 +59346,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58708
59346
|
}
|
|
58709
59347
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58710
59348
|
for (const dir of possibleSrcDirs) {
|
|
58711
|
-
const dirPath =
|
|
59349
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58712
59350
|
if (fs33.existsSync(dirPath)) {
|
|
58713
59351
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58714
59352
|
codeLines += lines;
|
|
58715
59353
|
});
|
|
58716
59354
|
}
|
|
58717
59355
|
}
|
|
58718
|
-
const testsDir =
|
|
59356
|
+
const testsDir = path47.join(workingDir, "tests");
|
|
58719
59357
|
if (fs33.existsSync(testsDir)) {
|
|
58720
59358
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58721
59359
|
testLines += lines;
|
|
@@ -58723,7 +59361,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58723
59361
|
}
|
|
58724
59362
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58725
59363
|
for (const dir of possibleTestDirs) {
|
|
58726
|
-
const dirPath =
|
|
59364
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58727
59365
|
if (fs33.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58728
59366
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58729
59367
|
testLines += lines;
|
|
@@ -58738,15 +59376,15 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58738
59376
|
try {
|
|
58739
59377
|
const entries = fs33.readdirSync(dirPath, { withFileTypes: true });
|
|
58740
59378
|
for (const entry of entries) {
|
|
58741
|
-
const fullPath =
|
|
59379
|
+
const fullPath = path47.join(dirPath, entry.name);
|
|
58742
59380
|
if (entry.isDirectory()) {
|
|
58743
59381
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58744
59382
|
continue;
|
|
58745
59383
|
}
|
|
58746
59384
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58747
59385
|
} else if (entry.isFile()) {
|
|
58748
|
-
const relativePath = fullPath.replace(`${
|
|
58749
|
-
const ext =
|
|
59386
|
+
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
59387
|
+
const ext = path47.extname(entry.name).toLowerCase();
|
|
58750
59388
|
const validExts = [
|
|
58751
59389
|
".ts",
|
|
58752
59390
|
".tsx",
|
|
@@ -58997,7 +59635,7 @@ init_dist();
|
|
|
58997
59635
|
init_manager();
|
|
58998
59636
|
init_detector();
|
|
58999
59637
|
import * as fs34 from "fs";
|
|
59000
|
-
import * as
|
|
59638
|
+
import * as path48 from "path";
|
|
59001
59639
|
import { extname as extname9 } from "path";
|
|
59002
59640
|
|
|
59003
59641
|
// src/sast/rules/c.ts
|
|
@@ -59745,7 +60383,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
59745
60383
|
}
|
|
59746
60384
|
}
|
|
59747
60385
|
async function executeWithTimeout(command, args2, options) {
|
|
59748
|
-
return new Promise((
|
|
60386
|
+
return new Promise((resolve16) => {
|
|
59749
60387
|
const child = spawn2(command, args2, {
|
|
59750
60388
|
shell: false,
|
|
59751
60389
|
cwd: options.cwd
|
|
@@ -59754,7 +60392,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
59754
60392
|
let stderr = "";
|
|
59755
60393
|
const timeout = setTimeout(() => {
|
|
59756
60394
|
child.kill("SIGTERM");
|
|
59757
|
-
|
|
60395
|
+
resolve16({
|
|
59758
60396
|
stdout,
|
|
59759
60397
|
stderr: "Process timed out",
|
|
59760
60398
|
exitCode: 124
|
|
@@ -59768,7 +60406,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
59768
60406
|
});
|
|
59769
60407
|
child.on("close", (code) => {
|
|
59770
60408
|
clearTimeout(timeout);
|
|
59771
|
-
|
|
60409
|
+
resolve16({
|
|
59772
60410
|
stdout,
|
|
59773
60411
|
stderr,
|
|
59774
60412
|
exitCode: code ?? 0
|
|
@@ -59776,7 +60414,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
59776
60414
|
});
|
|
59777
60415
|
child.on("error", (err2) => {
|
|
59778
60416
|
clearTimeout(timeout);
|
|
59779
|
-
|
|
60417
|
+
resolve16({
|
|
59780
60418
|
stdout,
|
|
59781
60419
|
stderr: err2.message,
|
|
59782
60420
|
exitCode: 1
|
|
@@ -59960,7 +60598,7 @@ async function sastScan(input, directory, config3) {
|
|
|
59960
60598
|
_filesSkipped++;
|
|
59961
60599
|
continue;
|
|
59962
60600
|
}
|
|
59963
|
-
const resolvedPath =
|
|
60601
|
+
const resolvedPath = path48.isAbsolute(filePath) ? filePath : path48.resolve(directory, filePath);
|
|
59964
60602
|
if (!fs34.existsSync(resolvedPath)) {
|
|
59965
60603
|
_filesSkipped++;
|
|
59966
60604
|
continue;
|
|
@@ -60159,20 +60797,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
60159
60797
|
let resolved;
|
|
60160
60798
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
60161
60799
|
if (isWinAbs) {
|
|
60162
|
-
resolved =
|
|
60163
|
-
} else if (
|
|
60164
|
-
resolved =
|
|
60800
|
+
resolved = path49.win32.resolve(inputPath);
|
|
60801
|
+
} else if (path49.isAbsolute(inputPath)) {
|
|
60802
|
+
resolved = path49.resolve(inputPath);
|
|
60165
60803
|
} else {
|
|
60166
|
-
resolved =
|
|
60804
|
+
resolved = path49.resolve(baseDir, inputPath);
|
|
60167
60805
|
}
|
|
60168
|
-
const workspaceResolved =
|
|
60169
|
-
let
|
|
60806
|
+
const workspaceResolved = path49.resolve(workspaceDir);
|
|
60807
|
+
let relative6;
|
|
60170
60808
|
if (isWinAbs) {
|
|
60171
|
-
|
|
60809
|
+
relative6 = path49.win32.relative(workspaceResolved, resolved);
|
|
60172
60810
|
} else {
|
|
60173
|
-
|
|
60811
|
+
relative6 = path49.relative(workspaceResolved, resolved);
|
|
60174
60812
|
}
|
|
60175
|
-
if (
|
|
60813
|
+
if (relative6.startsWith("..")) {
|
|
60176
60814
|
return "path traversal detected";
|
|
60177
60815
|
}
|
|
60178
60816
|
return null;
|
|
@@ -60231,13 +60869,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
60231
60869
|
}
|
|
60232
60870
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
60233
60871
|
const isWindows = process.platform === "win32";
|
|
60234
|
-
const binDir =
|
|
60872
|
+
const binDir = path49.join(workspaceDir, "node_modules", ".bin");
|
|
60235
60873
|
const validatedFiles = [];
|
|
60236
60874
|
for (const file3 of files) {
|
|
60237
60875
|
if (typeof file3 !== "string") {
|
|
60238
60876
|
continue;
|
|
60239
60877
|
}
|
|
60240
|
-
const resolvedPath =
|
|
60878
|
+
const resolvedPath = path49.resolve(file3);
|
|
60241
60879
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
60242
60880
|
if (validationError) {
|
|
60243
60881
|
continue;
|
|
@@ -60255,10 +60893,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
60255
60893
|
}
|
|
60256
60894
|
let command;
|
|
60257
60895
|
if (linter === "biome") {
|
|
60258
|
-
const biomeBin = isWindows ?
|
|
60896
|
+
const biomeBin = isWindows ? path49.join(binDir, "biome.EXE") : path49.join(binDir, "biome");
|
|
60259
60897
|
command = [biomeBin, "check", ...validatedFiles];
|
|
60260
60898
|
} else {
|
|
60261
|
-
const eslintBin = isWindows ?
|
|
60899
|
+
const eslintBin = isWindows ? path49.join(binDir, "eslint.cmd") : path49.join(binDir, "eslint");
|
|
60262
60900
|
command = [eslintBin, ...validatedFiles];
|
|
60263
60901
|
}
|
|
60264
60902
|
try {
|
|
@@ -60395,7 +61033,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
60395
61033
|
skippedFiles++;
|
|
60396
61034
|
continue;
|
|
60397
61035
|
}
|
|
60398
|
-
const resolvedPath =
|
|
61036
|
+
const resolvedPath = path49.resolve(file3);
|
|
60399
61037
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
60400
61038
|
if (validationError) {
|
|
60401
61039
|
skippedFiles++;
|
|
@@ -60413,7 +61051,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
60413
61051
|
};
|
|
60414
61052
|
}
|
|
60415
61053
|
for (const file3 of validatedFiles) {
|
|
60416
|
-
const ext =
|
|
61054
|
+
const ext = path49.extname(file3).toLowerCase();
|
|
60417
61055
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
60418
61056
|
skippedFiles++;
|
|
60419
61057
|
continue;
|
|
@@ -60531,8 +61169,8 @@ async function runQualityBudgetWrapped(changedFiles, directory, _config) {
|
|
|
60531
61169
|
};
|
|
60532
61170
|
}
|
|
60533
61171
|
}
|
|
60534
|
-
async function runPreCheckBatch(input, workspaceDir) {
|
|
60535
|
-
const effectiveWorkspaceDir = workspaceDir || input.directory ||
|
|
61172
|
+
async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
61173
|
+
const effectiveWorkspaceDir = workspaceDir || input.directory || contextDir;
|
|
60536
61174
|
const { files, directory, sast_threshold = "medium", config: config3 } = input;
|
|
60537
61175
|
const dirError = validateDirectory3(directory, effectiveWorkspaceDir);
|
|
60538
61176
|
if (dirError) {
|
|
@@ -60572,7 +61210,7 @@ async function runPreCheckBatch(input, workspaceDir) {
|
|
|
60572
61210
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
60573
61211
|
continue;
|
|
60574
61212
|
}
|
|
60575
|
-
changedFiles.push(
|
|
61213
|
+
changedFiles.push(path49.resolve(directory, file3));
|
|
60576
61214
|
}
|
|
60577
61215
|
if (changedFiles.length === 0) {
|
|
60578
61216
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -60723,7 +61361,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
60723
61361
|
};
|
|
60724
61362
|
return JSON.stringify(errorResult, null, 2);
|
|
60725
61363
|
}
|
|
60726
|
-
const resolvedDirectory =
|
|
61364
|
+
const resolvedDirectory = path49.resolve(typedArgs.directory);
|
|
60727
61365
|
const workspaceAnchor = resolvedDirectory;
|
|
60728
61366
|
const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
|
|
60729
61367
|
if (dirError) {
|
|
@@ -60743,7 +61381,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
60743
61381
|
directory: resolvedDirectory,
|
|
60744
61382
|
sast_threshold: typedArgs.sast_threshold,
|
|
60745
61383
|
config: typedArgs.config
|
|
60746
|
-
}, workspaceAnchor);
|
|
61384
|
+
}, workspaceAnchor, directory);
|
|
60747
61385
|
return JSON.stringify(result, null, 2);
|
|
60748
61386
|
} catch (error93) {
|
|
60749
61387
|
const errorMessage = error93 instanceof Error ? error93.message : "Unknown error";
|
|
@@ -60761,21 +61399,22 @@ var pre_check_batch = createSwarmTool({
|
|
|
60761
61399
|
});
|
|
60762
61400
|
// src/tools/retrieve-summary.ts
|
|
60763
61401
|
init_dist();
|
|
61402
|
+
init_create_tool();
|
|
60764
61403
|
var RETRIEVE_MAX_BYTES = 10 * 1024 * 1024;
|
|
60765
|
-
var retrieve_summary =
|
|
61404
|
+
var retrieve_summary = createSwarmTool({
|
|
60766
61405
|
description: "Retrieve the full content of a stored tool output summary by its ID (e.g. S1, S2). Use this when a prior tool output was summarized and you need the full content.",
|
|
60767
61406
|
args: {
|
|
60768
61407
|
id: tool.schema.string().describe("The summary ID to retrieve (e.g. S1, S2, S99). Must match pattern S followed by digits."),
|
|
60769
61408
|
offset: tool.schema.number().min(0).default(0).describe("Line offset to start from (default: 0)."),
|
|
60770
61409
|
limit: tool.schema.number().min(1).max(500).default(100).describe("Number of lines to return (default: 100, max: 500).")
|
|
60771
61410
|
},
|
|
60772
|
-
async execute(args2,
|
|
60773
|
-
const
|
|
60774
|
-
const offset =
|
|
60775
|
-
const limit = Math.min(
|
|
61411
|
+
async execute(args2, directory, _ctx) {
|
|
61412
|
+
const typedArgs = args2;
|
|
61413
|
+
const offset = typedArgs.offset ?? 0;
|
|
61414
|
+
const limit = Math.min(typedArgs.limit ?? 100, 500);
|
|
60776
61415
|
let sanitizedId;
|
|
60777
61416
|
try {
|
|
60778
|
-
sanitizedId = sanitizeSummaryId(
|
|
61417
|
+
sanitizedId = sanitizeSummaryId(typedArgs.id);
|
|
60779
61418
|
} catch {
|
|
60780
61419
|
return "Error: invalid summary ID format. Expected format: S followed by digits (e.g. S1, S2, S99).";
|
|
60781
61420
|
}
|
|
@@ -60831,7 +61470,7 @@ init_tool();
|
|
|
60831
61470
|
init_manager2();
|
|
60832
61471
|
init_create_tool();
|
|
60833
61472
|
import * as fs36 from "fs";
|
|
60834
|
-
import * as
|
|
61473
|
+
import * as path50 from "path";
|
|
60835
61474
|
function detectPlaceholderContent(args2) {
|
|
60836
61475
|
const issues = [];
|
|
60837
61476
|
const placeholderPattern = /^\[\w[\w\s]*\]$/;
|
|
@@ -60935,7 +61574,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
60935
61574
|
try {
|
|
60936
61575
|
await savePlan(dir, plan);
|
|
60937
61576
|
try {
|
|
60938
|
-
const markerPath =
|
|
61577
|
+
const markerPath = path50.join(dir, ".swarm", ".plan-write-marker");
|
|
60939
61578
|
const marker = JSON.stringify({
|
|
60940
61579
|
source: "save_plan",
|
|
60941
61580
|
timestamp: new Date().toISOString(),
|
|
@@ -60947,7 +61586,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
60947
61586
|
return {
|
|
60948
61587
|
success: true,
|
|
60949
61588
|
message: "Plan saved successfully",
|
|
60950
|
-
plan_path:
|
|
61589
|
+
plan_path: path50.join(dir, ".swarm", "plan.json"),
|
|
60951
61590
|
phases_count: plan.phases.length,
|
|
60952
61591
|
tasks_count: tasksCount
|
|
60953
61592
|
};
|
|
@@ -60986,7 +61625,7 @@ var save_plan = createSwarmTool({
|
|
|
60986
61625
|
init_dist();
|
|
60987
61626
|
init_manager();
|
|
60988
61627
|
import * as fs37 from "fs";
|
|
60989
|
-
import * as
|
|
61628
|
+
import * as path51 from "path";
|
|
60990
61629
|
|
|
60991
61630
|
// src/sbom/detectors/index.ts
|
|
60992
61631
|
init_utils();
|
|
@@ -61834,7 +62473,7 @@ function findManifestFiles(rootDir) {
|
|
|
61834
62473
|
try {
|
|
61835
62474
|
const entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
61836
62475
|
for (const entry of entries) {
|
|
61837
|
-
const fullPath =
|
|
62476
|
+
const fullPath = path51.join(dir, entry.name);
|
|
61838
62477
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
61839
62478
|
continue;
|
|
61840
62479
|
}
|
|
@@ -61843,7 +62482,7 @@ function findManifestFiles(rootDir) {
|
|
|
61843
62482
|
} else if (entry.isFile()) {
|
|
61844
62483
|
for (const pattern of patterns) {
|
|
61845
62484
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
61846
|
-
manifestFiles.push(
|
|
62485
|
+
manifestFiles.push(path51.relative(rootDir, fullPath));
|
|
61847
62486
|
break;
|
|
61848
62487
|
}
|
|
61849
62488
|
}
|
|
@@ -61861,11 +62500,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
61861
62500
|
try {
|
|
61862
62501
|
const entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
61863
62502
|
for (const entry of entries) {
|
|
61864
|
-
const fullPath =
|
|
62503
|
+
const fullPath = path51.join(dir, entry.name);
|
|
61865
62504
|
if (entry.isFile()) {
|
|
61866
62505
|
for (const pattern of patterns) {
|
|
61867
62506
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
61868
|
-
found.push(
|
|
62507
|
+
found.push(path51.relative(workingDir, fullPath));
|
|
61869
62508
|
break;
|
|
61870
62509
|
}
|
|
61871
62510
|
}
|
|
@@ -61878,11 +62517,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
61878
62517
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
61879
62518
|
const dirs = new Set;
|
|
61880
62519
|
for (const file3 of changedFiles) {
|
|
61881
|
-
let currentDir =
|
|
62520
|
+
let currentDir = path51.dirname(file3);
|
|
61882
62521
|
while (true) {
|
|
61883
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
61884
|
-
dirs.add(
|
|
61885
|
-
const parent =
|
|
62522
|
+
if (currentDir && currentDir !== "." && currentDir !== path51.sep) {
|
|
62523
|
+
dirs.add(path51.join(workingDir, currentDir));
|
|
62524
|
+
const parent = path51.dirname(currentDir);
|
|
61886
62525
|
if (parent === currentDir)
|
|
61887
62526
|
break;
|
|
61888
62527
|
currentDir = parent;
|
|
@@ -61966,7 +62605,7 @@ var sbom_generate = createSwarmTool({
|
|
|
61966
62605
|
const changedFiles = obj.changed_files;
|
|
61967
62606
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
61968
62607
|
const workingDir = directory;
|
|
61969
|
-
const outputDir =
|
|
62608
|
+
const outputDir = path51.isAbsolute(relativeOutputDir) ? relativeOutputDir : path51.join(workingDir, relativeOutputDir);
|
|
61970
62609
|
let manifestFiles = [];
|
|
61971
62610
|
if (scope === "all") {
|
|
61972
62611
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -61989,7 +62628,7 @@ var sbom_generate = createSwarmTool({
|
|
|
61989
62628
|
const processedFiles = [];
|
|
61990
62629
|
for (const manifestFile of manifestFiles) {
|
|
61991
62630
|
try {
|
|
61992
|
-
const fullPath =
|
|
62631
|
+
const fullPath = path51.isAbsolute(manifestFile) ? manifestFile : path51.join(workingDir, manifestFile);
|
|
61993
62632
|
if (!fs37.existsSync(fullPath)) {
|
|
61994
62633
|
continue;
|
|
61995
62634
|
}
|
|
@@ -62006,7 +62645,7 @@ var sbom_generate = createSwarmTool({
|
|
|
62006
62645
|
const bom = generateCycloneDX(allComponents);
|
|
62007
62646
|
const bomJson = serializeCycloneDX(bom);
|
|
62008
62647
|
const filename = generateSbomFilename();
|
|
62009
|
-
const outputPath =
|
|
62648
|
+
const outputPath = path51.join(outputDir, filename);
|
|
62010
62649
|
fs37.writeFileSync(outputPath, bomJson, "utf-8");
|
|
62011
62650
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
62012
62651
|
try {
|
|
@@ -62050,7 +62689,7 @@ var sbom_generate = createSwarmTool({
|
|
|
62050
62689
|
init_dist();
|
|
62051
62690
|
init_create_tool();
|
|
62052
62691
|
import * as fs38 from "fs";
|
|
62053
|
-
import * as
|
|
62692
|
+
import * as path52 from "path";
|
|
62054
62693
|
var SPEC_CANDIDATES = [
|
|
62055
62694
|
"openapi.json",
|
|
62056
62695
|
"openapi.yaml",
|
|
@@ -62082,12 +62721,12 @@ function normalizePath2(p) {
|
|
|
62082
62721
|
}
|
|
62083
62722
|
function discoverSpecFile(cwd, specFileArg) {
|
|
62084
62723
|
if (specFileArg) {
|
|
62085
|
-
const resolvedPath =
|
|
62086
|
-
const normalizedCwd = cwd.endsWith(
|
|
62724
|
+
const resolvedPath = path52.resolve(cwd, specFileArg);
|
|
62725
|
+
const normalizedCwd = cwd.endsWith(path52.sep) ? cwd : cwd + path52.sep;
|
|
62087
62726
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
62088
62727
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
62089
62728
|
}
|
|
62090
|
-
const ext =
|
|
62729
|
+
const ext = path52.extname(resolvedPath).toLowerCase();
|
|
62091
62730
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
62092
62731
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
62093
62732
|
}
|
|
@@ -62101,7 +62740,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
62101
62740
|
return resolvedPath;
|
|
62102
62741
|
}
|
|
62103
62742
|
for (const candidate of SPEC_CANDIDATES) {
|
|
62104
|
-
const candidatePath =
|
|
62743
|
+
const candidatePath = path52.resolve(cwd, candidate);
|
|
62105
62744
|
if (fs38.existsSync(candidatePath)) {
|
|
62106
62745
|
const stats = fs38.statSync(candidatePath);
|
|
62107
62746
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -62113,7 +62752,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
62113
62752
|
}
|
|
62114
62753
|
function parseSpec(specFile) {
|
|
62115
62754
|
const content = fs38.readFileSync(specFile, "utf-8");
|
|
62116
|
-
const ext =
|
|
62755
|
+
const ext = path52.extname(specFile).toLowerCase();
|
|
62117
62756
|
if (ext === ".json") {
|
|
62118
62757
|
return parseJsonSpec(content);
|
|
62119
62758
|
}
|
|
@@ -62189,7 +62828,7 @@ function extractRoutes(cwd) {
|
|
|
62189
62828
|
return;
|
|
62190
62829
|
}
|
|
62191
62830
|
for (const entry of entries) {
|
|
62192
|
-
const fullPath =
|
|
62831
|
+
const fullPath = path52.join(dir, entry.name);
|
|
62193
62832
|
if (entry.isSymbolicLink()) {
|
|
62194
62833
|
continue;
|
|
62195
62834
|
}
|
|
@@ -62199,7 +62838,7 @@ function extractRoutes(cwd) {
|
|
|
62199
62838
|
}
|
|
62200
62839
|
walkDir(fullPath);
|
|
62201
62840
|
} else if (entry.isFile()) {
|
|
62202
|
-
const ext =
|
|
62841
|
+
const ext = path52.extname(entry.name).toLowerCase();
|
|
62203
62842
|
const baseName = entry.name.toLowerCase();
|
|
62204
62843
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
62205
62844
|
continue;
|
|
@@ -62369,7 +63008,7 @@ init_secretscan();
|
|
|
62369
63008
|
init_tool();
|
|
62370
63009
|
init_create_tool();
|
|
62371
63010
|
import * as fs39 from "fs";
|
|
62372
|
-
import * as
|
|
63011
|
+
import * as path53 from "path";
|
|
62373
63012
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
62374
63013
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
62375
63014
|
function containsControlCharacters(str) {
|
|
@@ -62398,11 +63037,11 @@ function containsWindowsAttacks(str) {
|
|
|
62398
63037
|
}
|
|
62399
63038
|
function isPathInWorkspace(filePath, workspace) {
|
|
62400
63039
|
try {
|
|
62401
|
-
const resolvedPath =
|
|
63040
|
+
const resolvedPath = path53.resolve(workspace, filePath);
|
|
62402
63041
|
const realWorkspace = fs39.realpathSync(workspace);
|
|
62403
63042
|
const realResolvedPath = fs39.realpathSync(resolvedPath);
|
|
62404
|
-
const relativePath =
|
|
62405
|
-
if (relativePath.startsWith("..") ||
|
|
63043
|
+
const relativePath = path53.relative(realWorkspace, realResolvedPath);
|
|
63044
|
+
if (relativePath.startsWith("..") || path53.isAbsolute(relativePath)) {
|
|
62406
63045
|
return false;
|
|
62407
63046
|
}
|
|
62408
63047
|
return true;
|
|
@@ -62414,7 +63053,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
62414
63053
|
return isPathInWorkspace(filePath, workspace);
|
|
62415
63054
|
}
|
|
62416
63055
|
function extractTSSymbols(filePath, cwd) {
|
|
62417
|
-
const fullPath =
|
|
63056
|
+
const fullPath = path53.join(cwd, filePath);
|
|
62418
63057
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
62419
63058
|
return [];
|
|
62420
63059
|
}
|
|
@@ -62566,7 +63205,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
62566
63205
|
});
|
|
62567
63206
|
}
|
|
62568
63207
|
function extractPythonSymbols(filePath, cwd) {
|
|
62569
|
-
const fullPath =
|
|
63208
|
+
const fullPath = path53.join(cwd, filePath);
|
|
62570
63209
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
62571
63210
|
return [];
|
|
62572
63211
|
}
|
|
@@ -62649,7 +63288,7 @@ var symbols = createSwarmTool({
|
|
|
62649
63288
|
}, null, 2);
|
|
62650
63289
|
}
|
|
62651
63290
|
const cwd = directory;
|
|
62652
|
-
const ext =
|
|
63291
|
+
const ext = path53.extname(file3);
|
|
62653
63292
|
if (containsControlCharacters(file3)) {
|
|
62654
63293
|
return JSON.stringify({
|
|
62655
63294
|
file: file3,
|
|
@@ -62721,7 +63360,7 @@ init_dist();
|
|
|
62721
63360
|
init_utils();
|
|
62722
63361
|
init_create_tool();
|
|
62723
63362
|
import * as fs40 from "fs";
|
|
62724
|
-
import * as
|
|
63363
|
+
import * as path54 from "path";
|
|
62725
63364
|
var MAX_TEXT_LENGTH = 200;
|
|
62726
63365
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
62727
63366
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -62792,9 +63431,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
62792
63431
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
62793
63432
|
}
|
|
62794
63433
|
try {
|
|
62795
|
-
const resolvedPath =
|
|
62796
|
-
const normalizedCwd =
|
|
62797
|
-
const normalizedResolved =
|
|
63434
|
+
const resolvedPath = path54.resolve(paths);
|
|
63435
|
+
const normalizedCwd = path54.resolve(cwd);
|
|
63436
|
+
const normalizedResolved = path54.resolve(resolvedPath);
|
|
62798
63437
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
62799
63438
|
return {
|
|
62800
63439
|
error: "paths must be within the current working directory",
|
|
@@ -62810,7 +63449,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
62810
63449
|
}
|
|
62811
63450
|
}
|
|
62812
63451
|
function isSupportedExtension(filePath) {
|
|
62813
|
-
const ext =
|
|
63452
|
+
const ext = path54.extname(filePath).toLowerCase();
|
|
62814
63453
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
62815
63454
|
}
|
|
62816
63455
|
function findSourceFiles2(dir, files = []) {
|
|
@@ -62825,7 +63464,7 @@ function findSourceFiles2(dir, files = []) {
|
|
|
62825
63464
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
62826
63465
|
continue;
|
|
62827
63466
|
}
|
|
62828
|
-
const fullPath =
|
|
63467
|
+
const fullPath = path54.join(dir, entry);
|
|
62829
63468
|
let stat2;
|
|
62830
63469
|
try {
|
|
62831
63470
|
stat2 = fs40.statSync(fullPath);
|
|
@@ -62937,7 +63576,7 @@ var todo_extract = createSwarmTool({
|
|
|
62937
63576
|
filesToScan.push(scanPath);
|
|
62938
63577
|
} else {
|
|
62939
63578
|
const errorResult = {
|
|
62940
|
-
error: `unsupported file extension: ${
|
|
63579
|
+
error: `unsupported file extension: ${path54.extname(scanPath)}`,
|
|
62941
63580
|
total: 0,
|
|
62942
63581
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
62943
63582
|
entries: []
|
|
@@ -62983,14 +63622,14 @@ var todo_extract = createSwarmTool({
|
|
|
62983
63622
|
init_tool();
|
|
62984
63623
|
init_schema();
|
|
62985
63624
|
import * as fs42 from "fs";
|
|
62986
|
-
import * as
|
|
63625
|
+
import * as path56 from "path";
|
|
62987
63626
|
|
|
62988
63627
|
// src/hooks/diff-scope.ts
|
|
62989
63628
|
import * as fs41 from "fs";
|
|
62990
|
-
import * as
|
|
63629
|
+
import * as path55 from "path";
|
|
62991
63630
|
function getDeclaredScope(taskId, directory) {
|
|
62992
63631
|
try {
|
|
62993
|
-
const planPath =
|
|
63632
|
+
const planPath = path55.join(directory, ".swarm", "plan.json");
|
|
62994
63633
|
if (!fs41.existsSync(planPath))
|
|
62995
63634
|
return null;
|
|
62996
63635
|
const raw = fs41.readFileSync(planPath, "utf-8");
|
|
@@ -63105,7 +63744,7 @@ var TIER_3_PATTERNS = [
|
|
|
63105
63744
|
];
|
|
63106
63745
|
function matchesTier3Pattern(files) {
|
|
63107
63746
|
for (const file3 of files) {
|
|
63108
|
-
const fileName =
|
|
63747
|
+
const fileName = path56.basename(file3);
|
|
63109
63748
|
for (const pattern of TIER_3_PATTERNS) {
|
|
63110
63749
|
if (pattern.test(fileName)) {
|
|
63111
63750
|
return true;
|
|
@@ -63127,7 +63766,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63127
63766
|
if (hasActiveTurboMode2()) {
|
|
63128
63767
|
const resolvedDir2 = workingDirectory ?? process.cwd();
|
|
63129
63768
|
try {
|
|
63130
|
-
const planPath =
|
|
63769
|
+
const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
|
|
63131
63770
|
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
63132
63771
|
const plan = JSON.parse(planRaw);
|
|
63133
63772
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -63147,7 +63786,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63147
63786
|
}
|
|
63148
63787
|
const resolvedDir = workingDirectory ?? process.cwd();
|
|
63149
63788
|
try {
|
|
63150
|
-
const evidencePath =
|
|
63789
|
+
const evidencePath = path56.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
|
|
63151
63790
|
const raw = fs42.readFileSync(evidencePath, "utf-8");
|
|
63152
63791
|
const evidence = JSON.parse(raw);
|
|
63153
63792
|
if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
|
|
@@ -63188,7 +63827,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63188
63827
|
}
|
|
63189
63828
|
try {
|
|
63190
63829
|
const resolvedDir2 = workingDirectory ?? process.cwd();
|
|
63191
|
-
const planPath =
|
|
63830
|
+
const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
|
|
63192
63831
|
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
63193
63832
|
const plan = JSON.parse(planRaw);
|
|
63194
63833
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -63370,8 +64009,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
63370
64009
|
};
|
|
63371
64010
|
}
|
|
63372
64011
|
}
|
|
63373
|
-
normalizedDir =
|
|
63374
|
-
const pathParts = normalizedDir.split(
|
|
64012
|
+
normalizedDir = path56.normalize(args2.working_directory);
|
|
64013
|
+
const pathParts = normalizedDir.split(path56.sep);
|
|
63375
64014
|
if (pathParts.includes("..")) {
|
|
63376
64015
|
return {
|
|
63377
64016
|
success: false,
|
|
@@ -63381,10 +64020,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
63381
64020
|
]
|
|
63382
64021
|
};
|
|
63383
64022
|
}
|
|
63384
|
-
const resolvedDir =
|
|
64023
|
+
const resolvedDir = path56.resolve(normalizedDir);
|
|
63385
64024
|
try {
|
|
63386
64025
|
const realPath = fs42.realpathSync(resolvedDir);
|
|
63387
|
-
const planPath =
|
|
64026
|
+
const planPath = path56.join(realPath, ".swarm", "plan.json");
|
|
63388
64027
|
if (!fs42.existsSync(planPath)) {
|
|
63389
64028
|
return {
|
|
63390
64029
|
success: false,
|
|
@@ -63405,7 +64044,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
63405
64044
|
};
|
|
63406
64045
|
}
|
|
63407
64046
|
} else {
|
|
63408
|
-
|
|
64047
|
+
if (!fallbackDir) {
|
|
64048
|
+
console.warn("[update-task-status] fallbackDir is undefined, falling back to process.cwd()");
|
|
64049
|
+
}
|
|
64050
|
+
directory = fallbackDir || process.cwd();
|
|
63409
64051
|
}
|
|
63410
64052
|
if (args2.status === "completed") {
|
|
63411
64053
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
@@ -63523,6 +64165,24 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63523
64165
|
}
|
|
63524
64166
|
const delegationHandler = createDelegationTrackerHook(config3, guardrailsConfig.enabled);
|
|
63525
64167
|
const guardrailsHooks = createGuardrailsHooks(ctx.directory, guardrailsConfig);
|
|
64168
|
+
const watchdogConfig = WatchdogConfigSchema.parse(config3.watchdog ?? {});
|
|
64169
|
+
const advisoryInjector = (sessionId, message) => {
|
|
64170
|
+
const s = swarmState.agentSessions.get(sessionId);
|
|
64171
|
+
if (s) {
|
|
64172
|
+
s.pendingAdvisoryMessages ??= [];
|
|
64173
|
+
s.pendingAdvisoryMessages.push(message);
|
|
64174
|
+
}
|
|
64175
|
+
};
|
|
64176
|
+
const scopeGuardHook = createScopeGuardHook({
|
|
64177
|
+
enabled: watchdogConfig.scope_guard,
|
|
64178
|
+
skip_in_turbo: watchdogConfig.skip_in_turbo
|
|
64179
|
+
}, ctx.directory, advisoryInjector);
|
|
64180
|
+
const delegationLedgerHook = createDelegationLedgerHook({ enabled: watchdogConfig.delegation_ledger }, ctx.directory, advisoryInjector);
|
|
64181
|
+
const selfReviewConfig = SelfReviewConfigSchema.parse(config3.self_review ?? {});
|
|
64182
|
+
const selfReviewHook = createSelfReviewHook({
|
|
64183
|
+
enabled: selfReviewConfig.enabled,
|
|
64184
|
+
skip_in_turbo: selfReviewConfig.skip_in_turbo
|
|
64185
|
+
}, advisoryInjector);
|
|
63526
64186
|
const summaryConfig = SummaryConfigSchema.parse(config3.summaries ?? {});
|
|
63527
64187
|
const toolSummarizerHook = createToolSummarizerHook(summaryConfig, ctx.directory);
|
|
63528
64188
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
@@ -63536,7 +64196,8 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63536
64196
|
enabled: true,
|
|
63537
64197
|
classThreshold: 3,
|
|
63538
64198
|
commentStripThreshold: 5,
|
|
63539
|
-
diffLineThreshold: 200
|
|
64199
|
+
diffLineThreshold: 200,
|
|
64200
|
+
importHygieneThreshold: 2
|
|
63540
64201
|
}, ctx.directory, (sessionId, message) => {
|
|
63541
64202
|
const s = swarmState.agentSessions.get(sessionId);
|
|
63542
64203
|
if (s) {
|
|
@@ -63579,7 +64240,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63579
64240
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
63580
64241
|
preflightTriggerManager = new PTM(automationConfig);
|
|
63581
64242
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
63582
|
-
const swarmDir =
|
|
64243
|
+
const swarmDir = path57.resolve(ctx.directory, ".swarm");
|
|
63583
64244
|
statusArtifact = new ASA(swarmDir);
|
|
63584
64245
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
63585
64246
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -63676,6 +64337,10 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63676
64337
|
check_gate_status,
|
|
63677
64338
|
checkpoint,
|
|
63678
64339
|
complexity_hotspots,
|
|
64340
|
+
curator_analyze,
|
|
64341
|
+
knowledgeAdd,
|
|
64342
|
+
knowledgeRecall,
|
|
64343
|
+
knowledgeRemove,
|
|
63679
64344
|
detect_domains,
|
|
63680
64345
|
evidence_check,
|
|
63681
64346
|
extract_code_blocks,
|
|
@@ -63805,6 +64470,20 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63805
64470
|
});
|
|
63806
64471
|
},
|
|
63807
64472
|
"experimental.chat.messages.transform": composeHandlers(...[
|
|
64473
|
+
(input, _output) => {
|
|
64474
|
+
const p = input;
|
|
64475
|
+
if (p.sessionID) {
|
|
64476
|
+
const archAgent = swarmState.activeAgent.get(p.sessionID);
|
|
64477
|
+
const archSession = swarmState.agentSessions.get(p.sessionID);
|
|
64478
|
+
const agentName = archAgent ?? archSession?.agentName ?? "";
|
|
64479
|
+
if (stripKnownSwarmPrefix(agentName) === ORCHESTRATOR_NAME) {
|
|
64480
|
+
try {
|
|
64481
|
+
delegationLedgerHook.onArchitectResume(p.sessionID);
|
|
64482
|
+
} catch {}
|
|
64483
|
+
}
|
|
64484
|
+
}
|
|
64485
|
+
return Promise.resolve();
|
|
64486
|
+
},
|
|
63808
64487
|
pipelineHook["experimental.chat.messages.transform"],
|
|
63809
64488
|
contextBudgetHandler,
|
|
63810
64489
|
guardrailsHooks.messagesTransform,
|
|
@@ -63841,6 +64520,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63841
64520
|
}
|
|
63842
64521
|
}
|
|
63843
64522
|
await guardrailsHooks.toolBefore(input, output);
|
|
64523
|
+
await scopeGuardHook.toolBefore(input, output);
|
|
63844
64524
|
if (swarmState.lastBudgetPct >= 50) {
|
|
63845
64525
|
const pressureSession = ensureAgentSession(input.sessionID, swarmState.activeAgent.get(input.sessionID) ?? ORCHESTRATOR_NAME);
|
|
63846
64526
|
if (!pressureSession.contextPressureWarningSent) {
|
|
@@ -63854,6 +64534,8 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63854
64534
|
"tool.execute.after": async (input, output) => {
|
|
63855
64535
|
await activityHooks.toolAfter(input, output);
|
|
63856
64536
|
await guardrailsHooks.toolAfter(input, output);
|
|
64537
|
+
await safeHook(delegationLedgerHook.toolAfter)(input, output);
|
|
64538
|
+
await safeHook(selfReviewHook.toolAfter)(input, output);
|
|
63857
64539
|
await safeHook(delegationGateHooks.toolAfter)(input, output);
|
|
63858
64540
|
if (knowledgeCuratorHook)
|
|
63859
64541
|
await safeHook(knowledgeCuratorHook)(input, output);
|