opencode-swarm 6.25.7 → 6.25.9
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 +17 -6
- package/dist/evidence/manager.d.ts +5 -2
- package/dist/gate-evidence.d.ts +13 -0
- package/dist/index.js +51 -12
- package/dist/session/snapshot-writer.d.ts +2 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -14275,10 +14275,16 @@ function sanitizeTaskId(taskId) {
|
|
|
14275
14275
|
if (taskId.includes("..") || taskId.includes("../") || taskId.includes("..\\")) {
|
|
14276
14276
|
throw new Error("Invalid task ID: path traversal detected");
|
|
14277
14277
|
}
|
|
14278
|
-
if (
|
|
14279
|
-
|
|
14278
|
+
if (TASK_ID_REGEX.test(taskId)) {
|
|
14279
|
+
return taskId;
|
|
14280
14280
|
}
|
|
14281
|
-
|
|
14281
|
+
if (RETRO_TASK_ID_REGEX.test(taskId)) {
|
|
14282
|
+
return taskId;
|
|
14283
|
+
}
|
|
14284
|
+
if (INTERNAL_TOOL_ID_REGEX.test(taskId)) {
|
|
14285
|
+
return taskId;
|
|
14286
|
+
}
|
|
14287
|
+
throw new Error(`Invalid task ID: must match pattern ^\\d+\\.\\d+(\\.\\d+)*$, ^retro-\\d+$, or ^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build)$, got "${taskId}"`);
|
|
14282
14288
|
}
|
|
14283
14289
|
async function saveEvidence(directory, taskId, evidence) {
|
|
14284
14290
|
const sanitizedTaskId = sanitizeTaskId(taskId);
|
|
@@ -14488,13 +14494,15 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
|
14488
14494
|
}
|
|
14489
14495
|
return archived;
|
|
14490
14496
|
}
|
|
14491
|
-
var TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
14497
|
+
var TASK_ID_REGEX, RETRO_TASK_ID_REGEX, INTERNAL_TOOL_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
14492
14498
|
var init_manager = __esm(() => {
|
|
14493
14499
|
init_zod();
|
|
14494
14500
|
init_evidence_schema();
|
|
14495
14501
|
init_utils2();
|
|
14496
14502
|
init_utils();
|
|
14497
|
-
TASK_ID_REGEX =
|
|
14503
|
+
TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
14504
|
+
RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
14505
|
+
INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build)$/;
|
|
14498
14506
|
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
14499
14507
|
low: "simple",
|
|
14500
14508
|
medium: "moderate",
|
|
@@ -30959,7 +30967,10 @@ function serializeAgentSession(s) {
|
|
|
30959
30967
|
lastCompletedPhaseAgentsDispatched,
|
|
30960
30968
|
qaSkipCount: s.qaSkipCount ?? 0,
|
|
30961
30969
|
qaSkipTaskIds: s.qaSkipTaskIds ?? [],
|
|
30962
|
-
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map)
|
|
30970
|
+
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
|
|
30971
|
+
...s.scopeViolationDetected !== undefined && {
|
|
30972
|
+
scopeViolationDetected: s.scopeViolationDetected
|
|
30973
|
+
}
|
|
30963
30974
|
};
|
|
30964
30975
|
}
|
|
30965
30976
|
async function writeSnapshot(directory, state) {
|
|
@@ -34,8 +34,11 @@ export declare function isBuildEvidence(evidence: Evidence): evidence is BuildEv
|
|
|
34
34
|
export declare function isQualityBudgetEvidence(evidence: Evidence): evidence is QualityBudgetEvidence;
|
|
35
35
|
/**
|
|
36
36
|
* Validate and sanitize task ID.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* Accepts three formats:
|
|
38
|
+
* 1. Canonical N.M or N.M.P numeric format (matches TASK_ID_REGEX)
|
|
39
|
+
* 2. Retrospective format: retro-<number> (matches RETRO_TASK_ID_REGEX)
|
|
40
|
+
* 3. Internal automated-tool format: specific tool IDs (sast_scan, quality_budget, syntax_check, placeholder_scan, sbom_generate, build)
|
|
41
|
+
* Rejects: .., ../, null bytes, control characters, empty string, other non-numeric IDs
|
|
39
42
|
* @throws Error with descriptive message on failure
|
|
40
43
|
*/
|
|
41
44
|
export declare function sanitizeTaskId(taskId: string): string;
|
package/dist/gate-evidence.d.ts
CHANGED
|
@@ -21,6 +21,19 @@ export interface TaskEvidence {
|
|
|
21
21
|
gates: Record<string, GateEvidence>;
|
|
22
22
|
}
|
|
23
23
|
export declare const DEFAULT_REQUIRED_GATES: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Canonical task-id validation helper.
|
|
26
|
+
* Returns true if the taskId is a valid numeric format (N.M or N.M.P),
|
|
27
|
+
* false otherwise.
|
|
28
|
+
*
|
|
29
|
+
* Validates:
|
|
30
|
+
* - Non-empty string
|
|
31
|
+
* - Matches N.M or N.M.P numeric pattern (e.g., "1.1", "1.2.3")
|
|
32
|
+
* - No path traversal (..)
|
|
33
|
+
* - No path separators (/, \)
|
|
34
|
+
* - No null bytes
|
|
35
|
+
*/
|
|
36
|
+
export declare function isValidTaskId(taskId: string): boolean;
|
|
24
37
|
/**
|
|
25
38
|
* Maps the first-dispatched agent type to the initial required_gates array.
|
|
26
39
|
* Unknown agent types fall back to the safe default ["reviewer", "test_engineer"].
|
package/dist/index.js
CHANGED
|
@@ -15368,10 +15368,16 @@ function sanitizeTaskId(taskId) {
|
|
|
15368
15368
|
if (taskId.includes("..") || taskId.includes("../") || taskId.includes("..\\")) {
|
|
15369
15369
|
throw new Error("Invalid task ID: path traversal detected");
|
|
15370
15370
|
}
|
|
15371
|
-
if (
|
|
15372
|
-
|
|
15371
|
+
if (TASK_ID_REGEX.test(taskId)) {
|
|
15372
|
+
return taskId;
|
|
15373
15373
|
}
|
|
15374
|
-
|
|
15374
|
+
if (RETRO_TASK_ID_REGEX.test(taskId)) {
|
|
15375
|
+
return taskId;
|
|
15376
|
+
}
|
|
15377
|
+
if (INTERNAL_TOOL_ID_REGEX.test(taskId)) {
|
|
15378
|
+
return taskId;
|
|
15379
|
+
}
|
|
15380
|
+
throw new Error(`Invalid task ID: must match pattern ^\\d+\\.\\d+(\\.\\d+)*$, ^retro-\\d+$, or ^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build)$, got "${taskId}"`);
|
|
15375
15381
|
}
|
|
15376
15382
|
async function saveEvidence(directory, taskId, evidence) {
|
|
15377
15383
|
const sanitizedTaskId = sanitizeTaskId(taskId);
|
|
@@ -15581,7 +15587,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
|
15581
15587
|
}
|
|
15582
15588
|
return archived;
|
|
15583
15589
|
}
|
|
15584
|
-
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
15590
|
+
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX, RETRO_TASK_ID_REGEX, INTERNAL_TOOL_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
15585
15591
|
var init_manager = __esm(() => {
|
|
15586
15592
|
init_zod();
|
|
15587
15593
|
init_evidence_schema();
|
|
@@ -15601,7 +15607,9 @@ var init_manager = __esm(() => {
|
|
|
15601
15607
|
"build",
|
|
15602
15608
|
"quality_budget"
|
|
15603
15609
|
];
|
|
15604
|
-
TASK_ID_REGEX =
|
|
15610
|
+
TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
15611
|
+
RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
15612
|
+
INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build)$/;
|
|
15605
15613
|
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
15606
15614
|
low: "simple",
|
|
15607
15615
|
medium: "moderate",
|
|
@@ -35895,6 +35903,7 @@ __export(exports_gate_evidence, {
|
|
|
35895
35903
|
recordGateEvidence: () => recordGateEvidence,
|
|
35896
35904
|
recordAgentDispatch: () => recordAgentDispatch,
|
|
35897
35905
|
readTaskEvidence: () => readTaskEvidence,
|
|
35906
|
+
isValidTaskId: () => isValidTaskId2,
|
|
35898
35907
|
hasPassedAllGates: () => hasPassedAllGates,
|
|
35899
35908
|
expandRequiredGates: () => expandRequiredGates,
|
|
35900
35909
|
deriveRequiredGates: () => deriveRequiredGates,
|
|
@@ -35902,8 +35911,21 @@ __export(exports_gate_evidence, {
|
|
|
35902
35911
|
});
|
|
35903
35912
|
import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "fs";
|
|
35904
35913
|
import * as path27 from "path";
|
|
35914
|
+
function isValidTaskId2(taskId) {
|
|
35915
|
+
if (!taskId)
|
|
35916
|
+
return false;
|
|
35917
|
+
if (taskId.includes(".."))
|
|
35918
|
+
return false;
|
|
35919
|
+
if (taskId.includes("/"))
|
|
35920
|
+
return false;
|
|
35921
|
+
if (taskId.includes("\\"))
|
|
35922
|
+
return false;
|
|
35923
|
+
if (taskId.includes("\x00"))
|
|
35924
|
+
return false;
|
|
35925
|
+
return TASK_ID_PATTERN.test(taskId);
|
|
35926
|
+
}
|
|
35905
35927
|
function assertValidTaskId(taskId) {
|
|
35906
|
-
if (!
|
|
35928
|
+
if (!isValidTaskId2(taskId)) {
|
|
35907
35929
|
throw new Error(`Invalid taskId: "${taskId}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3").`);
|
|
35908
35930
|
}
|
|
35909
35931
|
}
|
|
@@ -46050,7 +46072,10 @@ function serializeAgentSession(s) {
|
|
|
46050
46072
|
lastCompletedPhaseAgentsDispatched,
|
|
46051
46073
|
qaSkipCount: s.qaSkipCount ?? 0,
|
|
46052
46074
|
qaSkipTaskIds: s.qaSkipTaskIds ?? [],
|
|
46053
|
-
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map)
|
|
46075
|
+
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
|
|
46076
|
+
...s.scopeViolationDetected !== undefined && {
|
|
46077
|
+
scopeViolationDetected: s.scopeViolationDetected
|
|
46078
|
+
}
|
|
46054
46079
|
};
|
|
46055
46080
|
}
|
|
46056
46081
|
async function writeSnapshot(directory, state) {
|
|
@@ -52795,6 +52820,7 @@ function deserializeAgentSession(s) {
|
|
|
52795
52820
|
lastGateOutcome: null,
|
|
52796
52821
|
declaredCoderScope: null,
|
|
52797
52822
|
lastScopeViolation: null,
|
|
52823
|
+
scopeViolationDetected: s.scopeViolationDetected,
|
|
52798
52824
|
modifiedFilesThisCoderTask: []
|
|
52799
52825
|
};
|
|
52800
52826
|
}
|
|
@@ -53073,6 +53099,20 @@ init_create_tool();
|
|
|
53073
53099
|
import * as fs19 from "fs";
|
|
53074
53100
|
import * as path32 from "path";
|
|
53075
53101
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
53102
|
+
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
53103
|
+
function isValidTaskId3(taskId) {
|
|
53104
|
+
if (!taskId)
|
|
53105
|
+
return false;
|
|
53106
|
+
if (taskId.includes(".."))
|
|
53107
|
+
return false;
|
|
53108
|
+
if (taskId.includes("/"))
|
|
53109
|
+
return false;
|
|
53110
|
+
if (taskId.includes("\\"))
|
|
53111
|
+
return false;
|
|
53112
|
+
if (taskId.includes("\x00"))
|
|
53113
|
+
return false;
|
|
53114
|
+
return TASK_ID_PATTERN2.test(taskId);
|
|
53115
|
+
}
|
|
53076
53116
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
53077
53117
|
const normalizedWorkspace = path32.resolve(workspaceRoot);
|
|
53078
53118
|
const swarmPath = path32.join(normalizedWorkspace, ".swarm", "evidence");
|
|
@@ -53103,7 +53143,7 @@ function readEvidenceFile(evidencePath) {
|
|
|
53103
53143
|
var check_gate_status = createSwarmTool({
|
|
53104
53144
|
description: "Read-only tool to check the gate status of a specific task. Reads .swarm/evidence/{taskId}.json and returns structured JSON describing required, passed, and missing gates.",
|
|
53105
53145
|
args: {
|
|
53106
|
-
task_id: tool.schema.string().min(1).regex(/^\d+\.\d+(\.\d+)
|
|
53146
|
+
task_id: tool.schema.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/, 'Task ID must be in N.M or N.M.P format (e.g., "1.1", "1.2.3", "1.2.3.4")').describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")')
|
|
53107
53147
|
},
|
|
53108
53148
|
async execute(args2, directory) {
|
|
53109
53149
|
let taskIdInput;
|
|
@@ -53125,8 +53165,7 @@ var check_gate_status = createSwarmTool({
|
|
|
53125
53165
|
};
|
|
53126
53166
|
return JSON.stringify(errorResult, null, 2);
|
|
53127
53167
|
}
|
|
53128
|
-
|
|
53129
|
-
if (!taskIdPattern.test(taskIdInput)) {
|
|
53168
|
+
if (!isValidTaskId3(taskIdInput)) {
|
|
53130
53169
|
const errorResult = {
|
|
53131
53170
|
taskId: taskIdInput,
|
|
53132
53171
|
status: "no_evidence",
|
|
@@ -53134,7 +53173,7 @@ var check_gate_status = createSwarmTool({
|
|
|
53134
53173
|
passed_gates: [],
|
|
53135
53174
|
missing_gates: [],
|
|
53136
53175
|
gates: {},
|
|
53137
|
-
message: `Invalid task_id format: "${taskIdInput}". Must match
|
|
53176
|
+
message: `Invalid task_id format: "${taskIdInput}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3", "1.2.3.4")`
|
|
53138
53177
|
};
|
|
53139
53178
|
return JSON.stringify(errorResult, null, 2);
|
|
53140
53179
|
}
|
|
@@ -53846,7 +53885,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
53846
53885
|
errors: ["Invalid working_directory: null bytes are not allowed"]
|
|
53847
53886
|
};
|
|
53848
53887
|
}
|
|
53849
|
-
|
|
53888
|
+
{
|
|
53850
53889
|
const devicePathPattern = /^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i;
|
|
53851
53890
|
if (devicePathPattern.test(args2.working_directory)) {
|
|
53852
53891
|
return {
|
|
@@ -37,6 +37,8 @@ export interface SerializedAgentSession {
|
|
|
37
37
|
qaSkipCount: number;
|
|
38
38
|
qaSkipTaskIds: string[];
|
|
39
39
|
taskWorkflowStates?: Record<string, string>;
|
|
40
|
+
/** Flag for one-shot scope violation warning injection (omitted when undefined for additive-only schema) */
|
|
41
|
+
scopeViolationDetected?: boolean;
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
44
|
* Minimal interface for serialized InvocationWindow
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.25.
|
|
3
|
+
"version": "6.25.9",
|
|
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",
|