opencode-swarm 7.99.5 → 7.99.7
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/{evidence-summary-service-5ww1npaa.js → evidence-summary-service-ch74hb16.js} +2 -2
- package/dist/cli/{guardrail-explain-2q5q86jv.js → guardrail-explain-dkh5f7nf.js} +5 -5
- package/dist/cli/{index-94qwbx11.js → index-7ztmmqpt.js} +6 -0
- package/dist/cli/{index-s3esnz7m.js → index-e9n3xsk0.js} +1 -1
- package/dist/cli/{index-s0nsx5v6.js → index-sz3kw59p.js} +5 -5
- package/dist/cli/{index-gjyrjr08.js → index-wpnam1jh.js} +53 -36
- package/dist/cli/{index-9twtnjkv.js → index-y3x3gvy6.js} +1 -1
- package/dist/cli/{index-tn5exv94.js → index-zyhd4mnn.js} +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/cli/{pending-delegations-vh2nae3n.js → pending-delegations-dvprsdfy.js} +1 -1
- package/dist/cli/{pr-subscriptions-d57tq0c0.js → pr-subscriptions-zfxjtyzw.js} +2 -2
- package/dist/commands/registry.d.ts +2 -0
- package/dist/hooks/utils.d.ts +8 -3
- package/dist/index.js +476 -113
- package/dist/services/version-check.d.ts +0 -4
- package/dist/tools/repo-graph/builder.d.ts +7 -5
- package/dist/tools/repo-graph/query.d.ts +2 -1
- package/dist/tools/repo-graph/types.d.ts +37 -0
- package/dist/tools/repo-graph.d.ts +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var package_default;
|
|
|
69
69
|
var init_package = __esm(() => {
|
|
70
70
|
package_default = {
|
|
71
71
|
name: "opencode-swarm",
|
|
72
|
-
version: "7.99.
|
|
72
|
+
version: "7.99.7",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -17516,21 +17516,6 @@ var init_bundled_skills = __esm(() => {
|
|
|
17516
17516
|
syncedProjectSkillTargets = new Set;
|
|
17517
17517
|
});
|
|
17518
17518
|
|
|
17519
|
-
// src/utils/errors.ts
|
|
17520
|
-
var SwarmError;
|
|
17521
|
-
var init_errors3 = __esm(() => {
|
|
17522
|
-
SwarmError = class SwarmError extends Error {
|
|
17523
|
-
code;
|
|
17524
|
-
guidance;
|
|
17525
|
-
constructor(message, code, guidance) {
|
|
17526
|
-
super(message);
|
|
17527
|
-
this.name = "SwarmError";
|
|
17528
|
-
this.code = code;
|
|
17529
|
-
this.guidance = guidance;
|
|
17530
|
-
}
|
|
17531
|
-
};
|
|
17532
|
-
});
|
|
17533
|
-
|
|
17534
17519
|
// src/utils/logger.ts
|
|
17535
17520
|
function isDebug() {
|
|
17536
17521
|
return process.env.OPENCODE_SWARM_DEBUG === "1";
|
|
@@ -17573,6 +17558,21 @@ function error48(message, data) {
|
|
|
17573
17558
|
}
|
|
17574
17559
|
var init_logger = () => {};
|
|
17575
17560
|
|
|
17561
|
+
// src/utils/errors.ts
|
|
17562
|
+
var SwarmError;
|
|
17563
|
+
var init_errors3 = __esm(() => {
|
|
17564
|
+
SwarmError = class SwarmError extends Error {
|
|
17565
|
+
code;
|
|
17566
|
+
guidance;
|
|
17567
|
+
constructor(message, code, guidance) {
|
|
17568
|
+
super(message);
|
|
17569
|
+
this.name = "SwarmError";
|
|
17570
|
+
this.code = code;
|
|
17571
|
+
this.guidance = guidance;
|
|
17572
|
+
}
|
|
17573
|
+
};
|
|
17574
|
+
});
|
|
17575
|
+
|
|
17576
17576
|
// src/utils/regex.ts
|
|
17577
17577
|
function escapeRegex2(s) {
|
|
17578
17578
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -18141,6 +18141,9 @@ var init_swarm_artifact_cache = __esm(() => {
|
|
|
18141
18141
|
// src/hooks/utils.ts
|
|
18142
18142
|
import * as fs4 from "node:fs";
|
|
18143
18143
|
import * as path5 from "node:path";
|
|
18144
|
+
function isFailClosedHandler(value) {
|
|
18145
|
+
return typeof value === "function" && Object.hasOwn(value, "__failClosed") && value.__failClosed === true;
|
|
18146
|
+
}
|
|
18144
18147
|
function safeHook(fn2) {
|
|
18145
18148
|
return async (input, output) => {
|
|
18146
18149
|
try {
|
|
@@ -18162,6 +18165,9 @@ function composeHandlers(...fns) {
|
|
|
18162
18165
|
}
|
|
18163
18166
|
return async (input, output) => {
|
|
18164
18167
|
for (const fn2 of fns) {
|
|
18168
|
+
if (isFailClosedHandler(fn2)) {
|
|
18169
|
+
throw new Error("composeHandlers cannot wrap fail-closed handlers; use composeBlockingHandlers or await them directly");
|
|
18170
|
+
}
|
|
18165
18171
|
const safeFn = _internals3.safeHook(fn2);
|
|
18166
18172
|
await safeFn(input, output);
|
|
18167
18173
|
}
|
|
@@ -43377,6 +43383,10 @@ function createToolBeforeHandler(ctx) {
|
|
|
43377
43383
|
return;
|
|
43378
43384
|
const executor = await getExecutor();
|
|
43379
43385
|
if (!executor || !executor.isAvailable()) {
|
|
43386
|
+
if (!hasWarnedSandboxUnavailable) {
|
|
43387
|
+
hasWarnedSandboxUnavailable = true;
|
|
43388
|
+
warn("[guardrails] sandbox executor unavailable; shell commands will run unsandboxed");
|
|
43389
|
+
}
|
|
43380
43390
|
appendGuardrailDecision({
|
|
43381
43391
|
type: "sandbox_skip",
|
|
43382
43392
|
ts: new Date().toISOString(),
|
|
@@ -43875,6 +43885,15 @@ function createToolBeforeHandler(ctx) {
|
|
|
43875
43885
|
handleDelegatedWriteTracking(input.sessionID, input.tool, output.args);
|
|
43876
43886
|
handleLoopDetection(input.sessionID, input.tool, output.args);
|
|
43877
43887
|
handleTestSuiteBlocking(input.tool, output.args);
|
|
43888
|
+
const agentNameForSandbox = (() => {
|
|
43889
|
+
const rawAgent = swarmState.activeAgent.get(input.sessionID);
|
|
43890
|
+
return rawAgent ? stripKnownSwarmPrefix(rawAgent) : "unknown";
|
|
43891
|
+
})();
|
|
43892
|
+
const rawShellCommand = (() => {
|
|
43893
|
+
const bashArgs = output.args;
|
|
43894
|
+
return typeof bashArgs?.command === "string" ? bashArgs.command : "";
|
|
43895
|
+
})();
|
|
43896
|
+
await applySandboxExecution(input.sessionID, input.tool, output.args, agentNameForSandbox, rawShellCommand, shellAuditPath, shellAuditEnabled);
|
|
43878
43897
|
const normalizedAuditTool = normalizeToolName(input.tool).toLowerCase();
|
|
43879
43898
|
if (normalizedAuditTool === "bash" || normalizedAuditTool === "shell") {
|
|
43880
43899
|
appendGuardrailDecision({
|
|
@@ -44221,17 +44240,10 @@ function createToolBeforeHandler(ctx) {
|
|
|
44221
44240
|
elapsedMinutes,
|
|
44222
44241
|
repetitionCount
|
|
44223
44242
|
});
|
|
44224
|
-
await applySandboxExecution(input.sessionID, input.tool, output.args, (() => {
|
|
44225
|
-
const rawAgent = swarmState.activeAgent.get(input.sessionID);
|
|
44226
|
-
return rawAgent ? stripKnownSwarmPrefix(rawAgent) : "unknown";
|
|
44227
|
-
})(), (() => {
|
|
44228
|
-
const bashArgs = output.args;
|
|
44229
|
-
const rawCmd = typeof bashArgs?.command === "string" ? bashArgs.command : "";
|
|
44230
|
-
return rawCmd;
|
|
44231
|
-
})(), shellAuditPath, shellAuditEnabled);
|
|
44232
44243
|
setStoredInputArgs(input.callID, output.args);
|
|
44233
44244
|
};
|
|
44234
44245
|
}
|
|
44246
|
+
var hasWarnedSandboxUnavailable = false;
|
|
44235
44247
|
var init_tool_before = __esm(() => {
|
|
44236
44248
|
init_tool_policy();
|
|
44237
44249
|
init_constants();
|
|
@@ -76654,26 +76666,45 @@ function writeVersionCache(entry) {
|
|
|
76654
76666
|
writeFileSync13(cacheFile(), JSON.stringify(entry, null, 2), "utf-8");
|
|
76655
76667
|
} catch {}
|
|
76656
76668
|
}
|
|
76669
|
+
function parseVersion(version3) {
|
|
76670
|
+
const trimmed = version3.trim();
|
|
76671
|
+
const match = SEMVER_REGEX.exec(trimmed);
|
|
76672
|
+
if (!match)
|
|
76673
|
+
return null;
|
|
76674
|
+
return {
|
|
76675
|
+
major: Number.parseInt(match[1], 10),
|
|
76676
|
+
minor: Number.parseInt(match[2], 10),
|
|
76677
|
+
patch: Number.parseInt(match[3], 10),
|
|
76678
|
+
prerelease: match[4] ?? null
|
|
76679
|
+
};
|
|
76680
|
+
}
|
|
76681
|
+
function normalizeVersionCandidate(version3) {
|
|
76682
|
+
if (typeof version3 !== "string")
|
|
76683
|
+
return null;
|
|
76684
|
+
const trimmed = version3.trim();
|
|
76685
|
+
return SEMVER_REGEX.test(trimmed) ? trimmed : null;
|
|
76686
|
+
}
|
|
76657
76687
|
function compareVersions(a, b) {
|
|
76658
|
-
const
|
|
76659
|
-
const
|
|
76660
|
-
|
|
76661
|
-
|
|
76662
|
-
|
|
76663
|
-
|
|
76664
|
-
const av = aParts[i] ?? 0;
|
|
76665
|
-
const bv = bParts[i] ?? 0;
|
|
76666
|
-
if (av > bv)
|
|
76667
|
-
return 1;
|
|
76668
|
-
if (av < bv)
|
|
76669
|
-
return -1;
|
|
76688
|
+
const aParsed = parseVersion(a);
|
|
76689
|
+
const bParsed = parseVersion(b);
|
|
76690
|
+
if (!aParsed || !bParsed)
|
|
76691
|
+
return 0;
|
|
76692
|
+
if (aParsed.major !== bParsed.major) {
|
|
76693
|
+
return aParsed.major > bParsed.major ? 1 : -1;
|
|
76670
76694
|
}
|
|
76671
|
-
if (
|
|
76695
|
+
if (aParsed.minor !== bParsed.minor) {
|
|
76696
|
+
return aParsed.minor > bParsed.minor ? 1 : -1;
|
|
76697
|
+
}
|
|
76698
|
+
if (aParsed.patch !== bParsed.patch) {
|
|
76699
|
+
return aParsed.patch > bParsed.patch ? 1 : -1;
|
|
76700
|
+
}
|
|
76701
|
+
if (aParsed.prerelease && !bParsed.prerelease)
|
|
76672
76702
|
return -1;
|
|
76673
|
-
if (!
|
|
76703
|
+
if (!aParsed.prerelease && bParsed.prerelease)
|
|
76674
76704
|
return 1;
|
|
76675
|
-
if (
|
|
76676
|
-
return
|
|
76705
|
+
if (aParsed.prerelease && bParsed.prerelease) {
|
|
76706
|
+
return aParsed.prerelease < bParsed.prerelease ? -1 : aParsed.prerelease > bParsed.prerelease ? 1 : 0;
|
|
76707
|
+
}
|
|
76677
76708
|
return 0;
|
|
76678
76709
|
}
|
|
76679
76710
|
async function fetchLatestVersion(signal) {
|
|
@@ -76731,7 +76762,8 @@ async function runVersionCheck(runningVersion, emitWarning, now, fetchImpl) {
|
|
|
76731
76762
|
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
76732
76763
|
let npmLatest = null;
|
|
76733
76764
|
try {
|
|
76734
|
-
|
|
76765
|
+
const fetchedVersion = await fetchImpl(controller.signal);
|
|
76766
|
+
npmLatest = normalizeVersionCandidate(fetchedVersion);
|
|
76735
76767
|
} finally {
|
|
76736
76768
|
clearTimeout(timeout);
|
|
76737
76769
|
}
|
|
@@ -76745,9 +76777,10 @@ function maybeWarn(runningVersion, npmLatest, emitWarning) {
|
|
|
76745
76777
|
emitWarning(`[opencode-swarm] Update available: ${runningVersion} → ${npmLatest}. ` + "OpenCode caches plugins indefinitely. Run `bunx opencode-swarm update` to refresh.");
|
|
76746
76778
|
}
|
|
76747
76779
|
}
|
|
76748
|
-
var NPM_REGISTRY_URL = "https://registry.npmjs.org/opencode-swarm/latest", CHECK_INTERVAL_MS, FETCH_TIMEOUT_MS = 5000, MAX_RESPONSE_BYTES, STRICT_SEMVER, _checkLatched = false, _internals43;
|
|
76780
|
+
var NPM_REGISTRY_URL = "https://registry.npmjs.org/opencode-swarm/latest", CHECK_INTERVAL_MS, FETCH_TIMEOUT_MS = 5000, SEMVER_REGEX, MAX_RESPONSE_BYTES, STRICT_SEMVER, _checkLatched = false, _internals43;
|
|
76749
76781
|
var init_version_check = __esm(() => {
|
|
76750
76782
|
CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
76783
|
+
SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
|
|
76751
76784
|
MAX_RESPONSE_BYTES = 256 * 1024;
|
|
76752
76785
|
STRICT_SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
76753
76786
|
_internals43 = {
|
|
@@ -101085,6 +101118,13 @@ function findSimilarCommands(query) {
|
|
|
101085
101118
|
scored.sort((a, b) => a.score - b.score);
|
|
101086
101119
|
return scored.slice(0, 3).map((s) => s.cmd);
|
|
101087
101120
|
}
|
|
101121
|
+
function emitValidationWarnings(prefix, warnings) {
|
|
101122
|
+
if (warnings.length === 0)
|
|
101123
|
+
return;
|
|
101124
|
+
warn(`${prefix}:
|
|
101125
|
+
${warnings.join(`
|
|
101126
|
+
`)}`);
|
|
101127
|
+
}
|
|
101088
101128
|
function buildDetailedHelp(commandName, entry) {
|
|
101089
101129
|
const lines = [];
|
|
101090
101130
|
lines.push(`## /swarm ${commandName}`, "");
|
|
@@ -101219,6 +101259,7 @@ function resolveCommand(tokens) {
|
|
|
101219
101259
|
var COMMAND_REGISTRY, VALID_COMMANDS, _internals15, validation;
|
|
101220
101260
|
var init_registry = __esm(() => {
|
|
101221
101261
|
init_bundled_skills();
|
|
101262
|
+
init_logger();
|
|
101222
101263
|
init_acknowledge_spec_drift();
|
|
101223
101264
|
init_agents();
|
|
101224
101265
|
init_archive();
|
|
@@ -102147,6 +102188,7 @@ Subcommands:
|
|
|
102147
102188
|
handleHelpCommand,
|
|
102148
102189
|
validateAliases,
|
|
102149
102190
|
validateToolPolicy,
|
|
102191
|
+
emitValidationWarnings,
|
|
102150
102192
|
resolveCommand,
|
|
102151
102193
|
levenshteinDistance: levenshteinDistance2,
|
|
102152
102194
|
findSimilarCommands,
|
|
@@ -102158,20 +102200,12 @@ Subcommands:
|
|
|
102158
102200
|
${validation.errors.join(`
|
|
102159
102201
|
`)}`);
|
|
102160
102202
|
}
|
|
102161
|
-
|
|
102162
|
-
console.warn(`COMMAND_REGISTRY alias warnings:
|
|
102163
|
-
${validation.warnings.join(`
|
|
102164
|
-
`)}`);
|
|
102165
|
-
}
|
|
102203
|
+
_internals15.emitValidationWarnings("COMMAND_REGISTRY alias warnings", validation.warnings);
|
|
102166
102204
|
try {
|
|
102167
102205
|
const toolPolicyValidation = _internals15.validateToolPolicy();
|
|
102168
|
-
|
|
102169
|
-
console.warn(`COMMAND_REGISTRY toolPolicy warnings:
|
|
102170
|
-
${toolPolicyValidation.warnings.join(`
|
|
102171
|
-
`)}`);
|
|
102172
|
-
}
|
|
102206
|
+
_internals15.emitValidationWarnings("COMMAND_REGISTRY toolPolicy warnings", toolPolicyValidation.warnings);
|
|
102173
102207
|
} catch (e) {
|
|
102174
|
-
|
|
102208
|
+
warn(`COMMAND_REGISTRY toolPolicy validation failed (non-fatal): ${e.message}`);
|
|
102175
102209
|
}
|
|
102176
102210
|
});
|
|
102177
102211
|
|
|
@@ -116575,6 +116609,7 @@ var SUPPORTED_EXTENSIONS = new Set(LANGUAGE_REGISTRY.getAll().filter((p) => !p.p
|
|
|
116575
116609
|
var DEFAULT_WALK_FILE_CAP = 1e4;
|
|
116576
116610
|
var DEFAULT_WALK_BUDGET_MS = 5000;
|
|
116577
116611
|
var ASYNC_WALK_YIELD_INTERVAL = 200;
|
|
116612
|
+
var MAX_DIAGNOSTIC_ENTRIES = 200;
|
|
116578
116613
|
var EXTENSION_TO_LANGUAGE = {};
|
|
116579
116614
|
for (const profile of LANGUAGE_REGISTRY.getAll()) {
|
|
116580
116615
|
if (profile.parserOnly)
|
|
@@ -116705,6 +116740,64 @@ function isRefusedWorkspaceRoot(target) {
|
|
|
116705
116740
|
}
|
|
116706
116741
|
return refused.has(resolved);
|
|
116707
116742
|
}
|
|
116743
|
+
function createEmptyDiagnostics() {
|
|
116744
|
+
return {
|
|
116745
|
+
extractionFailures: [],
|
|
116746
|
+
unresolvedImports: [],
|
|
116747
|
+
oversizedFiles: [],
|
|
116748
|
+
unsupportedFiles: [],
|
|
116749
|
+
binaryFiles: [],
|
|
116750
|
+
unreadableFiles: [],
|
|
116751
|
+
lowConfidenceEdgeCount: 0
|
|
116752
|
+
};
|
|
116753
|
+
}
|
|
116754
|
+
function diagnosticsHaveEntries(diagnostics) {
|
|
116755
|
+
return (diagnostics.extractionFailures?.length ?? 0) > 0 || (diagnostics.unresolvedImports?.length ?? 0) > 0 || (diagnostics.oversizedFiles?.length ?? 0) > 0 || (diagnostics.unsupportedFiles?.length ?? 0) > 0 || (diagnostics.binaryFiles?.length ?? 0) > 0 || (diagnostics.unreadableFiles?.length ?? 0) > 0 || (diagnostics.lowConfidenceEdgeCount ?? 0) > 0;
|
|
116756
|
+
}
|
|
116757
|
+
function pushCapped(target, value) {
|
|
116758
|
+
if (target.length < MAX_DIAGNOSTIC_ENTRIES) {
|
|
116759
|
+
target.push(value);
|
|
116760
|
+
}
|
|
116761
|
+
}
|
|
116762
|
+
function mergeDiagnostics(target, source) {
|
|
116763
|
+
if (!source)
|
|
116764
|
+
return;
|
|
116765
|
+
for (const entry of source.extractionFailures ?? []) {
|
|
116766
|
+
pushCapped(target.extractionFailures, entry);
|
|
116767
|
+
}
|
|
116768
|
+
for (const entry of source.unresolvedImports ?? []) {
|
|
116769
|
+
pushCapped(target.unresolvedImports, entry);
|
|
116770
|
+
}
|
|
116771
|
+
for (const entry of source.oversizedFiles ?? []) {
|
|
116772
|
+
pushCapped(target.oversizedFiles, entry);
|
|
116773
|
+
}
|
|
116774
|
+
for (const entry of source.unsupportedFiles ?? []) {
|
|
116775
|
+
pushCapped(target.unsupportedFiles, entry);
|
|
116776
|
+
}
|
|
116777
|
+
for (const entry of source.binaryFiles ?? []) {
|
|
116778
|
+
pushCapped(target.binaryFiles, entry);
|
|
116779
|
+
}
|
|
116780
|
+
for (const entry of source.unreadableFiles ?? []) {
|
|
116781
|
+
pushCapped(target.unreadableFiles, entry);
|
|
116782
|
+
}
|
|
116783
|
+
target.lowConfidenceEdgeCount += source.lowConfidenceEdgeCount ?? 0;
|
|
116784
|
+
}
|
|
116785
|
+
function isRelativeImportSpecifier(specifier) {
|
|
116786
|
+
return specifier === "." || specifier === ".." || specifier.startsWith("./") || specifier.startsWith("../");
|
|
116787
|
+
}
|
|
116788
|
+
function unresolvedRelativeImportsFor(parsedImports, filePath, absoluteRoot) {
|
|
116789
|
+
const unresolved = [];
|
|
116790
|
+
const moduleName = toModuleName(filePath, absoluteRoot);
|
|
116791
|
+
for (const parsed of parsedImports) {
|
|
116792
|
+
if (!isRelativeImportSpecifier(parsed.specifier))
|
|
116793
|
+
continue;
|
|
116794
|
+
const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
|
|
116795
|
+
if (resolvedTarget === null) {
|
|
116796
|
+
unresolved.push({ file: moduleName, specifier: parsed.specifier });
|
|
116797
|
+
}
|
|
116798
|
+
}
|
|
116799
|
+
return unresolved;
|
|
116800
|
+
}
|
|
116708
116801
|
var REGEX_ALLOWED_AFTER = new Set("(,=:[!&|?{};*+-~^<>%".split(""));
|
|
116709
116802
|
function stripComments2(content) {
|
|
116710
116803
|
let out = "";
|
|
@@ -116897,6 +116990,28 @@ function computeUsedSymbols(strippedContent, bindings) {
|
|
|
116897
116990
|
}
|
|
116898
116991
|
return [...used].sort((a, b) => a.localeCompare(b));
|
|
116899
116992
|
}
|
|
116993
|
+
function usedSymbolsForImport(parsed, strippedContent) {
|
|
116994
|
+
if (parsed.importType === "namespace" || parsed.importType === "sideeffect" || parsed.importType === "require") {
|
|
116995
|
+
return;
|
|
116996
|
+
}
|
|
116997
|
+
if (parsed.reExport) {
|
|
116998
|
+
return [...new Set(parsed.bindings.map((b) => b.imported))].sort((a, b) => a.localeCompare(b));
|
|
116999
|
+
}
|
|
117000
|
+
return computeUsedSymbols(strippedContent, parsed.bindings);
|
|
117001
|
+
}
|
|
117002
|
+
function collectExports(symbols2) {
|
|
117003
|
+
const exported = symbols2.filter((s) => s.exported);
|
|
117004
|
+
const exports = exported.map((s) => s.signature === `default ${s.name}` ? "default" : s.name);
|
|
117005
|
+
const exportLines = {};
|
|
117006
|
+
for (let i = 0;i < exported.length; i++) {
|
|
117007
|
+
const s = exported[i];
|
|
117008
|
+
const name = exports[i];
|
|
117009
|
+
if (typeof s.line === "number" && Number.isFinite(s.line) && exportLines[name] === undefined) {
|
|
117010
|
+
exportLines[name] = s.line;
|
|
117011
|
+
}
|
|
117012
|
+
}
|
|
117013
|
+
return { exports, exportLines };
|
|
117014
|
+
}
|
|
116900
117015
|
function parseImportedSymbols(matchedString, importType) {
|
|
116901
117016
|
if (importType === "namespace")
|
|
116902
117017
|
return ["*"];
|
|
@@ -117023,44 +117138,126 @@ function isBinaryContent(content) {
|
|
|
117023
117138
|
}
|
|
117024
117139
|
return false;
|
|
117025
117140
|
}
|
|
117141
|
+
function scanFile(filePath, absoluteRoot, maxFileSize) {
|
|
117142
|
+
let content;
|
|
117143
|
+
let fileStats;
|
|
117144
|
+
try {
|
|
117145
|
+
fileStats = fsSync8.statSync(filePath);
|
|
117146
|
+
if (fileStats.size > maxFileSize) {
|
|
117147
|
+
return { node: null, edges: [] };
|
|
117148
|
+
}
|
|
117149
|
+
content = fsSync8.readFileSync(filePath, "utf-8");
|
|
117150
|
+
} catch {
|
|
117151
|
+
return { node: null, edges: [] };
|
|
117152
|
+
}
|
|
117153
|
+
if (isBinaryContent(content)) {
|
|
117154
|
+
return { node: null, edges: [] };
|
|
117155
|
+
}
|
|
117156
|
+
const ext = path134.extname(filePath).toLowerCase();
|
|
117157
|
+
let exports = [];
|
|
117158
|
+
let exportLines = {};
|
|
117159
|
+
try {
|
|
117160
|
+
if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
117161
|
+
const relativePath = path134.relative(absoluteRoot, filePath);
|
|
117162
|
+
({ exports, exportLines } = collectExports(_internals82.extractTSSymbols(relativePath, absoluteRoot)));
|
|
117163
|
+
} else if (ext === ".py") {
|
|
117164
|
+
const relativePath = path134.relative(absoluteRoot, filePath);
|
|
117165
|
+
({ exports, exportLines } = collectExports(_internals82.extractPythonSymbols(relativePath, absoluteRoot)));
|
|
117166
|
+
}
|
|
117167
|
+
const parsedImports = _internals82.parseFileImports(content);
|
|
117168
|
+
const strippedForUsage = parsedImports.length > 0 ? _internals82.stripComments(content) : "";
|
|
117169
|
+
const moduleName = toModuleName(filePath, absoluteRoot);
|
|
117170
|
+
const node = {
|
|
117171
|
+
filePath,
|
|
117172
|
+
moduleName,
|
|
117173
|
+
exports,
|
|
117174
|
+
...Object.keys(exportLines).length > 0 ? { exportLines } : {},
|
|
117175
|
+
imports: parsedImports.map((p) => p.specifier),
|
|
117176
|
+
language: getLanguage(filePath),
|
|
117177
|
+
mtime: fileStats.mtime.toISOString(),
|
|
117178
|
+
ontology: _internals82.extractFileOntology({
|
|
117179
|
+
moduleName,
|
|
117180
|
+
filePath,
|
|
117181
|
+
content,
|
|
117182
|
+
language: getLanguage(filePath),
|
|
117183
|
+
exports,
|
|
117184
|
+
imports: parsedImports.map((p) => p.specifier)
|
|
117185
|
+
})
|
|
117186
|
+
};
|
|
117187
|
+
const edges = [];
|
|
117188
|
+
const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
|
|
117189
|
+
for (const parsed of sortedImports) {
|
|
117190
|
+
const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
|
|
117191
|
+
if (resolvedTarget !== null) {
|
|
117192
|
+
const usedSymbols = usedSymbolsForImport(parsed, strippedForUsage);
|
|
117193
|
+
edges.push({
|
|
117194
|
+
source: filePath,
|
|
117195
|
+
target: resolvedTarget,
|
|
117196
|
+
importSpecifier: parsed.specifier,
|
|
117197
|
+
importType: parsed.importType,
|
|
117198
|
+
importedSymbols: parsed.importedSymbols,
|
|
117199
|
+
...usedSymbols !== undefined ? { usedSymbols } : {}
|
|
117200
|
+
});
|
|
117201
|
+
}
|
|
117202
|
+
}
|
|
117203
|
+
return { node, edges };
|
|
117204
|
+
} catch {
|
|
117205
|
+
return { node: null, edges: [] };
|
|
117206
|
+
}
|
|
117207
|
+
}
|
|
117026
117208
|
async function scanFileAsync(filePath, absoluteRoot, maxFileSize) {
|
|
117027
117209
|
let content;
|
|
117028
117210
|
let fileStats;
|
|
117029
117211
|
try {
|
|
117030
117212
|
fileStats = fsSync8.statSync(filePath);
|
|
117031
117213
|
if (fileStats.size > maxFileSize) {
|
|
117032
|
-
return {
|
|
117214
|
+
return {
|
|
117215
|
+
node: null,
|
|
117216
|
+
edges: [],
|
|
117217
|
+
symbolEdges: [],
|
|
117218
|
+
diagnostics: { oversizedFiles: [toModuleName(filePath, absoluteRoot)] }
|
|
117219
|
+
};
|
|
117033
117220
|
}
|
|
117034
117221
|
content = fsSync8.readFileSync(filePath, "utf-8");
|
|
117035
117222
|
} catch {
|
|
117036
|
-
return {
|
|
117223
|
+
return {
|
|
117224
|
+
node: null,
|
|
117225
|
+
edges: [],
|
|
117226
|
+
symbolEdges: [],
|
|
117227
|
+
diagnostics: { unreadableFiles: [toModuleName(filePath, absoluteRoot)] }
|
|
117228
|
+
};
|
|
117037
117229
|
}
|
|
117038
117230
|
if (isBinaryContent(content)) {
|
|
117039
|
-
return {
|
|
117231
|
+
return {
|
|
117232
|
+
node: null,
|
|
117233
|
+
edges: [],
|
|
117234
|
+
symbolEdges: [],
|
|
117235
|
+
diagnostics: { binaryFiles: [toModuleName(filePath, absoluteRoot)] }
|
|
117236
|
+
};
|
|
117040
117237
|
}
|
|
117041
117238
|
const grammarId = getLanguage(filePath);
|
|
117042
117239
|
const facts = await _internals82.extractFileSymbols(grammarId, content);
|
|
117043
117240
|
if (facts === null) {
|
|
117044
|
-
const
|
|
117241
|
+
const fallback = scanFile(filePath, absoluteRoot, maxFileSize);
|
|
117242
|
+
let parsedImports = [];
|
|
117243
|
+
try {
|
|
117244
|
+
parsedImports = _internals82.parseFileImports(content);
|
|
117245
|
+
} catch {
|
|
117246
|
+
parsedImports = [];
|
|
117247
|
+
}
|
|
117045
117248
|
return {
|
|
117046
|
-
|
|
117047
|
-
|
|
117048
|
-
|
|
117049
|
-
|
|
117050
|
-
|
|
117051
|
-
|
|
117052
|
-
|
|
117053
|
-
|
|
117054
|
-
|
|
117055
|
-
|
|
117056
|
-
|
|
117057
|
-
|
|
117058
|
-
exports: [],
|
|
117059
|
-
imports: []
|
|
117060
|
-
})
|
|
117061
|
-
},
|
|
117062
|
-
edges: [],
|
|
117063
|
-
symbolEdges: []
|
|
117249
|
+
...fallback,
|
|
117250
|
+
symbolEdges: [],
|
|
117251
|
+
diagnostics: {
|
|
117252
|
+
extractionFailures: [
|
|
117253
|
+
{
|
|
117254
|
+
file: toModuleName(filePath, absoluteRoot),
|
|
117255
|
+
language: grammarId,
|
|
117256
|
+
reason: "symbol_extraction_failed"
|
|
117257
|
+
}
|
|
117258
|
+
],
|
|
117259
|
+
unresolvedImports: unresolvedRelativeImportsFor(parsedImports, filePath, absoluteRoot)
|
|
117260
|
+
}
|
|
117064
117261
|
};
|
|
117065
117262
|
}
|
|
117066
117263
|
const exportedDefs = facts.defs.filter((d) => d.exported);
|
|
@@ -117111,6 +117308,10 @@ async function scanFileAsync(filePath, absoluteRoot, maxFileSize) {
|
|
|
117111
117308
|
});
|
|
117112
117309
|
}
|
|
117113
117310
|
}
|
|
117311
|
+
const unresolvedImports = sortedImports.filter((imp) => isRelativeImportSpecifier(imp.specifier)).filter((imp) => resolveModuleSpecifier(absoluteRoot, filePath, imp.specifier) === null).map((imp) => ({
|
|
117312
|
+
file: moduleName,
|
|
117313
|
+
specifier: imp.specifier
|
|
117314
|
+
}));
|
|
117114
117315
|
const symbolEdges = [];
|
|
117115
117316
|
const localToImported = new Map;
|
|
117116
117317
|
for (const imp of facts.imports) {
|
|
@@ -117141,7 +117342,12 @@ async function scanFileAsync(filePath, absoluteRoot, maxFileSize) {
|
|
|
117141
117342
|
toSymbol: mapping.imported
|
|
117142
117343
|
});
|
|
117143
117344
|
}
|
|
117144
|
-
return {
|
|
117345
|
+
return {
|
|
117346
|
+
node,
|
|
117347
|
+
edges,
|
|
117348
|
+
symbolEdges,
|
|
117349
|
+
diagnostics: unresolvedImports.length > 0 ? { unresolvedImports } : undefined
|
|
117350
|
+
};
|
|
117145
117351
|
}
|
|
117146
117352
|
async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
117147
117353
|
validateWorkspace(workspaceRoot);
|
|
@@ -117163,6 +117369,7 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
117163
117369
|
skippedFiles: 0,
|
|
117164
117370
|
truncated: false
|
|
117165
117371
|
};
|
|
117372
|
+
const diagnostics = createEmptyDiagnostics();
|
|
117166
117373
|
const sourceFiles = await findSourceFilesAsync(absoluteRoot, stats2, {
|
|
117167
117374
|
walkBudgetMs,
|
|
117168
117375
|
maxFiles,
|
|
@@ -117183,6 +117390,7 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
117183
117390
|
let processedSinceYield = 0;
|
|
117184
117391
|
for (const filePath of sourceFiles) {
|
|
117185
117392
|
const result = await scanFileAsync(filePath, absoluteRoot, maxFileSize);
|
|
117393
|
+
mergeDiagnostics(diagnostics, result.diagnostics);
|
|
117186
117394
|
if (result.node) {
|
|
117187
117395
|
let appended = false;
|
|
117188
117396
|
try {
|
|
@@ -117223,6 +117431,7 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
117223
117431
|
if (allSymbolEdges.length > 0) {
|
|
117224
117432
|
graph.symbolEdges = allSymbolEdges;
|
|
117225
117433
|
}
|
|
117434
|
+
graph.diagnostics = diagnosticsHaveEntries(diagnostics) ? diagnostics : createEmptyDiagnostics();
|
|
117226
117435
|
if (stats2.skippedFiles > 0 || stats2.skippedDirs > 0 || stats2.truncated) {
|
|
117227
117436
|
log(`[repo-graph] Scan stats: ${stats2.filesScanned} files scanned, ` + `${stats2.skippedFiles} files skipped, ${stats2.skippedDirs} dirs skipped` + (stats2.truncated ? ", TRUNCATED" : ""));
|
|
117228
117437
|
}
|
|
@@ -117264,7 +117473,11 @@ import * as fsPromises7 from "node:fs/promises";
|
|
|
117264
117473
|
import * as path138 from "node:path";
|
|
117265
117474
|
|
|
117266
117475
|
// src/tools/repo-graph/query.ts
|
|
117476
|
+
init_path_security();
|
|
117477
|
+
import * as fsSync9 from "node:fs";
|
|
117267
117478
|
import * as path136 from "node:path";
|
|
117479
|
+
var GRAPH_HEALTH_OUTPUT_LIMIT = 50;
|
|
117480
|
+
var MAX_HEALTH_PATH_LENGTH = 500;
|
|
117268
117481
|
var cachedReverseIndex = null;
|
|
117269
117482
|
function normalizeLookupPath(input) {
|
|
117270
117483
|
return normalizeGraphPath(input).replace(/^(?:\.\/)+/, "");
|
|
@@ -117363,6 +117576,139 @@ function isGraphFresh(graph, maxAgeMs = 5 * 60 * 1000) {
|
|
|
117363
117576
|
return false;
|
|
117364
117577
|
return Date.now() - built <= maxAgeMs;
|
|
117365
117578
|
}
|
|
117579
|
+
function isSafeHealthPath(value) {
|
|
117580
|
+
if (typeof value !== "string")
|
|
117581
|
+
return false;
|
|
117582
|
+
if (value.length === 0 || value.length > MAX_HEALTH_PATH_LENGTH)
|
|
117583
|
+
return false;
|
|
117584
|
+
if (containsControlChars(value) || containsPathTraversal(value))
|
|
117585
|
+
return false;
|
|
117586
|
+
if (path136.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value))
|
|
117587
|
+
return false;
|
|
117588
|
+
return true;
|
|
117589
|
+
}
|
|
117590
|
+
function isSafeHealthText(value) {
|
|
117591
|
+
if (typeof value !== "string")
|
|
117592
|
+
return false;
|
|
117593
|
+
if (value.length === 0 || value.length > MAX_HEALTH_PATH_LENGTH)
|
|
117594
|
+
return false;
|
|
117595
|
+
if (containsControlChars(value))
|
|
117596
|
+
return false;
|
|
117597
|
+
return true;
|
|
117598
|
+
}
|
|
117599
|
+
function cap(entries) {
|
|
117600
|
+
return entries.slice(0, GRAPH_HEALTH_OUTPUT_LIMIT);
|
|
117601
|
+
}
|
|
117602
|
+
function sanitizeExtractionFailures(value) {
|
|
117603
|
+
if (!Array.isArray(value))
|
|
117604
|
+
return [];
|
|
117605
|
+
const entries = [];
|
|
117606
|
+
for (const raw of value) {
|
|
117607
|
+
if (!raw || typeof raw !== "object")
|
|
117608
|
+
continue;
|
|
117609
|
+
const entry = raw;
|
|
117610
|
+
if (isSafeHealthPath(entry.file) && isSafeHealthText(entry.language) && isSafeHealthText(entry.reason)) {
|
|
117611
|
+
entries.push({
|
|
117612
|
+
file: entry.file,
|
|
117613
|
+
language: entry.language,
|
|
117614
|
+
reason: entry.reason
|
|
117615
|
+
});
|
|
117616
|
+
}
|
|
117617
|
+
}
|
|
117618
|
+
return cap(entries);
|
|
117619
|
+
}
|
|
117620
|
+
function sanitizeUnresolvedImports(value) {
|
|
117621
|
+
if (!Array.isArray(value))
|
|
117622
|
+
return [];
|
|
117623
|
+
const entries = [];
|
|
117624
|
+
for (const raw of value) {
|
|
117625
|
+
if (!raw || typeof raw !== "object")
|
|
117626
|
+
continue;
|
|
117627
|
+
const entry = raw;
|
|
117628
|
+
if (isSafeHealthPath(entry.file) && isSafeHealthText(entry.specifier)) {
|
|
117629
|
+
entries.push({ file: entry.file, specifier: entry.specifier });
|
|
117630
|
+
}
|
|
117631
|
+
}
|
|
117632
|
+
return cap(entries);
|
|
117633
|
+
}
|
|
117634
|
+
function sanitizePathList(value) {
|
|
117635
|
+
if (!Array.isArray(value))
|
|
117636
|
+
return [];
|
|
117637
|
+
return cap(value.filter(isSafeHealthPath));
|
|
117638
|
+
}
|
|
117639
|
+
function getStaleFiles(graph, workspaceRoot) {
|
|
117640
|
+
const built = Date.parse(graph.metadata.generatedAt);
|
|
117641
|
+
if (!Number.isFinite(built))
|
|
117642
|
+
return [];
|
|
117643
|
+
const root = workspaceRoot ?? graph.workspaceRoot;
|
|
117644
|
+
const stale = [];
|
|
117645
|
+
for (const node of Object.values(graph.nodes)) {
|
|
117646
|
+
const moduleName = normalizeGraphPath(node.moduleName);
|
|
117647
|
+
if (!isSafeHealthPath(moduleName))
|
|
117648
|
+
continue;
|
|
117649
|
+
const filePath = path136.join(root, moduleName);
|
|
117650
|
+
try {
|
|
117651
|
+
if (fsSync9.statSync(filePath).mtimeMs > built) {
|
|
117652
|
+
stale.push(moduleName);
|
|
117653
|
+
if (stale.length >= GRAPH_HEALTH_OUTPUT_LIMIT)
|
|
117654
|
+
break;
|
|
117655
|
+
}
|
|
117656
|
+
} catch {}
|
|
117657
|
+
}
|
|
117658
|
+
return stale;
|
|
117659
|
+
}
|
|
117660
|
+
function getGraphHealth(graph, workspaceRoot) {
|
|
117661
|
+
if (!graph) {
|
|
117662
|
+
return {
|
|
117663
|
+
schemaVersion: null,
|
|
117664
|
+
fresh: false,
|
|
117665
|
+
staleFiles: [],
|
|
117666
|
+
extractionFailures: [],
|
|
117667
|
+
unresolvedImports: [],
|
|
117668
|
+
oversizedFiles: [],
|
|
117669
|
+
unsupportedFiles: [],
|
|
117670
|
+
binaryFiles: [],
|
|
117671
|
+
unreadableFiles: [],
|
|
117672
|
+
lowConfidenceEdgeCount: 0,
|
|
117673
|
+
notes: [
|
|
117674
|
+
'No repo graph found at .swarm/repo-graph.json. Run repo_map with action="build" first.'
|
|
117675
|
+
]
|
|
117676
|
+
};
|
|
117677
|
+
}
|
|
117678
|
+
const diagnostics = graph.diagnostics;
|
|
117679
|
+
const fresh = isGraphFresh(graph);
|
|
117680
|
+
const staleFiles = getStaleFiles(graph, workspaceRoot);
|
|
117681
|
+
const notes = [];
|
|
117682
|
+
if (!fresh || staleFiles.length > 0) {
|
|
117683
|
+
notes.push('Graph is stale. Run repo_map with action="build" to refresh.');
|
|
117684
|
+
}
|
|
117685
|
+
if (!diagnostics) {
|
|
117686
|
+
notes.push('Graph has no recorded diagnostics. Rebuild with repo_map action="build" to collect health details.');
|
|
117687
|
+
}
|
|
117688
|
+
const binaryFiles = sanitizePathList(diagnostics?.binaryFiles);
|
|
117689
|
+
const binaryCount = binaryFiles.length;
|
|
117690
|
+
if (binaryCount > 0) {
|
|
117691
|
+
notes.push(`${binaryCount} binary files skipped during last build.`);
|
|
117692
|
+
}
|
|
117693
|
+
const unreadableFiles = sanitizePathList(diagnostics?.unreadableFiles);
|
|
117694
|
+
const unreadableCount = unreadableFiles.length;
|
|
117695
|
+
if (unreadableCount > 0) {
|
|
117696
|
+
notes.push(`${unreadableCount} unreadable files skipped during last build.`);
|
|
117697
|
+
}
|
|
117698
|
+
return {
|
|
117699
|
+
schemaVersion: graph.schema_version,
|
|
117700
|
+
fresh,
|
|
117701
|
+
staleFiles,
|
|
117702
|
+
extractionFailures: sanitizeExtractionFailures(diagnostics?.extractionFailures),
|
|
117703
|
+
unresolvedImports: sanitizeUnresolvedImports(diagnostics?.unresolvedImports),
|
|
117704
|
+
oversizedFiles: sanitizePathList(diagnostics?.oversizedFiles),
|
|
117705
|
+
unsupportedFiles: sanitizePathList(diagnostics?.unsupportedFiles),
|
|
117706
|
+
binaryFiles,
|
|
117707
|
+
unreadableFiles,
|
|
117708
|
+
lowConfidenceEdgeCount: typeof diagnostics?.lowConfidenceEdgeCount === "number" && Number.isFinite(diagnostics.lowConfidenceEdgeCount) && diagnostics.lowConfidenceEdgeCount > 0 ? Math.floor(diagnostics.lowConfidenceEdgeCount) : 0,
|
|
117709
|
+
notes
|
|
117710
|
+
};
|
|
117711
|
+
}
|
|
117366
117712
|
function getImporters(graph, filePath) {
|
|
117367
117713
|
const node = getGraphNode(graph, filePath);
|
|
117368
117714
|
if (!node)
|
|
@@ -117951,7 +118297,7 @@ function buildOntologyPreflightPacket(graph, filePaths = [], options = {}) {
|
|
|
117951
118297
|
init_utils2();
|
|
117952
118298
|
init_logger();
|
|
117953
118299
|
init_path_security();
|
|
117954
|
-
import { constants as constants5, existsSync as existsSync77, readFileSync as readFileSync53, statSync as
|
|
118300
|
+
import { constants as constants5, existsSync as existsSync77, readFileSync as readFileSync53, statSync as statSync28 } from "node:fs";
|
|
117955
118301
|
import * as fsPromises6 from "node:fs/promises";
|
|
117956
118302
|
import * as path137 from "node:path";
|
|
117957
118303
|
var WINDOWS_RENAME_MAX_RETRIES2 = 5;
|
|
@@ -118076,7 +118422,7 @@ function loadGraphSync(workspace) {
|
|
|
118076
118422
|
const graphPath = getGraphPath(workspace);
|
|
118077
118423
|
if (!existsSync77(graphPath))
|
|
118078
118424
|
return null;
|
|
118079
|
-
const stats2 =
|
|
118425
|
+
const stats2 = statSync28(graphPath);
|
|
118080
118426
|
const content = readFileSync53(graphPath, "utf-8");
|
|
118081
118427
|
if (content.includes("\x00") || content.includes("�")) {
|
|
118082
118428
|
throw Object.assign(new Error("repo-graph.json contains null bytes or invalid encoding"), { code: "CORRUPTION" });
|
|
@@ -123102,9 +123448,9 @@ function parseDelegateDirectiveBlock(text) {
|
|
|
123102
123448
|
}
|
|
123103
123449
|
async function injectForDelegate(params) {
|
|
123104
123450
|
const { directory, agent, taskTitle, sessionId, config: config3 } = params;
|
|
123105
|
-
const
|
|
123451
|
+
const cap2 = config3.delegate_max_inject_count ?? 8;
|
|
123106
123452
|
const expectedTools = params.expectedTools && params.expectedTools.length > 0 ? params.expectedTools : defaultExpectedToolsForAgent(agent);
|
|
123107
|
-
if (
|
|
123453
|
+
if (cap2 <= 0)
|
|
123108
123454
|
return { entries: [], trace_id: "" };
|
|
123109
123455
|
const role = stripKnownSwarmPrefix(agent).toLowerCase();
|
|
123110
123456
|
const firstTool = expectedTools.length > 0 ? expectedTools[0] : undefined;
|
|
@@ -123128,11 +123474,11 @@ async function injectForDelegate(params) {
|
|
|
123128
123474
|
tier: "all",
|
|
123129
123475
|
applyScopeFilter: true,
|
|
123130
123476
|
applyRoleScope: false,
|
|
123131
|
-
maxResults: Math.max(40,
|
|
123477
|
+
maxResults: Math.max(40, cap2 * 4),
|
|
123132
123478
|
emitEvent: false
|
|
123133
123479
|
});
|
|
123134
123480
|
const scoped = search.results.filter((e) => matchesDelegateScope(e, role, expectedTools));
|
|
123135
|
-
const capped = scoped.slice(0,
|
|
123481
|
+
const capped = scoped.slice(0, cap2);
|
|
123136
123482
|
if (capped.length > 0) {
|
|
123137
123483
|
const ranks = {};
|
|
123138
123484
|
const scores = {};
|
|
@@ -129968,7 +130314,7 @@ ${body}`);
|
|
|
129968
130314
|
init_zod();
|
|
129969
130315
|
init_task_file();
|
|
129970
130316
|
import { appendFileSync as appendFileSync18, existsSync as existsSync95, mkdirSync as mkdirSync42, readFileSync as readFileSync64 } from "node:fs";
|
|
129971
|
-
import { join as
|
|
130317
|
+
import { join as join132 } from "node:path";
|
|
129972
130318
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
129973
130319
|
var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
|
|
129974
130320
|
var COUNCIL_GATE_NAME = "council";
|
|
@@ -130006,7 +130352,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
130006
130352
|
if (!VALID_TASK_ID.test(synthesis.taskId)) {
|
|
130007
130353
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
130008
130354
|
}
|
|
130009
|
-
const dir =
|
|
130355
|
+
const dir = join132(workingDir, EVIDENCE_DIR2);
|
|
130010
130356
|
mkdirSync42(dir, { recursive: true });
|
|
130011
130357
|
const filePath = taskEvidencePath(workingDir, synthesis.taskId);
|
|
130012
130358
|
await _internals96.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
|
|
@@ -130042,7 +130388,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
130042
130388
|
await atomicWriteFile(filePath, JSON.stringify(updated, null, 2));
|
|
130043
130389
|
});
|
|
130044
130390
|
try {
|
|
130045
|
-
const councilDir =
|
|
130391
|
+
const councilDir = join132(workingDir, ".swarm", "council");
|
|
130046
130392
|
mkdirSync42(councilDir, { recursive: true });
|
|
130047
130393
|
const auditLine = JSON.stringify({
|
|
130048
130394
|
round: synthesis.roundNumber,
|
|
@@ -130050,7 +130396,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
130050
130396
|
timestamp: synthesis.timestamp,
|
|
130051
130397
|
vetoedBy: synthesis.vetoedBy
|
|
130052
130398
|
});
|
|
130053
|
-
appendFileSync18(
|
|
130399
|
+
appendFileSync18(join132(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
|
|
130054
130400
|
`);
|
|
130055
130401
|
} catch (auditError) {
|
|
130056
130402
|
console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
|
|
@@ -130407,7 +130753,7 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
|
|
|
130407
130753
|
init_zod();
|
|
130408
130754
|
init_task_file();
|
|
130409
130755
|
import { existsSync as existsSync96, mkdirSync as mkdirSync43, readFileSync as readFileSync65 } from "node:fs";
|
|
130410
|
-
import { join as
|
|
130756
|
+
import { join as join133 } from "node:path";
|
|
130411
130757
|
var COUNCIL_DIR = ".swarm/council";
|
|
130412
130758
|
var CouncilCriteriaSchema = exports_external.object({
|
|
130413
130759
|
taskId: exports_external.string(),
|
|
@@ -130419,17 +130765,17 @@ var CouncilCriteriaSchema = exports_external.object({
|
|
|
130419
130765
|
declaredAt: exports_external.string()
|
|
130420
130766
|
});
|
|
130421
130767
|
async function writeCriteria(workingDir, taskId, criteria) {
|
|
130422
|
-
const dir =
|
|
130768
|
+
const dir = join133(workingDir, COUNCIL_DIR);
|
|
130423
130769
|
mkdirSync43(dir, { recursive: true });
|
|
130424
130770
|
const payload = {
|
|
130425
130771
|
taskId,
|
|
130426
130772
|
criteria,
|
|
130427
130773
|
declaredAt: new Date().toISOString()
|
|
130428
130774
|
};
|
|
130429
|
-
await atomicWriteFile(
|
|
130775
|
+
await atomicWriteFile(join133(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
|
|
130430
130776
|
}
|
|
130431
130777
|
function readCriteria(workingDir, taskId) {
|
|
130432
|
-
const filePath =
|
|
130778
|
+
const filePath = join133(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
|
|
130433
130779
|
if (!existsSync96(filePath))
|
|
130434
130780
|
return null;
|
|
130435
130781
|
try {
|
|
@@ -149644,7 +149990,8 @@ var VALID_ACTIONS = [
|
|
|
149644
149990
|
"preflight_packet",
|
|
149645
149991
|
"callers",
|
|
149646
149992
|
"dead_exports",
|
|
149647
|
-
"context_pack"
|
|
149993
|
+
"context_pack",
|
|
149994
|
+
"graph_health"
|
|
149648
149995
|
];
|
|
149649
149996
|
var MAX_FILE_PATH_LENGTH3 = 500;
|
|
149650
149997
|
var MAX_SYMBOL_LENGTH2 = 256;
|
|
@@ -149708,7 +150055,7 @@ async function loadOrError(directory, action) {
|
|
|
149708
150055
|
}
|
|
149709
150056
|
}
|
|
149710
150057
|
var repo_map = createSwarmTool({
|
|
149711
|
-
description: "Query the repository code graph for structural awareness before editing. " + 'Actions: "build" (build/refresh .swarm/repo-graph.json), "importers" (who imports a file), ' + '"dependencies" (what a file imports), "blast_radius" (transitive dependents + risk), ' + '"localization" (compact context block for a target file), "key_files" (top-N most-imported files), ' + '"ontology" (file roles/routes/data/security/findings), "package_boundaries" (inferred package/layer boundaries), ' + '"preflight_packet" (bounded ontology packet for planning), ' + '"callers" (files that reference an exported symbol, call-site granularity; needs file+symbol), ' + '"dead_exports" (advisory: exported symbols with no detected in-repo reference; results are review candidates, not delete directives), ' + '"context_pack" (token-budgeted slice of source spans for a target symbol — definition + transitive callers/callees; advisory/conservative; needs file+symbol; uses max_depth for traversal depth, top_n for span cap). ' + "Use this before refactoring shared modules to avoid breaking unseen consumers. " + 'Note: "callers"/"dead_exports"/"context_pack" use conservative regex analysis (TS/JS/Python) and cannot see ' + 'dynamic dispatch or namespace/barrel re-export usage; "dead_exports" results are review candidates, not delete directives.',
|
|
150058
|
+
description: "Query the repository code graph for structural awareness before editing. " + 'Actions: "build" (build/refresh .swarm/repo-graph.json), "importers" (who imports a file), ' + '"dependencies" (what a file imports), "blast_radius" (transitive dependents + risk), ' + '"localization" (compact context block for a target file), "key_files" (top-N most-imported files), ' + '"ontology" (file roles/routes/data/security/findings), "package_boundaries" (inferred package/layer boundaries), ' + '"preflight_packet" (bounded ontology packet for planning), ' + '"callers" (files that reference an exported symbol, call-site granularity; needs file+symbol), ' + '"dead_exports" (advisory: exported symbols with no detected in-repo reference; results are review candidates, not delete directives), ' + '"context_pack" (token-budgeted slice of source spans for a target symbol — definition + transitive callers/callees; advisory/conservative; needs file+symbol; uses max_depth for traversal depth, top_n for span cap), ' + '"graph_health" (freshness and bounded extraction diagnostics; no file required). ' + "Use this before refactoring shared modules to avoid breaking unseen consumers. " + 'Note: "callers"/"dead_exports"/"context_pack" use conservative regex analysis (TS/JS/Python) and cannot see ' + 'dynamic dispatch or namespace/barrel re-export usage; "dead_exports" results are review candidates, not delete directives.',
|
|
149712
150059
|
args: {
|
|
149713
150060
|
action: exports_external.enum([
|
|
149714
150061
|
"build",
|
|
@@ -149722,8 +150069,9 @@ var repo_map = createSwarmTool({
|
|
|
149722
150069
|
"preflight_packet",
|
|
149723
150070
|
"callers",
|
|
149724
150071
|
"dead_exports",
|
|
149725
|
-
"context_pack"
|
|
149726
|
-
|
|
150072
|
+
"context_pack",
|
|
150073
|
+
"graph_health"
|
|
150074
|
+
]).describe('Query action: "build" | "importers" | "dependencies" | "blast_radius" | "localization" | "key_files" | "ontology" | "package_boundaries" | "preflight_packet" | "callers" | "dead_exports" | "context_pack" | "graph_health"'),
|
|
149727
150075
|
file: exports_external.string().optional().describe("Target file (workspace-relative or absolute). Required for importers/dependencies/localization/ontology. Optional for preflight_packet."),
|
|
149728
150076
|
files: exports_external.array(exports_external.string()).optional().describe("Multiple target files for blast_radius/preflight_packet. If omitted, falls back to `file`."),
|
|
149729
150077
|
symbol: exports_external.string().optional().describe('Exported symbol name. Restricts consumers on action="importers"; required for action="callers"/"context_pack".'),
|
|
@@ -149758,6 +150106,15 @@ var repo_map = createSwarmTool({
|
|
|
149758
150106
|
return err(action, `build failed: ${message}`);
|
|
149759
150107
|
}
|
|
149760
150108
|
}
|
|
150109
|
+
if (action === "graph_health") {
|
|
150110
|
+
try {
|
|
150111
|
+
const graph2 = await loadGraph(directory);
|
|
150112
|
+
return ok(action, { ...getGraphHealth(graph2, directory) });
|
|
150113
|
+
} catch (e) {
|
|
150114
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
150115
|
+
return err(action, `failed to load repo graph: ${message}`);
|
|
150116
|
+
}
|
|
150117
|
+
}
|
|
149761
150118
|
const loaded = await loadOrError(directory, action);
|
|
149762
150119
|
if (!loaded.ok)
|
|
149763
150120
|
return loaded.response;
|
|
@@ -153111,7 +153468,7 @@ init_skill_generator();
|
|
|
153111
153468
|
init_create_tool();
|
|
153112
153469
|
import { existsSync as existsSync119 } from "node:fs";
|
|
153113
153470
|
import { readdir as readdir12, readFile as readFile33 } from "node:fs/promises";
|
|
153114
|
-
import { join as
|
|
153471
|
+
import { join as join167 } from "node:path";
|
|
153115
153472
|
var run_stale_reconciliation = createSwarmTool({
|
|
153116
153473
|
description: "Reconcile skills against the knowledge store. clear=false: mark skills stale when source knowledge is archived or deleted. clear=true: clear stale.marker on affected active skills (proposal files under .swarm/skills/proposals are scanned but not modified — they are drafts, not yet active skills).",
|
|
153117
153474
|
args: {
|
|
@@ -153138,8 +153495,8 @@ var run_stale_reconciliation = createSwarmTool({
|
|
|
153138
153495
|
} catch {}
|
|
153139
153496
|
const skillEntries = [];
|
|
153140
153497
|
for (const dir of [
|
|
153141
|
-
|
|
153142
|
-
|
|
153498
|
+
join167(directory, ".opencode", "skills", "generated"),
|
|
153499
|
+
join167(directory, ".swarm", "skills", "proposals")
|
|
153143
153500
|
]) {
|
|
153144
153501
|
if (!_internals125.existsSync(dir))
|
|
153145
153502
|
continue;
|
|
@@ -153148,14 +153505,14 @@ var run_stale_reconciliation = createSwarmTool({
|
|
|
153148
153505
|
if (entry.isDirectory()) {
|
|
153149
153506
|
skillEntries.push({
|
|
153150
153507
|
slug: entry.name,
|
|
153151
|
-
path:
|
|
153508
|
+
path: join167(dir, entry.name),
|
|
153152
153509
|
isProposal: false
|
|
153153
153510
|
});
|
|
153154
153511
|
} else if (entry.name.endsWith(".md")) {
|
|
153155
153512
|
const slug = entry.name.replace(/\.md$/, "");
|
|
153156
153513
|
skillEntries.push({
|
|
153157
153514
|
slug,
|
|
153158
|
-
path:
|
|
153515
|
+
path: join167(dir, entry.name),
|
|
153159
153516
|
isProposal: true
|
|
153160
153517
|
});
|
|
153161
153518
|
}
|
|
@@ -153163,7 +153520,7 @@ var run_stale_reconciliation = createSwarmTool({
|
|
|
153163
153520
|
}
|
|
153164
153521
|
const results = [];
|
|
153165
153522
|
for (const { slug, path: path210, isProposal } of skillEntries) {
|
|
153166
|
-
const skillMdPath = isProposal ? path210 :
|
|
153523
|
+
const skillMdPath = isProposal ? path210 : join167(path210, "SKILL.md");
|
|
153167
153524
|
if (!_internals125.existsSync(skillMdPath))
|
|
153168
153525
|
continue;
|
|
153169
153526
|
const content = await _internals125.readFile(skillMdPath, "utf-8");
|
|
@@ -153176,7 +153533,7 @@ var run_stale_reconciliation = createSwarmTool({
|
|
|
153176
153533
|
continue;
|
|
153177
153534
|
if (args2.clear) {
|
|
153178
153535
|
if (!isProposal) {
|
|
153179
|
-
const markerPath =
|
|
153536
|
+
const markerPath = join167(path210, "stale.marker");
|
|
153180
153537
|
if (_internals125.existsSync(markerPath)) {
|
|
153181
153538
|
try {
|
|
153182
153539
|
await _internals125.clearSkillStale(path210);
|
|
@@ -158389,14 +158746,6 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
158389
158746
|
prEventCleanup?.();
|
|
158390
158747
|
};
|
|
158391
158748
|
process.on("exit", cleanupAutomation);
|
|
158392
|
-
process.once("SIGINT", () => {
|
|
158393
|
-
cleanupAutomation();
|
|
158394
|
-
process.exit(130);
|
|
158395
|
-
});
|
|
158396
|
-
process.once("SIGTERM", () => {
|
|
158397
|
-
cleanupAutomation();
|
|
158398
|
-
process.exit(143);
|
|
158399
|
-
});
|
|
158400
158749
|
if (shouldRunOnStartup(automationConfig)) {
|
|
158401
158750
|
const enableAutofix = automationConfig.capabilities?.config_doctor_autofix === true;
|
|
158402
158751
|
Promise.resolve().then(() => (init_config_doctor(), exports_config_doctor)).then(({ runConfigDoctorWithFixes: runConfigDoctorWithFixes2 }) => {
|
|
@@ -158412,9 +158761,19 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
158412
158761
|
try {
|
|
158413
158762
|
const autoFixableCount = doctorResult.result.findings.filter((f) => f.autoFixable).length;
|
|
158414
158763
|
if (!enableAutofix && autoFixableCount > 0) {
|
|
158415
|
-
|
|
158764
|
+
const msg = `[opencode-swarm] Config Doctor found ${autoFixableCount} auto-fixable issue(s). Run /swarm config doctor --fix to apply.`;
|
|
158765
|
+
if (!config3.quiet) {
|
|
158766
|
+
console.warn(msg);
|
|
158767
|
+
} else {
|
|
158768
|
+
addDeferredWarning(msg);
|
|
158769
|
+
}
|
|
158416
158770
|
} else if (enableAutofix && doctorResult.appliedFixes.length > 0) {
|
|
158417
|
-
|
|
158771
|
+
const msg = `[opencode-swarm] Config Doctor applied ${doctorResult.appliedFixes.length} fix(es) automatically.`;
|
|
158772
|
+
if (!config3.quiet) {
|
|
158773
|
+
console.warn(msg);
|
|
158774
|
+
} else {
|
|
158775
|
+
addDeferredWarning(msg);
|
|
158776
|
+
}
|
|
158418
158777
|
}
|
|
158419
158778
|
} catch {}
|
|
158420
158779
|
}
|
|
@@ -158957,7 +159316,9 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
158957
159316
|
argsRecord.prompt = `SKILLS: none
|
|
158958
159317
|
|
|
158959
159318
|
${promptRaw}`;
|
|
158960
|
-
|
|
159319
|
+
if (!config3.quiet) {
|
|
159320
|
+
console.warn("[skill-propagation-gate] No skills above threshold 0.5 — injected SKILLS: none");
|
|
159321
|
+
}
|
|
158961
159322
|
} else {
|
|
158962
159323
|
const topSkills = qualified.slice(0, 5);
|
|
158963
159324
|
const skillPaths = topSkills.map((s) => {
|
|
@@ -158975,7 +159336,9 @@ ${promptRaw}`;
|
|
|
158975
159336
|
${promptRaw}`;
|
|
158976
159337
|
argsRecord.prompt = newPrompt;
|
|
158977
159338
|
const skillNames = topSkills.map((s) => `${path225.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
158978
|
-
|
|
159339
|
+
if (!config3.quiet) {
|
|
159340
|
+
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
159341
|
+
}
|
|
158979
159342
|
for (const skill of topSkills) {
|
|
158980
159343
|
try {
|
|
158981
159344
|
appendSkillUsageEntry(ctx.directory, {
|