opencode-swarm 7.50.4 → 7.51.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/cli/index.js +54 -15
- package/dist/index.js +1324 -566
- package/dist/lang/backend.d.ts +1 -0
- package/dist/tools/git-blame.d.ts +21 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/suggest-patch.d.ts +1 -0
- package/dist/tools/test-runner.d.ts +3 -2
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -735,6 +735,11 @@ Swarm provides tools for managing generated skill lifecycles:
|
|
|
735
735
|
| mutation_test | Applies LLM-generated mutation patches to source files and runs tests to measure kill rate; verdict is pass/warn/fail based on configurable thresholds; used by the mutation_test gate (opt-in, off by default) |
|
|
736
736
|
| generate_mutants | Architect-only: generates LLM-based mutation patches (5–10 per function across 6 types: off-by-one, null substitution, operator swap, guard removal, branch swap, side-effect deletion) for direct consumption by the mutation_test tool; returns SKIP verdict on LLM failure rather than throwing |
|
|
737
737
|
| write_mutation_evidence | Architect-only: writes mutation gate results atomically to `.swarm/evidence/{phase}/mutation-gate.json`; accepts verdict (PASS/WARN/FAIL/SKIP), kill rate metrics, and optional survived mutant details; normalizes uppercase-to-lowercase before persisting |
|
|
738
|
+
| git_blame | Per-line git blame metadata (sha, author, date, summary) via `git blame --porcelain`; supports optional line range filtering |
|
|
739
|
+
| diff | Structured git diff with contract change detection; supports `summaryOnly` mode returning file list with additions/deletions counts |
|
|
740
|
+
| suggest_patch | Reviewer-safe structured patch suggestion; supports `format` parameter ('json' or 'unified') where unified outputs valid unified diff with `diff --git` headers, hunks, and context |
|
|
741
|
+
| test_runner | Auto-detect and run tests; supports `bail` parameter to inject framework-specific bail flags for early exit on first failure |
|
|
742
|
+
| symbols | Extract exported symbols from source files; supports `workspace` (boolean) and `name` (string) parameters for multi-file symbol search |
|
|
738
743
|
|
|
739
744
|
|
|
740
745
|
All tools run locally. No Docker, no network calls, no external APIs.
|
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "opencode-swarm",
|
|
55
|
-
version: "7.
|
|
55
|
+
version: "7.51.1",
|
|
56
56
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
57
57
|
main: "dist/index.js",
|
|
58
58
|
types: "dist/index.d.ts",
|
|
@@ -16499,7 +16499,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
16499
16499
|
agents: ["architect", "reviewer", "critic_oversight"]
|
|
16500
16500
|
},
|
|
16501
16501
|
syntax_check: {
|
|
16502
|
-
description: "syntax
|
|
16502
|
+
description: "check syntax of source files using tree-sitter parsers across multiple languages, returning per-file errors",
|
|
16503
16503
|
agents: ["architect", "coder", "test_engineer"]
|
|
16504
16504
|
},
|
|
16505
16505
|
placeholder_scan: {
|
|
@@ -16507,7 +16507,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
16507
16507
|
agents: ["architect", "reviewer"]
|
|
16508
16508
|
},
|
|
16509
16509
|
imports: {
|
|
16510
|
-
description: "
|
|
16510
|
+
description: "find all consumers that import from a given file \u2014 use before refactoring shared modules to avoid breaking unseen dependents",
|
|
16511
16511
|
agents: [
|
|
16512
16512
|
"architect",
|
|
16513
16513
|
"sme",
|
|
@@ -16525,11 +16525,11 @@ var init_tool_metadata = __esm(() => {
|
|
|
16525
16525
|
]
|
|
16526
16526
|
},
|
|
16527
16527
|
lint: {
|
|
16528
|
-
description: "
|
|
16528
|
+
description: "run project linter in check or fix mode; supports biome, eslint, ruff, clippy, and more, returns structured results",
|
|
16529
16529
|
agents: ["architect", "reviewer", "coder"]
|
|
16530
16530
|
},
|
|
16531
16531
|
secretscan: {
|
|
16532
|
-
description: "
|
|
16532
|
+
description: "scan for secrets (API keys, tokens, passwords) via regex and entropy; returns redacted previews, excludes common dirs",
|
|
16533
16533
|
agents: ["architect", "reviewer", "critic_oversight"]
|
|
16534
16534
|
},
|
|
16535
16535
|
sast_scan: {
|
|
@@ -16537,7 +16537,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
16537
16537
|
agents: ["architect", "reviewer", "critic_oversight"]
|
|
16538
16538
|
},
|
|
16539
16539
|
build_check: {
|
|
16540
|
-
description: "build
|
|
16540
|
+
description: "discover and run build, typecheck, and test commands for various project ecosystems in the working directory",
|
|
16541
16541
|
agents: ["architect", "coder", "test_engineer"]
|
|
16542
16542
|
},
|
|
16543
16543
|
pre_check_batch: {
|
|
@@ -16549,7 +16549,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
16549
16549
|
agents: ["architect"]
|
|
16550
16550
|
},
|
|
16551
16551
|
symbols: {
|
|
16552
|
-
description: "
|
|
16552
|
+
description: "extract exported symbols (functions, classes, interfaces, types) from source files; supports TypeScript, JavaScript, and Python",
|
|
16553
16553
|
agents: [
|
|
16554
16554
|
"architect",
|
|
16555
16555
|
"sme",
|
|
@@ -16620,7 +16620,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
16620
16620
|
agents: ["architect"]
|
|
16621
16621
|
},
|
|
16622
16622
|
checkpoint: {
|
|
16623
|
-
description: "
|
|
16623
|
+
description: "create named git checkpoints for save, restore, and delete \u2014 use before risky operations to enable rollback",
|
|
16624
16624
|
agents: ["architect"]
|
|
16625
16625
|
},
|
|
16626
16626
|
pkg_audit: {
|
|
@@ -16664,6 +16664,10 @@ var init_tool_metadata = __esm(() => {
|
|
|
16664
16664
|
"explorer"
|
|
16665
16665
|
]
|
|
16666
16666
|
},
|
|
16667
|
+
git_blame: {
|
|
16668
|
+
description: "per-line git blame metadata: sha, author, date, summary for each line in a file",
|
|
16669
|
+
agents: ["reviewer", "explorer", "architect"]
|
|
16670
|
+
},
|
|
16667
16671
|
gitingest: {
|
|
16668
16672
|
description: "fetch a GitHub repository full content via gitingest.com",
|
|
16669
16673
|
agents: ["architect", "docs", "explorer"]
|
|
@@ -51215,11 +51219,14 @@ async function defaultSelectTestFramework(profile, dir) {
|
|
|
51215
51219
|
function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}) {
|
|
51216
51220
|
const scope = opts.scope ?? "all";
|
|
51217
51221
|
const coverage = opts.coverage ?? false;
|
|
51222
|
+
const bail = opts.bail ?? false;
|
|
51218
51223
|
switch (framework) {
|
|
51219
51224
|
case "bun": {
|
|
51220
51225
|
const args = ["bun", "test"];
|
|
51221
51226
|
if (coverage)
|
|
51222
51227
|
args.push("--coverage");
|
|
51228
|
+
if (bail)
|
|
51229
|
+
args.push("--bail");
|
|
51223
51230
|
if (scope !== "all" && files.length > 0)
|
|
51224
51231
|
args.push(...files);
|
|
51225
51232
|
return args;
|
|
@@ -51235,6 +51242,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
51235
51242
|
];
|
|
51236
51243
|
if (coverage)
|
|
51237
51244
|
args.push("--coverage");
|
|
51245
|
+
if (bail)
|
|
51246
|
+
args.push("--bail");
|
|
51238
51247
|
if (scope !== "all" && files.length > 0)
|
|
51239
51248
|
args.push(...files);
|
|
51240
51249
|
return args;
|
|
@@ -51243,12 +51252,16 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
51243
51252
|
const args = ["npx", "jest", "--json"];
|
|
51244
51253
|
if (coverage)
|
|
51245
51254
|
args.push("--coverage");
|
|
51255
|
+
if (bail)
|
|
51256
|
+
args.push("--bail");
|
|
51246
51257
|
if (scope !== "all" && files.length > 0)
|
|
51247
51258
|
args.push(...files);
|
|
51248
51259
|
return args;
|
|
51249
51260
|
}
|
|
51250
51261
|
case "mocha": {
|
|
51251
51262
|
const args = ["npx", "mocha"];
|
|
51263
|
+
if (bail)
|
|
51264
|
+
args.push("--bail");
|
|
51252
51265
|
if (scope !== "all" && files.length > 0)
|
|
51253
51266
|
args.push(...files);
|
|
51254
51267
|
return args;
|
|
@@ -51258,6 +51271,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
51258
51271
|
const args = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
|
|
51259
51272
|
if (coverage)
|
|
51260
51273
|
args.push("--cov=.", "--cov-report=term-missing");
|
|
51274
|
+
if (bail)
|
|
51275
|
+
args.push("-x");
|
|
51261
51276
|
if (scope !== "all" && files.length > 0)
|
|
51262
51277
|
args.push(...files);
|
|
51263
51278
|
return args;
|
|
@@ -51311,6 +51326,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
51311
51326
|
return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
|
|
51312
51327
|
case "rspec": {
|
|
51313
51328
|
const args = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
|
|
51329
|
+
if (bail)
|
|
51330
|
+
args.push("--fail-fast");
|
|
51314
51331
|
if (scope !== "all" && files.length > 0)
|
|
51315
51332
|
args.push(...files);
|
|
51316
51333
|
return args;
|
|
@@ -53285,6 +53302,10 @@ function validateArgs2(args) {
|
|
|
53285
53302
|
if (typeof obj.coverage !== "boolean")
|
|
53286
53303
|
return false;
|
|
53287
53304
|
}
|
|
53305
|
+
if (obj.bail !== undefined) {
|
|
53306
|
+
if (typeof obj.bail !== "boolean")
|
|
53307
|
+
return false;
|
|
53308
|
+
}
|
|
53288
53309
|
if (obj.timeout_ms !== undefined) {
|
|
53289
53310
|
if (typeof obj.timeout_ms !== "number")
|
|
53290
53311
|
return false;
|
|
@@ -53360,7 +53381,7 @@ async function detectTestFrameworkViaDispatch(cwd) {
|
|
|
53360
53381
|
return "none";
|
|
53361
53382
|
}
|
|
53362
53383
|
}
|
|
53363
|
-
async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir) {
|
|
53384
|
+
async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir, bail) {
|
|
53364
53385
|
if (framework === "none")
|
|
53365
53386
|
return null;
|
|
53366
53387
|
try {
|
|
@@ -53369,7 +53390,8 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
|
|
|
53369
53390
|
if (backend?.buildTestCommand) {
|
|
53370
53391
|
const cmd = backend.buildTestCommand(framework, files, baseDir, {
|
|
53371
53392
|
scope,
|
|
53372
|
-
coverage
|
|
53393
|
+
coverage,
|
|
53394
|
+
bail
|
|
53373
53395
|
});
|
|
53374
53396
|
if (cmd)
|
|
53375
53397
|
return cmd;
|
|
@@ -53738,12 +53760,14 @@ function getTargetedExecutionUnsupportedReason(framework) {
|
|
|
53738
53760
|
return null;
|
|
53739
53761
|
}
|
|
53740
53762
|
}
|
|
53741
|
-
function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
53763
|
+
function buildTestCommand2(framework, scope, files, coverage, baseDir, bail) {
|
|
53742
53764
|
switch (framework) {
|
|
53743
53765
|
case "bun": {
|
|
53744
53766
|
const args = ["bun", "test"];
|
|
53745
53767
|
if (coverage)
|
|
53746
53768
|
args.push("--coverage");
|
|
53769
|
+
if (bail)
|
|
53770
|
+
args.push("--bail");
|
|
53747
53771
|
if (scope !== "all" && files.length > 0) {
|
|
53748
53772
|
args.push(...files);
|
|
53749
53773
|
}
|
|
@@ -53760,6 +53784,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
53760
53784
|
];
|
|
53761
53785
|
if (coverage)
|
|
53762
53786
|
args.push("--coverage");
|
|
53787
|
+
if (bail)
|
|
53788
|
+
args.push("--bail=1");
|
|
53763
53789
|
if (scope !== "all" && files.length > 0) {
|
|
53764
53790
|
args.push(...files);
|
|
53765
53791
|
}
|
|
@@ -53769,6 +53795,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
53769
53795
|
const args = ["npx", "jest", "--json"];
|
|
53770
53796
|
if (coverage)
|
|
53771
53797
|
args.push("--coverage");
|
|
53798
|
+
if (bail)
|
|
53799
|
+
args.push("--bail");
|
|
53772
53800
|
if (scope !== "all" && files.length > 0) {
|
|
53773
53801
|
args.push(...files);
|
|
53774
53802
|
}
|
|
@@ -53776,6 +53804,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
53776
53804
|
}
|
|
53777
53805
|
case "mocha": {
|
|
53778
53806
|
const args = ["npx", "mocha"];
|
|
53807
|
+
if (bail)
|
|
53808
|
+
args.push("--bail");
|
|
53779
53809
|
if (scope !== "all" && files.length > 0) {
|
|
53780
53810
|
args.push(...files);
|
|
53781
53811
|
}
|
|
@@ -53786,6 +53816,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
53786
53816
|
const args = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
|
|
53787
53817
|
if (coverage)
|
|
53788
53818
|
args.push("--cov=.", "--cov-report=term-missing");
|
|
53819
|
+
if (bail)
|
|
53820
|
+
args.push("-x");
|
|
53789
53821
|
if (scope !== "all" && files.length > 0) {
|
|
53790
53822
|
args.push(...files);
|
|
53791
53823
|
}
|
|
@@ -53842,6 +53874,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
53842
53874
|
return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
|
|
53843
53875
|
case "rspec": {
|
|
53844
53876
|
const args = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
|
|
53877
|
+
if (bail)
|
|
53878
|
+
args.push("--fail-fast");
|
|
53845
53879
|
if (scope !== "all" && files.length > 0) {
|
|
53846
53880
|
args.push(...files);
|
|
53847
53881
|
}
|
|
@@ -54227,7 +54261,7 @@ async function readBoundedStream(stream, maxBytes) {
|
|
|
54227
54261
|
}
|
|
54228
54262
|
return { text: decoder.decode(combined), truncated };
|
|
54229
54263
|
}
|
|
54230
|
-
async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
54264
|
+
async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail) {
|
|
54231
54265
|
if (scope !== "all" && files.length > 0) {
|
|
54232
54266
|
const unsupportedReason = getTargetedExecutionUnsupportedReason(framework);
|
|
54233
54267
|
if (unsupportedReason) {
|
|
@@ -54242,7 +54276,7 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
54242
54276
|
}
|
|
54243
54277
|
}
|
|
54244
54278
|
const useDispatchBuild = process.env.SWARM_LANG_BACKEND !== "legacy";
|
|
54245
|
-
const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd) ?? buildTestCommand2(framework, scope, files, coverage, cwd) : buildTestCommand2(framework, scope, files, coverage, cwd);
|
|
54279
|
+
const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd, bail) ?? buildTestCommand2(framework, scope, files, coverage, cwd, bail) : buildTestCommand2(framework, scope, files, coverage, cwd, bail);
|
|
54246
54280
|
if (!command) {
|
|
54247
54281
|
return {
|
|
54248
54282
|
success: false,
|
|
@@ -54590,6 +54624,7 @@ var init_test_runner = __esm(() => {
|
|
|
54590
54624
|
scope: exports_external.enum(["all", "convention", "graph", "impact"]).optional().describe('Test scope: "all" runs full suite, "convention" accepts direct test files or maps source files to tests by naming, "graph" finds related tests via imports from source files, "impact" finds tests covering changed source files via test-impact analysis'),
|
|
54591
54625
|
files: exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
|
|
54592
54626
|
coverage: exports_external.boolean().optional().describe("Enable coverage reporting if supported"),
|
|
54627
|
+
bail: exports_external.boolean().optional().describe("Stop running tests after the first failure. Default false. Note: coverage may be incomplete when bail=true with coverage=true."),
|
|
54593
54628
|
timeout_ms: exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
|
|
54594
54629
|
allow_full_suite: exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
|
|
54595
54630
|
working_directory: exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
@@ -54690,6 +54725,7 @@ var init_test_runner = __esm(() => {
|
|
|
54690
54725
|
}
|
|
54691
54726
|
const _files = args.files || [];
|
|
54692
54727
|
const coverage = args.coverage || false;
|
|
54728
|
+
const bail = args.bail || false;
|
|
54693
54729
|
const timeout_ms = Math.min(args.timeout_ms || DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
|
|
54694
54730
|
const useDispatch = process.env.SWARM_LANG_BACKEND !== "legacy";
|
|
54695
54731
|
let framework;
|
|
@@ -54928,7 +54964,7 @@ var init_test_runner = __esm(() => {
|
|
|
54928
54964
|
};
|
|
54929
54965
|
return JSON.stringify(errorResult, null, 2);
|
|
54930
54966
|
}
|
|
54931
|
-
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir);
|
|
54967
|
+
const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir, bail);
|
|
54932
54968
|
recordAndAnalyzeResults(result, testFiles, workingDir, _files.length > 0 ? _files : undefined, result.testCases);
|
|
54933
54969
|
let historyReport;
|
|
54934
54970
|
if (!result.success && result.totals && result.totals.failed > 0) {
|
|
@@ -54944,6 +54980,9 @@ var init_test_runner = __esm(() => {
|
|
|
54944
54980
|
if (graphFallbackReason && result.message) {
|
|
54945
54981
|
result.message = `${result.message} (${graphFallbackReason})`;
|
|
54946
54982
|
}
|
|
54983
|
+
if (bail && coverage && result.message) {
|
|
54984
|
+
result.message = `${result.message} (coverage may be incomplete: bail=true stopped early)`;
|
|
54985
|
+
}
|
|
54947
54986
|
return JSON.stringify(result, null, 2);
|
|
54948
54987
|
}
|
|
54949
54988
|
});
|
|
@@ -55148,7 +55187,7 @@ async function runLintCheck(dir, linter, timeoutMs) {
|
|
|
55148
55187
|
async function runTestsCheck(_dir, scope, timeoutMs) {
|
|
55149
55188
|
const startTime = Date.now();
|
|
55150
55189
|
try {
|
|
55151
|
-
const result = await runTests("none", scope, [], false, timeoutMs, _dir);
|
|
55190
|
+
const result = await runTests("none", scope, [], false, timeoutMs, _dir, false);
|
|
55152
55191
|
if (!result.success) {
|
|
55153
55192
|
return {
|
|
55154
55193
|
type: "tests",
|