opencode-swarm 6.25.2 → 6.25.4
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 +67 -36
- package/dist/index.js +109 -50
- package/dist/tools/test-runner.d.ts +1 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -33858,6 +33858,7 @@ var MAX_OUTPUT_BYTES3 = 512000;
|
|
|
33858
33858
|
var MAX_COMMAND_LENGTH2 = 500;
|
|
33859
33859
|
var DEFAULT_TIMEOUT_MS = 60000;
|
|
33860
33860
|
var MAX_TIMEOUT_MS = 300000;
|
|
33861
|
+
var MAX_SAFE_TEST_FILES = 50;
|
|
33861
33862
|
function containsPathTraversal2(str) {
|
|
33862
33863
|
if (/\.\.[/\\]/.test(str))
|
|
33863
33864
|
return true;
|
|
@@ -34714,35 +34715,6 @@ var SKIP_DIRECTORIES = new Set([
|
|
|
34714
34715
|
".bundle",
|
|
34715
34716
|
".tox"
|
|
34716
34717
|
]);
|
|
34717
|
-
function findSourceFiles(dir, files = []) {
|
|
34718
|
-
let entries;
|
|
34719
|
-
try {
|
|
34720
|
-
entries = fs5.readdirSync(dir);
|
|
34721
|
-
} catch {
|
|
34722
|
-
return files;
|
|
34723
|
-
}
|
|
34724
|
-
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
34725
|
-
for (const entry of entries) {
|
|
34726
|
-
if (SKIP_DIRECTORIES.has(entry))
|
|
34727
|
-
continue;
|
|
34728
|
-
const fullPath = path13.join(dir, entry);
|
|
34729
|
-
let stat2;
|
|
34730
|
-
try {
|
|
34731
|
-
stat2 = fs5.statSync(fullPath);
|
|
34732
|
-
} catch {
|
|
34733
|
-
continue;
|
|
34734
|
-
}
|
|
34735
|
-
if (stat2.isDirectory()) {
|
|
34736
|
-
findSourceFiles(fullPath, files);
|
|
34737
|
-
} else if (stat2.isFile()) {
|
|
34738
|
-
const ext = path13.extname(fullPath).toLowerCase();
|
|
34739
|
-
if (SOURCE_EXTENSIONS.has(ext)) {
|
|
34740
|
-
files.push(fullPath);
|
|
34741
|
-
}
|
|
34742
|
-
}
|
|
34743
|
-
}
|
|
34744
|
-
return files;
|
|
34745
|
-
}
|
|
34746
34718
|
var test_runner = createSwarmTool({
|
|
34747
34719
|
description: 'Run project tests with framework detection. Supports bun, vitest, jest, mocha, pytest, cargo, pester, go-test, maven, gradle, dotnet-test, ctest, swift-test, dart-test, rspec, and minitest. Returns deterministic normalized JSON with framework, scope, command, totals, coverage, duration, success status, and failures. Use scope "all" for full suite, "convention" to map source files to test files, or "graph" to find related tests via imports.',
|
|
34748
34720
|
args: {
|
|
@@ -34800,6 +34772,26 @@ var test_runner = createSwarmTool({
|
|
|
34800
34772
|
return JSON.stringify(errorResult, null, 2);
|
|
34801
34773
|
}
|
|
34802
34774
|
const scope = args.scope || "all";
|
|
34775
|
+
if (scope === "all") {
|
|
34776
|
+
const errorResult = {
|
|
34777
|
+
success: false,
|
|
34778
|
+
framework: "none",
|
|
34779
|
+
scope: "all",
|
|
34780
|
+
error: 'Full-suite test execution (scope: "all") is prohibited in interactive sessions',
|
|
34781
|
+
message: 'Use scope "convention" or "graph" with explicit files to run targeted tests in interactive mode. Full-suite runs are restricted to prevent excessive resource consumption.'
|
|
34782
|
+
};
|
|
34783
|
+
return JSON.stringify(errorResult, null, 2);
|
|
34784
|
+
}
|
|
34785
|
+
if ((scope === "convention" || scope === "graph") && (!args.files || args.files.length === 0)) {
|
|
34786
|
+
const errorResult = {
|
|
34787
|
+
success: false,
|
|
34788
|
+
framework: "none",
|
|
34789
|
+
scope,
|
|
34790
|
+
error: 'scope "convention" and "graph" require explicit files array - omitting files causes unsafe full-project discovery',
|
|
34791
|
+
message: 'When using scope "convention" or "graph", you must provide a non-empty "files" array. Use scope "all" for full project test suite without specifying files.'
|
|
34792
|
+
};
|
|
34793
|
+
return JSON.stringify(errorResult, null, 2);
|
|
34794
|
+
}
|
|
34803
34795
|
const _files = args.files || [];
|
|
34804
34796
|
const coverage = args.coverage || false;
|
|
34805
34797
|
const timeout_ms = Math.min(args.timeout_ms || DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
|
|
@@ -34823,19 +34815,37 @@ var test_runner = createSwarmTool({
|
|
|
34823
34815
|
let testFiles = [];
|
|
34824
34816
|
let graphFallbackReason;
|
|
34825
34817
|
let effectiveScope = scope;
|
|
34826
|
-
if (scope === "
|
|
34827
|
-
|
|
34828
|
-
} else if (scope === "convention") {
|
|
34829
|
-
const sourceFiles = args.files && args.files.length > 0 ? args.files.filter((f) => {
|
|
34818
|
+
if (scope === "convention") {
|
|
34819
|
+
const sourceFiles = args.files.filter((f) => {
|
|
34830
34820
|
const ext = path13.extname(f).toLowerCase();
|
|
34831
34821
|
return SOURCE_EXTENSIONS.has(ext);
|
|
34832
|
-
})
|
|
34822
|
+
});
|
|
34823
|
+
if (sourceFiles.length === 0) {
|
|
34824
|
+
const errorResult = {
|
|
34825
|
+
success: false,
|
|
34826
|
+
framework,
|
|
34827
|
+
scope,
|
|
34828
|
+
error: "Provided files contain no source files with recognized extensions",
|
|
34829
|
+
message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Non-source files like README.md or config.json are not valid for test discovery."
|
|
34830
|
+
};
|
|
34831
|
+
return JSON.stringify(errorResult, null, 2);
|
|
34832
|
+
}
|
|
34833
34833
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
34834
34834
|
} else if (scope === "graph") {
|
|
34835
|
-
const sourceFiles = args.files
|
|
34835
|
+
const sourceFiles = args.files.filter((f) => {
|
|
34836
34836
|
const ext = path13.extname(f).toLowerCase();
|
|
34837
34837
|
return SOURCE_EXTENSIONS.has(ext);
|
|
34838
|
-
})
|
|
34838
|
+
});
|
|
34839
|
+
if (sourceFiles.length === 0) {
|
|
34840
|
+
const errorResult = {
|
|
34841
|
+
success: false,
|
|
34842
|
+
framework,
|
|
34843
|
+
scope,
|
|
34844
|
+
error: "Provided files contain no source files with recognized extensions",
|
|
34845
|
+
message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Non-source files like README.md or config.json are not valid for test discovery."
|
|
34846
|
+
};
|
|
34847
|
+
return JSON.stringify(errorResult, null, 2);
|
|
34848
|
+
}
|
|
34839
34849
|
const graphTestFiles = await getTestFilesFromGraph(sourceFiles);
|
|
34840
34850
|
if (graphTestFiles.length > 0) {
|
|
34841
34851
|
testFiles = graphTestFiles;
|
|
@@ -34845,6 +34855,27 @@ var test_runner = createSwarmTool({
|
|
|
34845
34855
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
34846
34856
|
}
|
|
34847
34857
|
}
|
|
34858
|
+
if (testFiles.length === 0) {
|
|
34859
|
+
const errorResult = {
|
|
34860
|
+
success: false,
|
|
34861
|
+
framework,
|
|
34862
|
+
scope: effectiveScope,
|
|
34863
|
+
error: "Provided source files resolved to zero test files",
|
|
34864
|
+
message: "No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, __tests__/, tests/, test/)."
|
|
34865
|
+
};
|
|
34866
|
+
return JSON.stringify(errorResult, null, 2);
|
|
34867
|
+
}
|
|
34868
|
+
if (testFiles.length > MAX_SAFE_TEST_FILES) {
|
|
34869
|
+
const sampleFiles = testFiles.slice(0, 5);
|
|
34870
|
+
const errorResult = {
|
|
34871
|
+
success: false,
|
|
34872
|
+
framework,
|
|
34873
|
+
scope: effectiveScope,
|
|
34874
|
+
error: `Resolved test file count (${testFiles.length}) exceeds safe maximum (${MAX_SAFE_TEST_FILES})`,
|
|
34875
|
+
message: `Too many test files resolved (${testFiles.length}). Maximum allowed is ${MAX_SAFE_TEST_FILES}. Provide more specific source files to narrow down test scope. First few resolved: ${sampleFiles.join(", ")}`
|
|
34876
|
+
};
|
|
34877
|
+
return JSON.stringify(errorResult, null, 2);
|
|
34878
|
+
}
|
|
34848
34879
|
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir);
|
|
34849
34880
|
if (graphFallbackReason && result.message) {
|
|
34850
34881
|
result.message = `${result.message} (${graphFallbackReason})`;
|
package/dist/index.js
CHANGED
|
@@ -35070,36 +35070,7 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
35070
35070
|
};
|
|
35071
35071
|
}
|
|
35072
35072
|
}
|
|
35073
|
-
|
|
35074
|
-
let entries;
|
|
35075
|
-
try {
|
|
35076
|
-
entries = fs10.readdirSync(dir);
|
|
35077
|
-
} catch {
|
|
35078
|
-
return files;
|
|
35079
|
-
}
|
|
35080
|
-
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
35081
|
-
for (const entry of entries) {
|
|
35082
|
-
if (SKIP_DIRECTORIES.has(entry))
|
|
35083
|
-
continue;
|
|
35084
|
-
const fullPath = path22.join(dir, entry);
|
|
35085
|
-
let stat2;
|
|
35086
|
-
try {
|
|
35087
|
-
stat2 = fs10.statSync(fullPath);
|
|
35088
|
-
} catch {
|
|
35089
|
-
continue;
|
|
35090
|
-
}
|
|
35091
|
-
if (stat2.isDirectory()) {
|
|
35092
|
-
findSourceFiles(fullPath, files);
|
|
35093
|
-
} else if (stat2.isFile()) {
|
|
35094
|
-
const ext = path22.extname(fullPath).toLowerCase();
|
|
35095
|
-
if (SOURCE_EXTENSIONS.has(ext)) {
|
|
35096
|
-
files.push(fullPath);
|
|
35097
|
-
}
|
|
35098
|
-
}
|
|
35099
|
-
}
|
|
35100
|
-
return files;
|
|
35101
|
-
}
|
|
35102
|
-
var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, POWERSHELL_METACHARACTERS, TEST_PATTERNS, COMPOUND_TEST_EXTENSIONS, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
|
|
35073
|
+
var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, POWERSHELL_METACHARACTERS, TEST_PATTERNS, COMPOUND_TEST_EXTENSIONS, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
|
|
35103
35074
|
var init_test_runner = __esm(() => {
|
|
35104
35075
|
init_dist();
|
|
35105
35076
|
init_discovery();
|
|
@@ -35233,6 +35204,26 @@ var init_test_runner = __esm(() => {
|
|
|
35233
35204
|
return JSON.stringify(errorResult, null, 2);
|
|
35234
35205
|
}
|
|
35235
35206
|
const scope = args2.scope || "all";
|
|
35207
|
+
if (scope === "all") {
|
|
35208
|
+
const errorResult = {
|
|
35209
|
+
success: false,
|
|
35210
|
+
framework: "none",
|
|
35211
|
+
scope: "all",
|
|
35212
|
+
error: 'Full-suite test execution (scope: "all") is prohibited in interactive sessions',
|
|
35213
|
+
message: 'Use scope "convention" or "graph" with explicit files to run targeted tests in interactive mode. Full-suite runs are restricted to prevent excessive resource consumption.'
|
|
35214
|
+
};
|
|
35215
|
+
return JSON.stringify(errorResult, null, 2);
|
|
35216
|
+
}
|
|
35217
|
+
if ((scope === "convention" || scope === "graph") && (!args2.files || args2.files.length === 0)) {
|
|
35218
|
+
const errorResult = {
|
|
35219
|
+
success: false,
|
|
35220
|
+
framework: "none",
|
|
35221
|
+
scope,
|
|
35222
|
+
error: 'scope "convention" and "graph" require explicit files array - omitting files causes unsafe full-project discovery',
|
|
35223
|
+
message: 'When using scope "convention" or "graph", you must provide a non-empty "files" array. Use scope "all" for full project test suite without specifying files.'
|
|
35224
|
+
};
|
|
35225
|
+
return JSON.stringify(errorResult, null, 2);
|
|
35226
|
+
}
|
|
35236
35227
|
const _files = args2.files || [];
|
|
35237
35228
|
const coverage = args2.coverage || false;
|
|
35238
35229
|
const timeout_ms = Math.min(args2.timeout_ms || DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
|
|
@@ -35256,19 +35247,37 @@ var init_test_runner = __esm(() => {
|
|
|
35256
35247
|
let testFiles = [];
|
|
35257
35248
|
let graphFallbackReason;
|
|
35258
35249
|
let effectiveScope = scope;
|
|
35259
|
-
if (scope === "
|
|
35260
|
-
|
|
35261
|
-
} else if (scope === "convention") {
|
|
35262
|
-
const sourceFiles = args2.files && args2.files.length > 0 ? args2.files.filter((f) => {
|
|
35250
|
+
if (scope === "convention") {
|
|
35251
|
+
const sourceFiles = args2.files.filter((f) => {
|
|
35263
35252
|
const ext = path22.extname(f).toLowerCase();
|
|
35264
35253
|
return SOURCE_EXTENSIONS.has(ext);
|
|
35265
|
-
})
|
|
35254
|
+
});
|
|
35255
|
+
if (sourceFiles.length === 0) {
|
|
35256
|
+
const errorResult = {
|
|
35257
|
+
success: false,
|
|
35258
|
+
framework,
|
|
35259
|
+
scope,
|
|
35260
|
+
error: "Provided files contain no source files with recognized extensions",
|
|
35261
|
+
message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Non-source files like README.md or config.json are not valid for test discovery."
|
|
35262
|
+
};
|
|
35263
|
+
return JSON.stringify(errorResult, null, 2);
|
|
35264
|
+
}
|
|
35266
35265
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
35267
35266
|
} else if (scope === "graph") {
|
|
35268
|
-
const sourceFiles = args2.files
|
|
35267
|
+
const sourceFiles = args2.files.filter((f) => {
|
|
35269
35268
|
const ext = path22.extname(f).toLowerCase();
|
|
35270
35269
|
return SOURCE_EXTENSIONS.has(ext);
|
|
35271
|
-
})
|
|
35270
|
+
});
|
|
35271
|
+
if (sourceFiles.length === 0) {
|
|
35272
|
+
const errorResult = {
|
|
35273
|
+
success: false,
|
|
35274
|
+
framework,
|
|
35275
|
+
scope,
|
|
35276
|
+
error: "Provided files contain no source files with recognized extensions",
|
|
35277
|
+
message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Non-source files like README.md or config.json are not valid for test discovery."
|
|
35278
|
+
};
|
|
35279
|
+
return JSON.stringify(errorResult, null, 2);
|
|
35280
|
+
}
|
|
35272
35281
|
const graphTestFiles = await getTestFilesFromGraph(sourceFiles);
|
|
35273
35282
|
if (graphTestFiles.length > 0) {
|
|
35274
35283
|
testFiles = graphTestFiles;
|
|
@@ -35278,6 +35287,27 @@ var init_test_runner = __esm(() => {
|
|
|
35278
35287
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
35279
35288
|
}
|
|
35280
35289
|
}
|
|
35290
|
+
if (testFiles.length === 0) {
|
|
35291
|
+
const errorResult = {
|
|
35292
|
+
success: false,
|
|
35293
|
+
framework,
|
|
35294
|
+
scope: effectiveScope,
|
|
35295
|
+
error: "Provided source files resolved to zero test files",
|
|
35296
|
+
message: "No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, __tests__/, tests/, test/)."
|
|
35297
|
+
};
|
|
35298
|
+
return JSON.stringify(errorResult, null, 2);
|
|
35299
|
+
}
|
|
35300
|
+
if (testFiles.length > MAX_SAFE_TEST_FILES) {
|
|
35301
|
+
const sampleFiles = testFiles.slice(0, 5);
|
|
35302
|
+
const errorResult = {
|
|
35303
|
+
success: false,
|
|
35304
|
+
framework,
|
|
35305
|
+
scope: effectiveScope,
|
|
35306
|
+
error: `Resolved test file count (${testFiles.length}) exceeds safe maximum (${MAX_SAFE_TEST_FILES})`,
|
|
35307
|
+
message: `Too many test files resolved (${testFiles.length}). Maximum allowed is ${MAX_SAFE_TEST_FILES}. Provide more specific source files to narrow down test scope. First few resolved: ${sampleFiles.join(", ")}`
|
|
35308
|
+
};
|
|
35309
|
+
return JSON.stringify(errorResult, null, 2);
|
|
35310
|
+
}
|
|
35281
35311
|
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir);
|
|
35282
35312
|
if (graphFallbackReason && result.message) {
|
|
35283
35313
|
result.message = `${result.message} (${graphFallbackReason})`;
|
|
@@ -41343,12 +41373,30 @@ When tests fail:
|
|
|
41343
41373
|
OUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):
|
|
41344
41374
|
Begin directly with the VERDICT line. Do NOT prepend "Here's my analysis..." or any conversational preamble.
|
|
41345
41375
|
|
|
41346
|
-
VERDICT: PASS [N/N tests passed] | FAIL [N passed, M failed]
|
|
41347
|
-
TESTS: [total count] tests, [pass count] passed, [fail count] failed
|
|
41376
|
+
VERDICT: PASS [N/N tests passed] | FAIL [N passed, M failed] | SKIPPED [reason]
|
|
41377
|
+
TESTS: [total count] tests, [pass count] passed, [fail count] failed, [skip count] skipped
|
|
41348
41378
|
FAILURES: [list of failed test names + error messages, if any]
|
|
41349
41379
|
COVERAGE: [X]% of public functions \u2014 [areas covered]
|
|
41350
41380
|
BUGS FOUND: [list any source code bugs discovered during testing, or "none"]
|
|
41351
41381
|
|
|
41382
|
+
## SKIP CONDITIONS
|
|
41383
|
+
|
|
41384
|
+
Use \`VERDICT: SKIPPED [reason]\` when tests CANNOT be executed due to environment or configuration issues \u2014 NOT when tests can run but fail. SKIPPED is not a bypass to avoid reporting real failures.
|
|
41385
|
+
|
|
41386
|
+
SKIP CONDITIONS (any of these justifies SKIPPED):
|
|
41387
|
+
1. PROHIBITED SCOPE: test_runner refuses scope: "all" \u2014 this is blocked for safety
|
|
41388
|
+
2. EXCESSIVE FILE COUNT: resolved test file count exceeds safe threshold (exceeds MAX_FILES limit)
|
|
41389
|
+
3. FRAMEWORK DETECTION NONE: test_runner reports framework detection returns "none"
|
|
41390
|
+
4. MISSING TEST FILE: test file does not exist after write (write failed or path error)
|
|
41391
|
+
5. SESSION INSTABILITY: timeout, spawn failure, or runner crash that prevents execution
|
|
41392
|
+
|
|
41393
|
+
SKIPPED is NOT appropriate when:
|
|
41394
|
+
- Tests exist and can run but produce failures (use FAIL verdict)
|
|
41395
|
+
- Tests pass but coverage is low (use PASS verdict, note coverage warning)
|
|
41396
|
+
- You chose not to write tests (write them or explain why impossible)
|
|
41397
|
+
|
|
41398
|
+
When reporting SKIPPED, include the specific reason from the conditions above.
|
|
41399
|
+
|
|
41352
41400
|
COVERAGE REPORTING:
|
|
41353
41401
|
- After running tests, report the line/branch coverage percentage if the test runner provides it.
|
|
41354
41402
|
- Format: COVERAGE_PCT: [N]% (or "N/A" if not available)
|
|
@@ -49144,6 +49192,15 @@ function extractPlanTaskId(text) {
|
|
|
49144
49192
|
function getSeedTaskId(session) {
|
|
49145
49193
|
return session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
49146
49194
|
}
|
|
49195
|
+
function getEvidenceTaskId(session) {
|
|
49196
|
+
const primary = session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
49197
|
+
if (primary)
|
|
49198
|
+
return primary;
|
|
49199
|
+
if (session.taskWorkflowStates && session.taskWorkflowStates.size > 0) {
|
|
49200
|
+
return session.taskWorkflowStates.keys().next().value ?? null;
|
|
49201
|
+
}
|
|
49202
|
+
return null;
|
|
49203
|
+
}
|
|
49147
49204
|
function createDelegationGateHook(config3, directory) {
|
|
49148
49205
|
const enabled = config3.hooks?.delegation_gate !== false;
|
|
49149
49206
|
const delegationMaxChars = config3.hooks?.delegation_max_chars ?? 4000;
|
|
@@ -49234,7 +49291,7 @@ function createDelegationGateHook(config3, directory) {
|
|
|
49234
49291
|
}
|
|
49235
49292
|
}
|
|
49236
49293
|
if (typeof subagentType === "string") {
|
|
49237
|
-
const evidenceTaskId = session
|
|
49294
|
+
const evidenceTaskId = getEvidenceTaskId(session);
|
|
49238
49295
|
if (evidenceTaskId) {
|
|
49239
49296
|
try {
|
|
49240
49297
|
const gateAgents = [
|
|
@@ -49242,7 +49299,9 @@ function createDelegationGateHook(config3, directory) {
|
|
|
49242
49299
|
"test_engineer",
|
|
49243
49300
|
"docs",
|
|
49244
49301
|
"designer",
|
|
49245
|
-
"critic"
|
|
49302
|
+
"critic",
|
|
49303
|
+
"explorer",
|
|
49304
|
+
"sme"
|
|
49246
49305
|
];
|
|
49247
49306
|
const targetAgentForEvidence = stripKnownSwarmPrefix(subagentType);
|
|
49248
49307
|
if (gateAgents.includes(targetAgentForEvidence)) {
|
|
@@ -49350,16 +49409,16 @@ function createDelegationGateHook(config3, directory) {
|
|
|
49350
49409
|
}
|
|
49351
49410
|
}
|
|
49352
49411
|
{
|
|
49353
|
-
const evidenceTaskId = session
|
|
49412
|
+
const evidenceTaskId = getEvidenceTaskId(session);
|
|
49354
49413
|
if (evidenceTaskId) {
|
|
49355
49414
|
try {
|
|
49356
49415
|
if (hasReviewer) {
|
|
49357
49416
|
const { recordGateEvidence: recordGateEvidence2 } = await Promise.resolve().then(() => (init_gate_evidence(), exports_gate_evidence));
|
|
49358
|
-
await recordGateEvidence2(
|
|
49417
|
+
await recordGateEvidence2(process.cwd(), evidenceTaskId, "reviewer", input.sessionID);
|
|
49359
49418
|
}
|
|
49360
49419
|
if (hasTestEngineer) {
|
|
49361
49420
|
const { recordGateEvidence: recordGateEvidence2 } = await Promise.resolve().then(() => (init_gate_evidence(), exports_gate_evidence));
|
|
49362
|
-
await recordGateEvidence2(
|
|
49421
|
+
await recordGateEvidence2(process.cwd(), evidenceTaskId, "test_engineer", input.sessionID);
|
|
49363
49422
|
}
|
|
49364
49423
|
} catch (err2) {
|
|
49365
49424
|
console.warn(`[delegation-gate] evidence write failed for task ${evidenceTaskId}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
@@ -54837,7 +54896,7 @@ var SKIP_DIRECTORIES2 = new Set([
|
|
|
54837
54896
|
".svn",
|
|
54838
54897
|
".hg"
|
|
54839
54898
|
]);
|
|
54840
|
-
function
|
|
54899
|
+
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
54841
54900
|
let entries;
|
|
54842
54901
|
try {
|
|
54843
54902
|
entries = fs25.readdirSync(dir);
|
|
@@ -54866,7 +54925,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
54866
54925
|
continue;
|
|
54867
54926
|
}
|
|
54868
54927
|
if (stat2.isDirectory()) {
|
|
54869
|
-
|
|
54928
|
+
findSourceFiles(fullPath, files, stats);
|
|
54870
54929
|
} else if (stat2.isFile()) {
|
|
54871
54930
|
const ext = path38.extname(fullPath).toLowerCase();
|
|
54872
54931
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
@@ -54952,7 +55011,7 @@ var imports = tool({
|
|
|
54952
55011
|
skippedFiles: 0,
|
|
54953
55012
|
fileErrors: []
|
|
54954
55013
|
};
|
|
54955
|
-
const sourceFiles =
|
|
55014
|
+
const sourceFiles = findSourceFiles(baseDir, [], scanStats);
|
|
54956
55015
|
const filesToScan = sourceFiles.filter((f) => f !== targetFile).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).slice(0, MAX_CONSUMERS * 10);
|
|
54957
55016
|
const consumers = [];
|
|
54958
55017
|
let skippedFileCount = 0;
|
|
@@ -61429,7 +61488,7 @@ function isSupportedExtension(filePath) {
|
|
|
61429
61488
|
const ext = path48.extname(filePath).toLowerCase();
|
|
61430
61489
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
61431
61490
|
}
|
|
61432
|
-
function
|
|
61491
|
+
function findSourceFiles2(dir, files = []) {
|
|
61433
61492
|
let entries;
|
|
61434
61493
|
try {
|
|
61435
61494
|
entries = fs35.readdirSync(dir);
|
|
@@ -61449,7 +61508,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
61449
61508
|
continue;
|
|
61450
61509
|
}
|
|
61451
61510
|
if (stat2.isDirectory()) {
|
|
61452
|
-
|
|
61511
|
+
findSourceFiles2(fullPath, files);
|
|
61453
61512
|
} else if (stat2.isFile()) {
|
|
61454
61513
|
if (isSupportedExtension(fullPath)) {
|
|
61455
61514
|
files.push(fullPath);
|
|
@@ -61561,7 +61620,7 @@ var todo_extract = createSwarmTool({
|
|
|
61561
61620
|
return JSON.stringify(errorResult, null, 2);
|
|
61562
61621
|
}
|
|
61563
61622
|
} else {
|
|
61564
|
-
|
|
61623
|
+
findSourceFiles2(scanPath, filesToScan);
|
|
61565
61624
|
}
|
|
61566
61625
|
const allEntries = [];
|
|
61567
61626
|
for (const filePath of filesToScan) {
|
|
@@ -3,6 +3,7 @@ export declare const MAX_OUTPUT_BYTES = 512000;
|
|
|
3
3
|
export declare const MAX_COMMAND_LENGTH = 500;
|
|
4
4
|
export declare const DEFAULT_TIMEOUT_MS = 60000;
|
|
5
5
|
export declare const MAX_TIMEOUT_MS = 300000;
|
|
6
|
+
export declare const MAX_SAFE_TEST_FILES = 50;
|
|
6
7
|
export declare const SUPPORTED_FRAMEWORKS: readonly ["bun", "vitest", "jest", "mocha", "pytest", "cargo", "pester", "go-test", "maven", "gradle", "dotnet-test", "ctest", "swift-test", "dart-test", "rspec", "minitest"];
|
|
7
8
|
export type TestFramework = (typeof SUPPORTED_FRAMEWORKS)[number] | 'none';
|
|
8
9
|
export interface TestRunnerArgs {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.25.
|
|
3
|
+
"version": "6.25.4",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|