opencode-swarm 6.25.7 → 6.25.8
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 +13 -6
- package/dist/evidence/manager.d.ts +4 -2
- package/dist/gate-evidence.d.ts +13 -0
- package/dist/index.js +47 -12
- package/dist/session/snapshot-writer.d.ts +2 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -14275,10 +14275,13 @@ 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
|
+
throw new Error(`Invalid task ID: must match pattern ^\\d+\\.\\d+(\\.\\d+)*$ or ^retro-\\d+$, got "${taskId}"`);
|
|
14282
14285
|
}
|
|
14283
14286
|
async function saveEvidence(directory, taskId, evidence) {
|
|
14284
14287
|
const sanitizedTaskId = sanitizeTaskId(taskId);
|
|
@@ -14488,13 +14491,14 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
|
14488
14491
|
}
|
|
14489
14492
|
return archived;
|
|
14490
14493
|
}
|
|
14491
|
-
var TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
14494
|
+
var TASK_ID_REGEX, RETRO_TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
14492
14495
|
var init_manager = __esm(() => {
|
|
14493
14496
|
init_zod();
|
|
14494
14497
|
init_evidence_schema();
|
|
14495
14498
|
init_utils2();
|
|
14496
14499
|
init_utils();
|
|
14497
|
-
TASK_ID_REGEX =
|
|
14500
|
+
TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
14501
|
+
RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
14498
14502
|
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
14499
14503
|
low: "simple",
|
|
14500
14504
|
medium: "moderate",
|
|
@@ -30959,7 +30963,10 @@ function serializeAgentSession(s) {
|
|
|
30959
30963
|
lastCompletedPhaseAgentsDispatched,
|
|
30960
30964
|
qaSkipCount: s.qaSkipCount ?? 0,
|
|
30961
30965
|
qaSkipTaskIds: s.qaSkipTaskIds ?? [],
|
|
30962
|
-
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map)
|
|
30966
|
+
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
|
|
30967
|
+
...s.scopeViolationDetected !== undefined && {
|
|
30968
|
+
scopeViolationDetected: s.scopeViolationDetected
|
|
30969
|
+
}
|
|
30963
30970
|
};
|
|
30964
30971
|
}
|
|
30965
30972
|
async function writeSnapshot(directory, state) {
|
|
@@ -34,8 +34,10 @@ 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 two 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
|
+
* Rejects: .., ../, null bytes, control characters, empty string, other non-numeric IDs
|
|
39
41
|
* @throws Error with descriptive message on failure
|
|
40
42
|
*/
|
|
41
43
|
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,13 @@ 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
|
+
throw new Error(`Invalid task ID: must match pattern ^\\d+\\.\\d+(\\.\\d+)*$ or ^retro-\\d+$, got "${taskId}"`);
|
|
15375
15378
|
}
|
|
15376
15379
|
async function saveEvidence(directory, taskId, evidence) {
|
|
15377
15380
|
const sanitizedTaskId = sanitizeTaskId(taskId);
|
|
@@ -15581,7 +15584,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
|
15581
15584
|
}
|
|
15582
15585
|
return archived;
|
|
15583
15586
|
}
|
|
15584
|
-
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
15587
|
+
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX, RETRO_TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
15585
15588
|
var init_manager = __esm(() => {
|
|
15586
15589
|
init_zod();
|
|
15587
15590
|
init_evidence_schema();
|
|
@@ -15601,7 +15604,8 @@ var init_manager = __esm(() => {
|
|
|
15601
15604
|
"build",
|
|
15602
15605
|
"quality_budget"
|
|
15603
15606
|
];
|
|
15604
|
-
TASK_ID_REGEX =
|
|
15607
|
+
TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
15608
|
+
RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
15605
15609
|
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
15606
15610
|
low: "simple",
|
|
15607
15611
|
medium: "moderate",
|
|
@@ -35895,6 +35899,7 @@ __export(exports_gate_evidence, {
|
|
|
35895
35899
|
recordGateEvidence: () => recordGateEvidence,
|
|
35896
35900
|
recordAgentDispatch: () => recordAgentDispatch,
|
|
35897
35901
|
readTaskEvidence: () => readTaskEvidence,
|
|
35902
|
+
isValidTaskId: () => isValidTaskId2,
|
|
35898
35903
|
hasPassedAllGates: () => hasPassedAllGates,
|
|
35899
35904
|
expandRequiredGates: () => expandRequiredGates,
|
|
35900
35905
|
deriveRequiredGates: () => deriveRequiredGates,
|
|
@@ -35902,8 +35907,21 @@ __export(exports_gate_evidence, {
|
|
|
35902
35907
|
});
|
|
35903
35908
|
import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "fs";
|
|
35904
35909
|
import * as path27 from "path";
|
|
35910
|
+
function isValidTaskId2(taskId) {
|
|
35911
|
+
if (!taskId)
|
|
35912
|
+
return false;
|
|
35913
|
+
if (taskId.includes(".."))
|
|
35914
|
+
return false;
|
|
35915
|
+
if (taskId.includes("/"))
|
|
35916
|
+
return false;
|
|
35917
|
+
if (taskId.includes("\\"))
|
|
35918
|
+
return false;
|
|
35919
|
+
if (taskId.includes("\x00"))
|
|
35920
|
+
return false;
|
|
35921
|
+
return TASK_ID_PATTERN.test(taskId);
|
|
35922
|
+
}
|
|
35905
35923
|
function assertValidTaskId(taskId) {
|
|
35906
|
-
if (!
|
|
35924
|
+
if (!isValidTaskId2(taskId)) {
|
|
35907
35925
|
throw new Error(`Invalid taskId: "${taskId}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3").`);
|
|
35908
35926
|
}
|
|
35909
35927
|
}
|
|
@@ -46050,7 +46068,10 @@ function serializeAgentSession(s) {
|
|
|
46050
46068
|
lastCompletedPhaseAgentsDispatched,
|
|
46051
46069
|
qaSkipCount: s.qaSkipCount ?? 0,
|
|
46052
46070
|
qaSkipTaskIds: s.qaSkipTaskIds ?? [],
|
|
46053
|
-
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map)
|
|
46071
|
+
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
|
|
46072
|
+
...s.scopeViolationDetected !== undefined && {
|
|
46073
|
+
scopeViolationDetected: s.scopeViolationDetected
|
|
46074
|
+
}
|
|
46054
46075
|
};
|
|
46055
46076
|
}
|
|
46056
46077
|
async function writeSnapshot(directory, state) {
|
|
@@ -52795,6 +52816,7 @@ function deserializeAgentSession(s) {
|
|
|
52795
52816
|
lastGateOutcome: null,
|
|
52796
52817
|
declaredCoderScope: null,
|
|
52797
52818
|
lastScopeViolation: null,
|
|
52819
|
+
scopeViolationDetected: s.scopeViolationDetected,
|
|
52798
52820
|
modifiedFilesThisCoderTask: []
|
|
52799
52821
|
};
|
|
52800
52822
|
}
|
|
@@ -53073,6 +53095,20 @@ init_create_tool();
|
|
|
53073
53095
|
import * as fs19 from "fs";
|
|
53074
53096
|
import * as path32 from "path";
|
|
53075
53097
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
53098
|
+
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
53099
|
+
function isValidTaskId3(taskId) {
|
|
53100
|
+
if (!taskId)
|
|
53101
|
+
return false;
|
|
53102
|
+
if (taskId.includes(".."))
|
|
53103
|
+
return false;
|
|
53104
|
+
if (taskId.includes("/"))
|
|
53105
|
+
return false;
|
|
53106
|
+
if (taskId.includes("\\"))
|
|
53107
|
+
return false;
|
|
53108
|
+
if (taskId.includes("\x00"))
|
|
53109
|
+
return false;
|
|
53110
|
+
return TASK_ID_PATTERN2.test(taskId);
|
|
53111
|
+
}
|
|
53076
53112
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
53077
53113
|
const normalizedWorkspace = path32.resolve(workspaceRoot);
|
|
53078
53114
|
const swarmPath = path32.join(normalizedWorkspace, ".swarm", "evidence");
|
|
@@ -53103,7 +53139,7 @@ function readEvidenceFile(evidencePath) {
|
|
|
53103
53139
|
var check_gate_status = createSwarmTool({
|
|
53104
53140
|
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
53141
|
args: {
|
|
53106
|
-
task_id: tool.schema.string().min(1).regex(/^\d+\.\d+(\.\d+)
|
|
53142
|
+
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
53143
|
},
|
|
53108
53144
|
async execute(args2, directory) {
|
|
53109
53145
|
let taskIdInput;
|
|
@@ -53125,8 +53161,7 @@ var check_gate_status = createSwarmTool({
|
|
|
53125
53161
|
};
|
|
53126
53162
|
return JSON.stringify(errorResult, null, 2);
|
|
53127
53163
|
}
|
|
53128
|
-
|
|
53129
|
-
if (!taskIdPattern.test(taskIdInput)) {
|
|
53164
|
+
if (!isValidTaskId3(taskIdInput)) {
|
|
53130
53165
|
const errorResult = {
|
|
53131
53166
|
taskId: taskIdInput,
|
|
53132
53167
|
status: "no_evidence",
|
|
@@ -53134,7 +53169,7 @@ var check_gate_status = createSwarmTool({
|
|
|
53134
53169
|
passed_gates: [],
|
|
53135
53170
|
missing_gates: [],
|
|
53136
53171
|
gates: {},
|
|
53137
|
-
message: `Invalid task_id format: "${taskIdInput}". Must match
|
|
53172
|
+
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
53173
|
};
|
|
53139
53174
|
return JSON.stringify(errorResult, null, 2);
|
|
53140
53175
|
}
|
|
@@ -53846,7 +53881,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
53846
53881
|
errors: ["Invalid working_directory: null bytes are not allowed"]
|
|
53847
53882
|
};
|
|
53848
53883
|
}
|
|
53849
|
-
|
|
53884
|
+
{
|
|
53850
53885
|
const devicePathPattern = /^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i;
|
|
53851
53886
|
if (devicePathPattern.test(args2.working_directory)) {
|
|
53852
53887
|
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.8",
|
|
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",
|