opencode-swarm 6.41.1 → 6.41.2

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
@@ -32643,7 +32643,7 @@ async function executeWriteRetro(args, directory) {
32643
32643
  var write_retro = createSwarmTool({
32644
32644
  description: "Write a retrospective evidence bundle for a completed phase. " + "Accepts flat retro fields and writes a correctly-wrapped EvidenceBundle to " + ".swarm/evidence/retro-{phase}/evidence.json. " + "Use this instead of manually writing retro JSON to avoid schema validation failures in phase_complete.",
32645
32645
  args: {
32646
- phase: tool.schema.number().int().positive().max(99).describe("The phase number being completed (e.g., 1, 2, 3)"),
32646
+ phase: tool.schema.number().int().min(1).max(99).describe("The phase number being completed (e.g., 1, 2, 3)"),
32647
32647
  summary: tool.schema.string().describe("Human-readable summary of the phase"),
32648
32648
  task_count: tool.schema.number().int().min(1).max(9999).describe("Count of tasks completed in this phase"),
32649
32649
  task_complexity: tool.schema.enum(["trivial", "simple", "moderate", "complex"]).describe("Complexity level of the completed tasks"),
package/dist/index.js CHANGED
@@ -47074,7 +47074,7 @@ async function executeWriteRetro(args2, directory) {
47074
47074
  var write_retro = createSwarmTool({
47075
47075
  description: "Write a retrospective evidence bundle for a completed phase. " + "Accepts flat retro fields and writes a correctly-wrapped EvidenceBundle to " + ".swarm/evidence/retro-{phase}/evidence.json. " + "Use this instead of manually writing retro JSON to avoid schema validation failures in phase_complete.",
47076
47076
  args: {
47077
- phase: tool.schema.number().int().positive().max(99).describe("The phase number being completed (e.g., 1, 2, 3)"),
47077
+ phase: tool.schema.number().int().min(1).max(99).describe("The phase number being completed (e.g., 1, 2, 3)"),
47078
47078
  summary: tool.schema.string().describe("Human-readable summary of the phase"),
47079
47079
  task_count: tool.schema.number().int().min(1).max(9999).describe("Count of tasks completed in this phase"),
47080
47080
  task_complexity: tool.schema.enum(["trivial", "simple", "moderate", "complex"]).describe("Complexity level of the completed tasks"),
@@ -57676,6 +57676,19 @@ function parseFilePaths(description, filesTouched) {
57676
57676
  }
57677
57677
  return filePaths;
57678
57678
  }
57679
+ function buildVerifySummary(tasksChecked, tasksSkipped, tasksBlocked) {
57680
+ if (tasksBlocked > 0) {
57681
+ return `Blocked: ${tasksBlocked} task(s) with missing identifiers`;
57682
+ }
57683
+ const verified = tasksChecked - tasksSkipped;
57684
+ if (tasksSkipped === tasksChecked) {
57685
+ return `All ${tasksChecked} completed task(s) skipped \u2014 research/inventory tasks`;
57686
+ }
57687
+ if (tasksSkipped > 0) {
57688
+ return `${verified} task(s) verified, ${tasksSkipped} skipped (research tasks)`;
57689
+ }
57690
+ return `All ${tasksChecked} completed tasks verified successfully`;
57691
+ }
57679
57692
  async function executeCompletionVerify(args2, directory) {
57680
57693
  const phase = Number(args2.phase);
57681
57694
  if (Number.isNaN(phase) || phase < 1 || !Number.isFinite(phase)) {
@@ -57737,7 +57750,7 @@ async function executeCompletionVerify(args2, directory) {
57737
57750
  return JSON.stringify(result2, null, 2);
57738
57751
  }
57739
57752
  let tasksChecked = 0;
57740
- const tasksSkipped = 0;
57753
+ let tasksSkipped = 0;
57741
57754
  let tasksBlocked = 0;
57742
57755
  const blockedTasks = [];
57743
57756
  for (const task of targetPhase.tasks) {
@@ -57748,13 +57761,7 @@ async function executeCompletionVerify(args2, directory) {
57748
57761
  const fileTargets = parseFilePaths(task.description, task.files_touched);
57749
57762
  const identifiers = parseIdentifiers(task.description);
57750
57763
  if (fileTargets.length === 0) {
57751
- blockedTasks.push({
57752
- task_id: task.id,
57753
- identifier: "",
57754
- file_path: "",
57755
- reason: "No file targets \u2014 cannot verify completion without files_touched"
57756
- });
57757
- tasksBlocked++;
57764
+ tasksSkipped++;
57758
57765
  continue;
57759
57766
  }
57760
57767
  if (identifiers.length === 0) {
@@ -57772,6 +57779,19 @@ async function executeCompletionVerify(args2, directory) {
57772
57779
  for (const filePath of fileTargets) {
57773
57780
  const normalizedPath = filePath.replace(/\\/g, "/");
57774
57781
  const resolvedPath = path45.resolve(directory, normalizedPath);
57782
+ const projectRoot = path45.resolve(directory);
57783
+ const relative6 = path45.relative(projectRoot, resolvedPath);
57784
+ const withinProject = relative6 === "" || !relative6.startsWith("..") && !path45.isAbsolute(relative6);
57785
+ if (!withinProject) {
57786
+ blockedTasks.push({
57787
+ task_id: task.id,
57788
+ identifier: "",
57789
+ file_path: filePath,
57790
+ reason: `File path '${filePath}' escapes the project directory \u2014 cannot verify completion`
57791
+ });
57792
+ hasFileReadFailure = true;
57793
+ continue;
57794
+ }
57775
57795
  let fileContent;
57776
57796
  try {
57777
57797
  fileContent = fs33.readFileSync(resolvedPath, "utf-8");
@@ -57830,7 +57850,7 @@ async function executeCompletionVerify(args2, directory) {
57830
57850
  timestamp: now,
57831
57851
  agent: "completion_verify",
57832
57852
  verdict: tasksBlocked === 0 ? "pass" : "fail",
57833
- summary: tasksBlocked === 0 ? `All ${tasksChecked} completed tasks verified successfully` : `Blocked: ${tasksBlocked} task(s) with missing identifiers`,
57853
+ summary: buildVerifySummary(tasksChecked, tasksSkipped, tasksBlocked),
57834
57854
  phase,
57835
57855
  tasks_checked: tasksChecked,
57836
57856
  tasks_skipped: tasksSkipped,
@@ -61509,7 +61529,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
61509
61529
  var phase_complete = createSwarmTool({
61510
61530
  description: "Mark a phase as complete and track which agents were dispatched. Used for phase completion gating and tracking. Accepts phase number and optional summary. Returns list of agents that were dispatched.",
61511
61531
  args: {
61512
- phase: tool.schema.number().describe("The phase number being completed (e.g., 1, 2, 3)"),
61532
+ phase: tool.schema.number().int().min(1).describe("The phase number being completed \u2014 a positive integer (e.g., 1, 2, 3)"),
61513
61533
  summary: tool.schema.string().optional().describe("Optional summary of what was accomplished in this phase"),
61514
61534
  sessionID: tool.schema.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)")
61515
61535
  },
@@ -64047,13 +64067,13 @@ function validatePath(inputPath, baseDir, workspaceDir) {
64047
64067
  resolved = path56.resolve(baseDir, inputPath);
64048
64068
  }
64049
64069
  const workspaceResolved = path56.resolve(workspaceDir);
64050
- let relative7;
64070
+ let relative8;
64051
64071
  if (isWinAbs) {
64052
- relative7 = path56.win32.relative(workspaceResolved, resolved);
64072
+ relative8 = path56.win32.relative(workspaceResolved, resolved);
64053
64073
  } else {
64054
- relative7 = path56.relative(workspaceResolved, resolved);
64074
+ relative8 = path56.relative(workspaceResolved, resolved);
64055
64075
  }
64056
- if (relative7.startsWith("..")) {
64076
+ if (relative8.startsWith("..")) {
64057
64077
  return "path traversal detected";
64058
64078
  }
64059
64079
  return null;
@@ -64962,7 +64982,7 @@ async function executeSavePlan(args2, fallbackDir) {
64962
64982
  success: false,
64963
64983
  message: "Plan rejected: invalid phase or task IDs",
64964
64984
  errors: validationErrors,
64965
- recovery_guidance: "Use save_plan with corrected inputs to create or restructure plans. Never write .swarm/plan.json or .swarm/plan.md directly."
64985
+ recovery_guidance: "Phase IDs must be positive integers: 1, 2, 3 (not 0, -1, or decimals). " + 'Task IDs must use N.M format: "1.1", "2.3", "3.1". ' + "Call save_plan again with corrected ids. " + "Never write .swarm/plan.json or .swarm/plan.md directly."
64966
64986
  };
64967
64987
  }
64968
64988
  const placeholderIssues = detectPlaceholderContent(args2);
@@ -65075,7 +65095,7 @@ var save_plan = createSwarmTool({
65075
65095
  title: tool.schema.string().min(1).describe("Plan title \u2014 the REAL project name from the spec. NOT a placeholder like [Project]."),
65076
65096
  swarm_id: tool.schema.string().min(1).describe('Swarm identifier (e.g. "mega")'),
65077
65097
  phases: tool.schema.array(tool.schema.object({
65078
- id: tool.schema.number().int().positive().describe("Phase number, starting at 1"),
65098
+ id: tool.schema.number().int().min(1).describe("Phase number \u2014 a positive integer starting at 1. Use 1, 2, 3, etc."),
65079
65099
  name: tool.schema.string().min(1).describe("Descriptive phase name derived from the spec"),
65080
65100
  tasks: tool.schema.array(tool.schema.object({
65081
65101
  id: tool.schema.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/, 'Task ID must be in N.M format, e.g. "1.1"').describe('Task ID in N.M format, e.g. "1.1", "2.3"'),
@@ -67658,7 +67678,7 @@ async function executeWriteDriftEvidence(args2, directory) {
67658
67678
  var write_drift_evidence = createSwarmTool({
67659
67679
  description: "Write drift verification evidence for a completed phase. " + "Normalizes verdict (APPROVED->approved, NEEDS_REVISION->rejected) and writes " + "a gate-contract formatted EvidenceBundle to .swarm/evidence/{phase}/drift-verifier.json. " + "Use this after critic_drift_verifier delegation to persist the verification result.",
67660
67680
  args: {
67661
- phase: tool.schema.number().int().positive().describe("The phase number for the drift verification"),
67681
+ phase: tool.schema.number().int().min(1).describe("The phase number for the drift verification (e.g., 1, 2, 3)"),
67662
67682
  verdict: tool.schema.enum(["APPROVED", "NEEDS_REVISION"]).describe("Verdict of the drift verification: 'APPROVED' or 'NEEDS_REVISION'"),
67663
67683
  summary: tool.schema.string().describe("Human-readable summary of the drift verification")
67664
67684
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.41.1",
3
+ "version": "6.41.2",
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",