opencode-swarm 7.22.0 → 7.22.1

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
@@ -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.22.0",
37
+ version: "7.22.1",
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",
@@ -21023,9 +21023,10 @@ var init_guardrails = __esm(() => {
21023
21023
  function clearPendingCoderScope() {
21024
21024
  pendingCoderScopeByTaskId.clear();
21025
21025
  }
21026
- var pendingCoderScopeByTaskId;
21026
+ var pendingCoderScopeByTaskId, ACTIVE_PARALLEL_TASK_STATES;
21027
21027
  var init_delegation_gate = __esm(() => {
21028
21028
  init_schema();
21029
+ init_manager();
21029
21030
  init_state();
21030
21031
  init_telemetry();
21031
21032
  init_logger();
@@ -21034,6 +21035,12 @@ var init_delegation_gate = __esm(() => {
21034
21035
  init_normalize_tool_name();
21035
21036
  init_utils2();
21036
21037
  pendingCoderScopeByTaskId = new Map;
21038
+ ACTIVE_PARALLEL_TASK_STATES = new Set([
21039
+ "coder_delegated",
21040
+ "pre_check_passed",
21041
+ "reviewer_run",
21042
+ "tests_run"
21043
+ ]);
21037
21044
  });
21038
21045
 
21039
21046
  // src/state/agent-run-context.ts
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.22.0",
36
+ version: "7.22.1",
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",
@@ -26774,6 +26774,70 @@ function extractPlanTaskId(text) {
26774
26774
  function getSeedTaskId(session) {
26775
26775
  return session.currentTaskId ?? session.lastCoderDelegationTaskId;
26776
26776
  }
26777
+ function isTaskCompletedForParallelGuidance(task) {
26778
+ const status = task.status ?? "pending";
26779
+ return status === "completed" || status === "closed";
26780
+ }
26781
+ async function buildParallelExecutionGuidance(directory, sessionID, session) {
26782
+ if (!directory)
26783
+ return null;
26784
+ const plan = await loadPlanJsonOnly(directory);
26785
+ if (!plan) {
26786
+ return null;
26787
+ }
26788
+ const profile = plan.execution_profile;
26789
+ const enabled = profile?.parallelization_enabled === true;
26790
+ const maxConcurrent = profile?.max_concurrent_tasks ?? 1;
26791
+ if (!enabled || maxConcurrent <= 1)
26792
+ return null;
26793
+ if (hasActiveLeanTurbo(sessionID)) {
26794
+ return "[NEXT] Lean Turbo is active; use lean_turbo_run_phase and Lean Turbo lane guidance instead of standard execution-profile slot filling.";
26795
+ }
26796
+ const currentPhase = plan.current_phase !== undefined ? plan.phases.find((phase) => phase.id === plan.current_phase) : plan.phases.find((phase) => !isParallelGuidancePhaseComplete(phase));
26797
+ if (!currentPhase)
26798
+ return null;
26799
+ const tasks = currentPhase.tasks;
26800
+ if (tasks.length === 0)
26801
+ return null;
26802
+ const allTasks = plan.phases.flatMap((phase) => phase.tasks);
26803
+ const completed = new Set;
26804
+ for (const task of allTasks) {
26805
+ const taskId = task.id;
26806
+ if (isTaskCompletedForParallelGuidance(task))
26807
+ completed.add(taskId);
26808
+ if (getTaskState(session, taskId) === "complete")
26809
+ completed.add(taskId);
26810
+ }
26811
+ const occupied = new Set;
26812
+ for (const task of allTasks) {
26813
+ const taskId = task.id;
26814
+ if (task.status === "in_progress")
26815
+ occupied.add(taskId);
26816
+ const state = getTaskState(session, taskId);
26817
+ if (ACTIVE_PARALLEL_TASK_STATES.has(state))
26818
+ occupied.add(taskId);
26819
+ }
26820
+ const availableSlots = Math.max(0, maxConcurrent - occupied.size);
26821
+ if (availableSlots <= 0) {
26822
+ return `[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${maxConcurrent}; all standard execution slots are occupied. Continue current active task gates before starting more coder work.`;
26823
+ }
26824
+ const eligible = tasks.filter((task) => {
26825
+ const taskId = task.id;
26826
+ const status = task.status ?? "pending";
26827
+ if (status !== "pending")
26828
+ return false;
26829
+ if (occupied.has(taskId))
26830
+ return false;
26831
+ return task.depends.every((dep) => completed.has(dep));
26832
+ }).map((task) => task.id).slice(0, availableSlots);
26833
+ if (eligible.length === 0) {
26834
+ return `[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${maxConcurrent}; no dependency-ready pending tasks are available for a new coder slot. Continue the current task/gate.`;
26835
+ }
26836
+ return `[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${maxConcurrent}; ${occupied.size} slot(s) occupied. Eligible now: ${eligible.join(", ")}. [NEXT] dispatch up to ${availableSlots} eligible coder task(s) before waiting; preserve ONE task per coder call and call declare_scope for each task.`;
26837
+ }
26838
+ function isParallelGuidancePhaseComplete(phase) {
26839
+ return phase.status === "complete" || phase.status === "completed" || phase.status === "closed";
26840
+ }
26777
26841
  async function getEvidenceTaskId(session, directory) {
26778
26842
  const primary = session.currentTaskId ?? session.lastCoderDelegationTaskId;
26779
26843
  if (primary)
@@ -27279,15 +27343,16 @@ ${trimComment}${after}`;
27279
27343
  if (!/^[a-zA-Z0-9_-]{1,128}$/.test(deliberationSessionID)) {} else {
27280
27344
  const deliberationSession = ensureAgentSession(deliberationSessionID);
27281
27345
  const lastGate = deliberationSession.lastGateOutcome;
27346
+ const parallelGuidance = await buildParallelExecutionGuidance(directory, deliberationSessionID, deliberationSession);
27282
27347
  let guidance;
27283
27348
  if (lastGate?.taskId) {
27284
27349
  const gateResult = lastGate.passed ? "PASSED" : "FAILED";
27285
27350
  const sanitizedGate = lastGate.gate.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\[ \]/g, "()").replace(/\[/g, "(").replace(/\]/g, ")").replace(/[\r\n]/g, " ").slice(0, 64);
27286
27351
  const sanitizedTaskId = lastGate.taskId.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\[/g, "(").replace(/\]/g, ")").replace(/[\r\n]/g, " ").slice(0, 32);
27287
27352
  guidance = `[Last gate: ${sanitizedGate} ${gateResult} for task ${sanitizedTaskId}]
27288
- [NEXT] Execute the next gate for the current task.`;
27353
+ ${parallelGuidance ?? "[NEXT] Execute the next gate for the current task."}`;
27289
27354
  } else {
27290
- guidance = "[NEXT] Begin the first plan task and run gates sequentially.";
27355
+ guidance = parallelGuidance ?? "[NEXT] Begin the first plan task and run gates sequentially.";
27291
27356
  }
27292
27357
  const systemMsgIdx = messages.findIndex((m) => m && m.info?.role === "system");
27293
27358
  const insertIdx = systemMsgIdx >= 0 ? systemMsgIdx + 1 : 0;
@@ -27380,9 +27445,10 @@ ${warningLines.join(`
27380
27445
  toolAfter
27381
27446
  };
27382
27447
  }
27383
- var pendingCoderScopeByTaskId;
27448
+ var pendingCoderScopeByTaskId, ACTIVE_PARALLEL_TASK_STATES;
27384
27449
  var init_delegation_gate = __esm(() => {
27385
27450
  init_schema();
27451
+ init_manager();
27386
27452
  init_state();
27387
27453
  init_telemetry();
27388
27454
  init_logger();
@@ -27391,6 +27457,12 @@ var init_delegation_gate = __esm(() => {
27391
27457
  init_normalize_tool_name();
27392
27458
  init_utils2();
27393
27459
  pendingCoderScopeByTaskId = new Map;
27460
+ ACTIVE_PARALLEL_TASK_STATES = new Set([
27461
+ "coder_delegated",
27462
+ "pre_check_passed",
27463
+ "reviewer_run",
27464
+ "tests_run"
27465
+ ]);
27394
27466
  });
27395
27467
 
27396
27468
  // src/state/agent-run-context.ts
@@ -62853,6 +62925,8 @@ If a tool modifies a file, it is a CODER tool. Delegate.
62853
62925
  - Rationale: declare_scope persists the allowed set to disk (.swarm/scopes/scope-\${taskId}.json) so it survives cross-process delegation. Without a call, the coder process reads an empty scope and every Edit/Write is denied.
62854
62926
  <!-- BEHAVIORAL_GUIDANCE_END -->
62855
62927
  2. ONE agent per message. Send, STOP, wait for response.
62928
+ Exception: Stage B reviewer/test_engineer gate agents for the SAME completed coder task may be dispatched together before waiting when both gates are required.
62929
+ This exception NEVER applies to coder delegations. Preserve ONE task per coder call.
62856
62930
  3. ONE task per {{AGENT_PREFIX}}coder call. Never batch.
62857
62931
  3a. PRE-DELEGATION SCOPE CALL (required): BEFORE every {{AGENT_PREFIX}}coder delegation, you MUST call \`declare_scope\` with { taskId, files } listing the exact file(s) this task will modify (including generated/lockfile paths). No \`declare_scope\` call → no coder delegation. See Rule 1a.
62858
62932
  <!-- BEHAVIORAL_GUIDANCE_START -->
@@ -62993,7 +63067,7 @@ VERIFICATION PROTOCOL: After the coder reports DONE, and before running Stage B
62993
63067
  The reviewer's verdict MUST include a REUSE_RE_VERIFICATION field — do NOT accept an APPROVED verdict without it. Validate the field value against context: if the coder's EXPORTS_ADDED was non-empty, REUSE_RE_VERIFICATION must be VERIFIED or DUPLICATION_DETECTED (not SKIPPED). If EXPORTS_ADDED was "none", REUSE_RE_VERIFICATION must be SKIPPED.
62994
63068
  Stage B runs by default for TIER 1-3 classifications. Stage A passing does not satisfy Stage B.
62995
63069
  Stage B is where logic errors, security flaws, edge cases, and behavioral bugs are caught.
62996
- You MUST delegate to each Stage B agent and wait for their response.
63070
+ You MUST delegate to each required Stage B agent. For the standard reviewer + test_engineer pair, dispatch both before waiting so Stage B actually runs in parallel.
62997
63071
 
62998
63072
  Stage B (reviewer + test_engineer) **always runs per-task** regardless of council mode — it is never replaced, never omitted, never deferred. When \`council_mode\` is enabled in the QA gate profile, a **phase-level** council review is additionally required before calling \`phase_complete\`: dispatch all 5 council members, collect their verdicts, call \`submit_phase_council_verdicts\`, then call \`phase_complete\` (Gate 5 validates the resulting \`phase-council.json\` evidence). Stage A (\`pre_check_batch\`) still runs as the pre-review gate for each task.
62999
63073
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.22.0",
3
+ "version": "7.22.1",
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",