opencode-swarm 7.21.4 → 7.21.5
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 +3 -2
- package/dist/config/schema.d.ts +2 -0
- package/dist/index.js +125 -8
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.21.
|
|
37
|
+
version: "7.21.5",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -17378,7 +17378,8 @@ var init_schema = __esm(() => {
|
|
|
17378
17378
|
AuthorityConfigSchema = exports_external.object({
|
|
17379
17379
|
enabled: exports_external.boolean().default(true),
|
|
17380
17380
|
rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({}),
|
|
17381
|
-
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([])
|
|
17381
|
+
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([]),
|
|
17382
|
+
verifier_config_paths: exports_external.array(exports_external.string()).optional().describe("Additional glob patterns for verifier config files that are merged into the architect agent's blockedGlobs at plugin init. Writes to matching files are blocked by the authority layer.")
|
|
17382
17383
|
});
|
|
17383
17384
|
GeneralCouncilMemberConfigSchema = exports_external.object({
|
|
17384
17385
|
memberId: exports_external.string().min(1),
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -641,6 +641,7 @@ export declare const AuthorityConfigSchema: z.ZodObject<{
|
|
|
641
641
|
allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
642
642
|
}, z.core.$strip>>>;
|
|
643
643
|
universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
644
|
+
verifier_config_paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
644
645
|
}, z.core.$strip>;
|
|
645
646
|
export type AuthorityConfig = z.infer<typeof AuthorityConfigSchema>;
|
|
646
647
|
export declare const GeneralCouncilConfigSchema: z.ZodObject<{
|
|
@@ -1005,6 +1006,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1005
1006
|
allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1006
1007
|
}, z.core.$strip>>>;
|
|
1007
1008
|
universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1009
|
+
verifier_config_paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1008
1010
|
}, z.core.$strip>>;
|
|
1009
1011
|
plan_cursor: z.ZodOptional<z.ZodObject<{
|
|
1010
1012
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.21.
|
|
36
|
+
version: "7.21.5",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -15591,7 +15591,8 @@ var init_schema = __esm(() => {
|
|
|
15591
15591
|
AuthorityConfigSchema = exports_external.object({
|
|
15592
15592
|
enabled: exports_external.boolean().default(true),
|
|
15593
15593
|
rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({}),
|
|
15594
|
-
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([])
|
|
15594
|
+
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([]),
|
|
15595
|
+
verifier_config_paths: exports_external.array(exports_external.string()).optional().describe("Additional glob patterns for verifier config files that are merged into the architect agent's blockedGlobs at plugin init. Writes to matching files are blocked by the authority layer.")
|
|
15595
15596
|
});
|
|
15596
15597
|
GeneralCouncilMemberConfigSchema = exports_external.object({
|
|
15597
15598
|
memberId: exports_external.string().min(1),
|
|
@@ -24166,6 +24167,21 @@ var init_normalize_tool_name = __esm(() => {
|
|
|
24166
24167
|
import * as fsSync2 from "node:fs";
|
|
24167
24168
|
import * as fs8 from "node:fs/promises";
|
|
24168
24169
|
import * as path10 from "node:path";
|
|
24170
|
+
function isConfigFilePath(filePath, cwd, extraGlobs) {
|
|
24171
|
+
const normalized = path10.relative(path10.resolve(cwd), path10.resolve(cwd, filePath)).replace(/\\/g, "/");
|
|
24172
|
+
const { zone } = classifyFile(normalized);
|
|
24173
|
+
if (zone === "config") {
|
|
24174
|
+
return true;
|
|
24175
|
+
}
|
|
24176
|
+
const allGlobs = extraGlobs && extraGlobs.length > 0 ? [...KNOWN_VERIFIER_CONFIG_GLOBS, ...extraGlobs] : KNOWN_VERIFIER_CONFIG_GLOBS;
|
|
24177
|
+
for (const glob of allGlobs) {
|
|
24178
|
+
const matcher = getGlobMatcher(glob);
|
|
24179
|
+
if (matcher(normalized)) {
|
|
24180
|
+
return true;
|
|
24181
|
+
}
|
|
24182
|
+
}
|
|
24183
|
+
return false;
|
|
24184
|
+
}
|
|
24169
24185
|
function enforceSpecDriftGate(directory, toolName) {
|
|
24170
24186
|
if (!directory)
|
|
24171
24187
|
return;
|
|
@@ -24713,6 +24729,17 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
24713
24729
|
};
|
|
24714
24730
|
}
|
|
24715
24731
|
const precomputedAuthorityRules = buildEffectiveRules(authorityConfig);
|
|
24732
|
+
const verifierPaths = authorityConfig?.verifier_config_paths;
|
|
24733
|
+
if (verifierPaths && verifierPaths.length > 0) {
|
|
24734
|
+
const existingArchitect = precomputedAuthorityRules.architect ?? {};
|
|
24735
|
+
precomputedAuthorityRules.architect = {
|
|
24736
|
+
...existingArchitect,
|
|
24737
|
+
blockedGlobs: [
|
|
24738
|
+
...existingArchitect.blockedGlobs ?? [],
|
|
24739
|
+
...verifierPaths
|
|
24740
|
+
]
|
|
24741
|
+
};
|
|
24742
|
+
}
|
|
24716
24743
|
const universalDenyPrefixes = authorityConfig?.universal_deny_prefixes ?? [];
|
|
24717
24744
|
const cfg = guardrailsConfig;
|
|
24718
24745
|
const requiredQaGates = cfg.qa_gates?.required_tools ?? [
|
|
@@ -25102,6 +25129,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25102
25129
|
if (!authorityCheck.allowed) {
|
|
25103
25130
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${delegTargetPath}". Reason: ${authorityCheck.reason}`);
|
|
25104
25131
|
}
|
|
25132
|
+
if (isConfigFilePath(delegTargetPath, cwd, authorityConfig?.verifier_config_paths)) {
|
|
25133
|
+
const normalizedPath = path10.relative(path10.resolve(cwd), path10.resolve(cwd, delegTargetPath)).replace(/\\/g, "/");
|
|
25134
|
+
const logEntry = {
|
|
25135
|
+
agent: agentName,
|
|
25136
|
+
path: normalizedPath,
|
|
25137
|
+
allowed: authorityCheck.allowed,
|
|
25138
|
+
type: "delegated_write"
|
|
25139
|
+
};
|
|
25140
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25141
|
+
logEntry.reason = authorityCheck.reason;
|
|
25142
|
+
}
|
|
25143
|
+
warn("Config file write attempt", logEntry);
|
|
25144
|
+
}
|
|
25105
25145
|
if (!currentSession.modifiedFilesThisCoderTask.includes(delegTargetPath)) {
|
|
25106
25146
|
currentSession.modifiedFilesThisCoderTask.push(delegTargetPath);
|
|
25107
25147
|
}
|
|
@@ -25112,6 +25152,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25112
25152
|
const cwd = effectiveDirectory;
|
|
25113
25153
|
for (const p of extractPatchTargetPaths(tool, args2)) {
|
|
25114
25154
|
const authorityCheck = checkFileAuthorityWithRules(agentName, p, cwd, precomputedAuthorityRules, { declaredScope: resolveDeclaredScope(sessionID) });
|
|
25155
|
+
if (isConfigFilePath(p, cwd, authorityConfig?.verifier_config_paths)) {
|
|
25156
|
+
const normalizedPath = path10.relative(path10.resolve(cwd), path10.resolve(cwd, p)).replace(/\\/g, "/");
|
|
25157
|
+
const logEntry = {
|
|
25158
|
+
agent: agentName,
|
|
25159
|
+
path: normalizedPath,
|
|
25160
|
+
allowed: authorityCheck.allowed,
|
|
25161
|
+
type: "delegated_patch"
|
|
25162
|
+
};
|
|
25163
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25164
|
+
logEntry.reason = authorityCheck.reason;
|
|
25165
|
+
}
|
|
25166
|
+
warn("Config file write attempt", logEntry);
|
|
25167
|
+
}
|
|
25115
25168
|
if (!authorityCheck.allowed) {
|
|
25116
25169
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${p}" (via patch). Reason: ${authorityCheck.reason}`);
|
|
25117
25170
|
}
|
|
@@ -25443,6 +25496,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25443
25496
|
if (!authorityCheck.allowed) {
|
|
25444
25497
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${targetPath}". Reason: ${authorityCheck.reason}`);
|
|
25445
25498
|
}
|
|
25499
|
+
if (isConfigFilePath(targetPath, effectiveDirectory, authorityConfig?.verifier_config_paths)) {
|
|
25500
|
+
const normalizedPath = path10.relative(path10.resolve(effectiveDirectory), path10.resolve(effectiveDirectory, targetPath)).replace(/\\/g, "/");
|
|
25501
|
+
const logEntry = {
|
|
25502
|
+
agent: agentName,
|
|
25503
|
+
path: normalizedPath,
|
|
25504
|
+
allowed: authorityCheck.allowed,
|
|
25505
|
+
type: "direct_write"
|
|
25506
|
+
};
|
|
25507
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25508
|
+
logEntry.reason = authorityCheck.reason;
|
|
25509
|
+
}
|
|
25510
|
+
warn("Config file write attempt", logEntry);
|
|
25511
|
+
}
|
|
25446
25512
|
}
|
|
25447
25513
|
}
|
|
25448
25514
|
if (input.tool === "apply_patch" || input.tool === "patch") {
|
|
@@ -25468,6 +25534,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25468
25534
|
if (!authorityCheck.allowed) {
|
|
25469
25535
|
throw new Error(`WRITE BLOCKED: Agent "${patchAgentName}" is not authorised to write "${p}" (via patch). Reason: ${authorityCheck.reason}`);
|
|
25470
25536
|
}
|
|
25537
|
+
if (isConfigFilePath(p, effectiveDirectory, authorityConfig?.verifier_config_paths)) {
|
|
25538
|
+
const normalizedPath = path10.relative(path10.resolve(effectiveDirectory), path10.resolve(effectiveDirectory, p)).replace(/\\/g, "/");
|
|
25539
|
+
const logEntry = {
|
|
25540
|
+
agent: patchAgentName,
|
|
25541
|
+
path: normalizedPath,
|
|
25542
|
+
allowed: authorityCheck.allowed,
|
|
25543
|
+
type: "direct_patch"
|
|
25544
|
+
};
|
|
25545
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25546
|
+
logEntry.reason = authorityCheck.reason;
|
|
25547
|
+
}
|
|
25548
|
+
warn("Config file write attempt", logEntry);
|
|
25549
|
+
}
|
|
25471
25550
|
}
|
|
25472
25551
|
}
|
|
25473
25552
|
{
|
|
@@ -26170,11 +26249,11 @@ function checkWriteTargetForSymlink(targetPath, cwd) {
|
|
|
26170
26249
|
}
|
|
26171
26250
|
function buildEffectiveRules(authorityConfig) {
|
|
26172
26251
|
if (authorityConfig?.enabled === false || !authorityConfig?.rules) {
|
|
26173
|
-
return DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26252
|
+
return { ...DEFAULT_AGENT_AUTHORITY_RULES };
|
|
26174
26253
|
}
|
|
26175
26254
|
const entries = Object.entries(authorityConfig.rules);
|
|
26176
26255
|
if (entries.length === 0) {
|
|
26177
|
-
return DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26256
|
+
return { ...DEFAULT_AGENT_AUTHORITY_RULES };
|
|
26178
26257
|
}
|
|
26179
26258
|
const merged = {
|
|
26180
26259
|
...DEFAULT_AGENT_AUTHORITY_RULES
|
|
@@ -26312,7 +26391,7 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
|
|
|
26312
26391
|
}
|
|
26313
26392
|
return { allowed: true };
|
|
26314
26393
|
}
|
|
26315
|
-
var import_picomatch, _internals10, SPEC_DRIFT_BLOCKED_TOOLS, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, TRANSIENT_PROVIDER_RECOVERY_TAG = "TRANSIENT PROVIDER RECOVERY", DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26394
|
+
var import_picomatch, KNOWN_VERIFIER_CONFIG_GLOBS, _internals10, SPEC_DRIFT_BLOCKED_TOOLS, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, TRANSIENT_PROVIDER_RECOVERY_TAG = "TRANSIENT PROVIDER RECOVERY", DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26316
26395
|
var init_guardrails = __esm(() => {
|
|
26317
26396
|
init_quick_lru();
|
|
26318
26397
|
init_agents2();
|
|
@@ -26332,6 +26411,17 @@ var init_guardrails = __esm(() => {
|
|
|
26332
26411
|
init_model_limits();
|
|
26333
26412
|
init_normalize_tool_name();
|
|
26334
26413
|
import_picomatch = __toESM(require_picomatch2(), 1);
|
|
26414
|
+
KNOWN_VERIFIER_CONFIG_GLOBS = [
|
|
26415
|
+
"**/oxlintrc*",
|
|
26416
|
+
"**/.oxlintrc*",
|
|
26417
|
+
"**/.eslintrc*",
|
|
26418
|
+
"**/eslint.config.*",
|
|
26419
|
+
"**/.prettierrc*",
|
|
26420
|
+
"**/prettier.config.*",
|
|
26421
|
+
"**/biome.jsonc",
|
|
26422
|
+
"**/.secretscanignore",
|
|
26423
|
+
"**/.golangci*"
|
|
26424
|
+
];
|
|
26335
26425
|
_internals10 = {
|
|
26336
26426
|
getSwarmAgents,
|
|
26337
26427
|
getMostRecentAssistantText,
|
|
@@ -26426,7 +26516,18 @@ var init_guardrails = __esm(() => {
|
|
|
26426
26516
|
explore: {},
|
|
26427
26517
|
architect: {
|
|
26428
26518
|
blockedExact: [".swarm/plan.md", ".swarm/plan.json"],
|
|
26429
|
-
blockedZones: ["generated"]
|
|
26519
|
+
blockedZones: ["generated", "config"],
|
|
26520
|
+
blockedGlobs: [
|
|
26521
|
+
"**/oxlintrc*",
|
|
26522
|
+
"**/.oxlintrc*",
|
|
26523
|
+
"**/.eslintrc*",
|
|
26524
|
+
"**/eslint.config.*",
|
|
26525
|
+
"**/.prettierrc*",
|
|
26526
|
+
"**/prettier.config.*",
|
|
26527
|
+
"**/biome.jsonc",
|
|
26528
|
+
"**/.secretscanignore",
|
|
26529
|
+
"**/.golangci*"
|
|
26530
|
+
]
|
|
26430
26531
|
},
|
|
26431
26532
|
coder: {
|
|
26432
26533
|
blockedPrefix: [".swarm/"],
|
|
@@ -65779,6 +65880,18 @@ DO (explicitly):
|
|
|
65779
65880
|
- VERIFY platform compatibility: path.join() used for all paths, no hardcoded separators
|
|
65780
65881
|
- For confirmed issues requiring a concrete fix: use suggest_patch to produce a structured patch artifact for the coder
|
|
65781
65882
|
|
|
65883
|
+
## CONFIG STRICTNESS VERIFICATION
|
|
65884
|
+
|
|
65885
|
+
When the declared scope includes a verifier/linter config file (biome.json, biome.jsonc, oxlintrc, oxlintrc.json, .eslintrc, .eslintrc.json, eslint.config.*, .prettierrc, .prettierrc.json, prettier.config.*, biome.jsonc, .secretscanignore, golangci-lint configs, tsconfig.json, tsconfig.*.json, or any other linter/formatter/security-tool configuration):
|
|
65886
|
+
|
|
65887
|
+
- Verify the change does NOT reduce strictness of any existing rule
|
|
65888
|
+
- Reject changes that downgrade "error" to "warn", remove rules, weaken validation thresholds, or narrow file/directory scopes
|
|
65889
|
+
- Allow changes that ADD new stricter rules, enable additional rule categories, fix syntax errors, or correct misconfigured paths
|
|
65890
|
+
- Document the specific config change and its impact on validation strictness in your review output
|
|
65891
|
+
- If a rule is changed from "error" to "warn" or a rule is removed: REJECT with STRICTNESS_REDUCTION: [rule name] — [original setting] → [new setting]
|
|
65892
|
+
|
|
65893
|
+
This is a pre-review gate: if config strictness is reduced, reject immediately without proceeding to Tier review.
|
|
65894
|
+
|
|
65782
65895
|
## REUSE RE-VERIFICATION (MANDATORY FOR NEW EXPORTS)
|
|
65783
65896
|
|
|
65784
65897
|
When EXPORTS_ADDED is non-empty in the coder's completion report:
|
|
@@ -80616,7 +80729,9 @@ var DENY_SHELL_PATTERNS = [
|
|
|
80616
80729
|
/\bbunx?\s+publish\b/i,
|
|
80617
80730
|
/\bterraform\s+(?:apply|destroy)\b/i,
|
|
80618
80731
|
/\bkubectl\s+(?:delete|apply\s+-f)/i,
|
|
80619
|
-
/\bdrop\s+(?:database|table)\b/i
|
|
80732
|
+
/\bdrop\s+(?:database|table)\b/i,
|
|
80733
|
+
/\bsed\s+-i\b(?=[^\n]*\b(?:biome\.json|eslintrc|oxlintrc)\b)(?=[^\n]*\b(?:error|warn|off)\b)/i,
|
|
80734
|
+
/\b(?:cat|tee)\b[^\n]*>\s*[^\n]*\b(biome\.json|eslintrc|oxlintrc)\b[^\n]*\b(error|warn|off)\b/i
|
|
80620
80735
|
];
|
|
80621
80736
|
var ESCALATE_SHELL_PATTERNS = [
|
|
80622
80737
|
/\bcurl\b/i,
|
|
@@ -80636,7 +80751,9 @@ var ESCALATE_SHELL_PATTERNS = [
|
|
|
80636
80751
|
/\bgit\s+pull\b/i,
|
|
80637
80752
|
/\bgit\s+rebase\b/i,
|
|
80638
80753
|
/\bgit\s+merge\b/i,
|
|
80639
|
-
/\bgit\s+commit\b/i
|
|
80754
|
+
/\bgit\s+commit\b/i,
|
|
80755
|
+
/\b(sed\s+-i|echo\s+|printf\s+)[^\n]*\b(biome\.jsonc?|eslintrc|eslint\.config|oxlintrc|prettierrc|secretscanignore|golangci|tsconfig\.json|tsconfig\.[^.]+\.json)\b/i,
|
|
80756
|
+
/\b(?:cat|tee)\b[^\n]*>\s*[^\n]*\b(biome\.jsonc?|eslintrc|eslint\.config|oxlintrc|prettierrc|secretscanignore|golangci|tsconfig\.json|tsconfig\.[^.]+\.json)\b/i
|
|
80640
80757
|
];
|
|
80641
80758
|
function isReadOnlyTool(toolName) {
|
|
80642
80759
|
if (!toolName)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.21.
|
|
3
|
+
"version": "7.21.5",
|
|
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",
|