opencode-swarm 6.25.6 → 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 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 (!TASK_ID_REGEX.test(taskId)) {
14279
- throw new Error(`Invalid task ID: must match pattern ^[\\w-]+(\\.[\\w-]+)*$, got "${taskId}"`);
14278
+ if (TASK_ID_REGEX.test(taskId)) {
14279
+ return taskId;
14280
14280
  }
14281
- return taskId;
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 = /^[\w-]+(\.[\w-]+)*$/;
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
- * Must match regex ^[\w-]+(\.[\w-]+)*$
38
- * Rejects: .., ../, null bytes, control characters, empty string
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;
@@ -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 (!TASK_ID_REGEX.test(taskId)) {
15372
- throw new Error(`Invalid task ID: must match pattern ^[\\w-]+(\\.[\\w-]+)*$, got "${taskId}"`);
15371
+ if (TASK_ID_REGEX.test(taskId)) {
15372
+ return taskId;
15373
15373
  }
15374
- return taskId;
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 = /^[\w-]+(\.[\w-]+)*$/;
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 (!taskId || taskId.includes("..") || taskId.includes("/") || taskId.includes("\\") || taskId.includes("\x00") || !TASK_ID_PATTERN.test(taskId)) {
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+)?$/, "Task ID must be in N.M or N.M.P format").describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")')
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
- const taskIdPattern = /^\d+\.\d+(\.\d+)?$/;
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 pattern N.M or N.M.P (e.g., "1.1", "1.2.3")`
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
- if (process.platform === "win32") {
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.6",
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",